This commit is contained in:
2024-07-20 07:50:41 +08:00
parent 5221e5a59f
commit 2f4ae442e1
2 changed files with 124 additions and 16 deletions

View File

@@ -66,15 +66,16 @@ impl Config {
match self.get(s) { match self.get(s) {
Some(e) => match e { Some(e) => match e {
Yaml::String(s) => Some(vec![s.to_owned()]), Yaml::String(s) => Some(vec![s.to_owned()]),
Yaml::Array(s) => Some(s Yaml::Array(s) => Some(
.iter() s.iter()
.filter_map(|s| match s { .filter_map(|s| match s {
Yaml::String(s) => Some(s.to_owned()), Yaml::String(s) => Some(s.to_owned()),
Yaml::Integer(i) => Some(i.to_string()), Yaml::Integer(i) => Some(i.to_string()),
Yaml::Real(i) => Some(i.to_owned()), Yaml::Real(i) => Some(i.to_owned()),
_ => None, _ => None,
}) })
.collect()), .collect(),
),
_ => None, _ => None,
}, },
None => None, None => None,
@@ -83,7 +84,10 @@ impl Config {
pub fn game_backuper_cfg(&self) -> Option<String> { pub fn game_backuper_cfg(&self) -> Option<String> {
let mut pb = crate::utils::get_exe_path_else_current(); let mut pb = crate::utils::get_exe_path_else_current();
pb.push(self.get_str("game_backuper_cfg").unwrap_or("game_backuper.yml")); pb.push(
self.get_str("game_backuper_cfg")
.unwrap_or("game_backuper.yml"),
);
if !pb.exists() { if !pb.exists() {
return None; return None;
} }
@@ -110,10 +114,33 @@ impl Config {
} }
pub fn pause_at_exit(&self) -> bool { pub fn pause_at_exit(&self) -> bool {
self.get_bool("pause_at_exit").map(|s| s.to_owned()).unwrap_or(false) self.get_bool("pause_at_exit")
.map(|s| s.to_owned())
.unwrap_or(false)
} }
pub fn pause_on_backup_error(&self) -> bool { pub fn pause_on_backup_error(&self) -> bool {
self.get_bool("pause_on_backup_error").map(|s| s.to_owned()).unwrap_or(false) self.get_bool("pause_on_backup_error")
.map(|s| s.to_owned())
.unwrap_or(false)
}
pub fn rclone_exe(&self) -> String {
match self.get_str("rclone_exe") {
Some(s) => s.to_owned(),
None => String::from("game-backuper"),
}
}
pub fn rclone_remote(&self) -> Option<&str> {
self.get_str("rclone_remote")
}
pub fn rclone_local(&self) -> Option<&str> {
self.get_str("rclone_local")
}
pub fn rclone_flag(&self) -> Vec<String> {
self.get_str_vec("rclone_flag").unwrap_or(vec![])
} }
} }

View File

@@ -23,13 +23,19 @@ enum Error {
struct Main { struct Main {
_cfg: cfg::Config, _cfg: cfg::Config,
_dryrun: bool, _dryrun: bool,
_rclone_enable: bool,
_skip_restore: bool,
_backup_only: bool,
} }
impl Main { impl Main {
fn new(cfg: cfg::Config, dryrun: bool) -> Self { fn new(cfg: cfg::Config, dryrun: bool, skip_restore: bool, backup_only: bool) -> Self {
Self { Self {
_rclone_enable: cfg.rclone_remote().is_some() && cfg.rclone_local().is_some(),
_cfg: cfg, _cfg: cfg,
_dryrun: dryrun, _dryrun: dryrun,
_skip_restore: skip_restore,
_backup_only: backup_only,
} }
} }
@@ -57,6 +63,40 @@ impl Main {
}; };
if !ok { if !ok {
println!("Backup failed: {:?}.", e); println!("Backup failed: {:?}.", e);
if self._rclone_enable {
if !utils::ask_continue() {
return Err(Error::Exited);
}
return Ok(());
}
return Err(Error::Exited);
}
Ok(())
}
}
fn backup_rclone(&self) -> Result<(), Error> {
let mut cml = vec![self._cfg.rclone_exe(), String::from("sync")];
cml.push(self._cfg.rclone_local().unwrap().to_owned());
cml.push(self._cfg.rclone_remote().unwrap().to_owned());
cml.extend_from_slice(&self._cfg.rclone_flag());
if self._dryrun {
println!("Rclone backup command line: {:?}", cml);
Ok(())
} else {
let e = Self::call(cml)?;
let ok = match &e {
ExitStatus::Exited(c) => *c == 0,
_ => false,
};
if !ok {
println!("Rclone backup failed: {:?}.", e);
if self._rclone_enable {
if !utils::ask_continue() {
return Err(Error::Exited);
}
return Ok(());
}
return Err(Error::Exited); return Err(Error::Exited);
} }
Ok(()) Ok(())
@@ -100,10 +140,44 @@ impl Main {
} }
} }
fn restore_rclone(&self) -> Result<(), Error> {
let mut cml = vec![self._cfg.rclone_exe(), String::from("sync")];
cml.push(self._cfg.rclone_remote().unwrap().to_owned());
cml.push(self._cfg.rclone_local().unwrap().to_owned());
cml.extend_from_slice(&self._cfg.rclone_flag());
if self._dryrun {
println!("Rclone restore command line: {:?}", cml);
Ok(())
} else {
let e = Self::call(cml)?;
let ok = match &e {
ExitStatus::Exited(c) => *c == 0,
_ => false,
};
if !ok {
println!("Rclone restore failed: {:?}.", e);
if !utils::ask_continue() {
return Err(Error::Exited);
}
}
Ok(())
}
}
fn run(&self) -> Result<(), Error> { fn run(&self) -> Result<(), Error> {
self.restore()?; if !self._skip_restore && !self._backup_only {
self.run_exe()?; if self._rclone_enable {
self.restore_rclone()?;
}
self.restore()?;
}
if !self._backup_only {
self.run_exe()?;
}
self.backup()?; self.backup()?;
if self._rclone_enable {
self.backup_rclone()?;
}
Ok(()) Ok(())
} }
@@ -135,6 +209,8 @@ fn main() -> ExitCode {
opts.optflag("h", "help", "Print help message."); opts.optflag("h", "help", "Print help message.");
opts.optopt("c", "config", "The location of config file.", "FILE"); opts.optopt("c", "config", "The location of config file.", "FILE");
opts.optflag("d", "dryrun", "Run without calling any process."); opts.optflag("d", "dryrun", "Run without calling any process.");
opts.optflag("r", "skip-restore", "Skip restore backup.");
opts.optflag("b", "backup-only", "Backup only.");
let result = match opts.parse(&argv[1..]) { let result = match opts.parse(&argv[1..]) {
Ok(m) => m, Ok(m) => m,
Err(err) => { Err(err) => {
@@ -162,7 +238,12 @@ fn main() -> ExitCode {
println!("game_exe need be set."); println!("game_exe need be set.");
return ExitCode::from(1); return ExitCode::from(1);
} }
let m = Main::new(cfg, result.opt_present("d")); let m = Main::new(
cfg,
result.opt_present("d"),
result.opt_present("r"),
result.opt_present("b"),
);
let e = match m.run() { let e = match m.run() {
Ok(_) => 0, Ok(_) => 0,
Err(e) => { Err(e) => {