diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bc664f..8bf1ea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,15 @@ but don't have a good way to check the registry keys directly. * CLI: The `find` command now supports `--fuzzy` and `--multiple` options. This is also available for the `api` command's `findTitle` request. + * CLI: The `wrap` command now supports several options from the `backup` command: + `--path`, + `--format`, + `--compression`, + `--compression-level`, + `--full-limit`, + `--differential-limit`, + `--cloud-sync`, + `--no-cloud-sync`. * Changed: * When the game list is filtered, the summary line (e.g., "1 of 10 games") now reflects the filtered totals. diff --git a/src/cli.rs b/src/cli.rs index d017dcb..1fae55c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -871,6 +871,14 @@ pub fn run(sub: Subcommand, no_manifest_update: bool, try_manifest_update: bool) name_source, force, gui, + path, + format, + compression, + compression_level, + full_limit, + differential_limit, + cloud_sync, + no_cloud_sync, commands, } => { let manifest = load_manifest(&config, &mut cache, no_manifest_update, try_manifest_update)?; @@ -959,20 +967,20 @@ pub fn run(sub: Subcommand, no_manifest_update: bool, try_manifest_update: bool) Subcommand::Restore { games: vec![game_name.clone()], force: true, - preview: Default::default(), - path: Default::default(), + preview, + path: path.clone(), api: Default::default(), gui: Default::default(), sort: Default::default(), backup: Default::default(), - cloud_sync: Default::default(), - no_cloud_sync: Default::default(), + cloud_sync, + no_cloud_sync, dump_registry: Default::default(), }, no_manifest_update, try_manifest_update, ) { - log::error!("WRAP::restore: failed for game {:?} with: {:?}", wrap_game_info, err); + log::error!("Wrap failed to restore game {:?} with: {:?}", wrap_game_info, err); ui::alert_with_error(gui, force, &TRANSLATOR.restore_one_game_failed(game_name), &err)?; return Err(err); } @@ -983,10 +991,10 @@ pub fn run(sub: Subcommand, no_manifest_update: bool, try_manifest_update: bool) let result = Command::new(&commands[0]).args(&commands[1..]).status(); match result { Ok(status) => { - log::debug!("WRAP::execute: Game command executed, returning status: {:#?}", status); + log::debug!("Wrapped game command executed, returning status: {:#?}", status); } Err(err) => { - log::error!("WRAP::execute: Game command execution failed with: {:#?}", err); + log::error!("Wrapped game command execution failed with: {:#?}", err); ui::alert_with_raw_error(gui, force, &TRANSLATOR.game_did_not_launch(), &err.to_string())?; return Err(Error::GameDidNotLaunch { why: err.to_string() }); } @@ -1006,25 +1014,25 @@ pub fn run(sub: Subcommand, no_manifest_update: bool, try_manifest_update: bool) Subcommand::Backup { games: vec![game_name.clone()], force: true, - preview: Default::default(), - path: Default::default(), + preview, + path, wine_prefix: Default::default(), api: Default::default(), gui: Default::default(), sort: Default::default(), - format: Default::default(), - compression: Default::default(), - compression_level: Default::default(), - full_limit: Default::default(), - differential_limit: Default::default(), - cloud_sync: Default::default(), - no_cloud_sync: Default::default(), + format, + compression, + compression_level, + full_limit, + differential_limit, + cloud_sync, + no_cloud_sync, dump_registry: Default::default(), }, no_manifest_update, try_manifest_update, ) { - log::error!("WRAP::backup: failed with: {:#?}", err); + log::error!("Wrap failed to back up with: {:#?}", err); ui::alert_with_error(gui, force, &TRANSLATOR.back_up_one_game_failed(game_name), &err)?; return Err(err); } diff --git a/src/cli/parse.rs b/src/cli/parse.rs index 2bde302..b3c8cbb 100644 --- a/src/cli/parse.rs +++ b/src/cli/parse.rs @@ -400,6 +400,52 @@ pub enum Subcommand { #[clap(long)] gui: bool, + /// Directory in which to find/store backups. + /// It will be created if it does not already exist. + /// When not specified, this defers to the config file. + #[clap(long, value_parser = parse_strict_path)] + path: Option, + + /// Format in which to store new backups. + /// When not specified, this defers to the config file. + #[clap(long, value_parser = possible_values!(BackupFormat, ALL_NAMES))] + format: Option, + + /// Compression method to use for new zip backups. + /// When not specified, this defers to the config file. + #[clap(long, value_parser = possible_values!(ZipCompression, ALL_NAMES))] + compression: Option, + + /// Compression level to use for new zip backups. + /// When not specified, this defers to the config file. + /// Valid ranges: 1 to 9 for deflate/bzip2, -7 to 22 for zstd. + #[clap(long, allow_hyphen_values(true))] + compression_level: Option, + + /// Maximum number of full backups to retain per game. + /// Must be between 1 and 255 (inclusive). + /// When not specified, this defers to the config file. + #[clap(long)] + full_limit: Option, + + /// Maximum number of differential backups to retain per full backup. + /// Must be between 0 and 255 (inclusive). + /// When not specified, this defers to the config file. + #[clap(long)] + differential_limit: Option, + + /// Upload any changes to the cloud when the backup is complete. + /// If the local and cloud backups are not in sync to begin with, + /// then nothing will be uploaded. + /// When not specified, this defers to the config file. + #[clap(long)] + cloud_sync: bool, + + /// Don't perform any cloud checks or synchronization. + /// When not specified, this defers to the config file. + #[clap(long, conflicts_with("cloud_sync"))] + no_cloud_sync: bool, + /// Commands to launch the game. /// Use `--` first to separate these from the `wrap` options; /// e.g., `ludusavi wrap --name foo -- foo.exe --windowed`.