From 8eeed5fb83f58ca9f321892e036d955eb4b0b76e Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Wed, 17 Aug 2022 20:34:23 +0200 Subject: [PATCH] improve help usage --- src/backend/ignore.rs | 4 +- src/commands/backup.rs | 5 ++- src/commands/cat.rs | 11 ++++-- src/commands/check.rs | 4 +- src/commands/config.rs | 22 ++++++----- src/commands/diff.rs | 4 +- src/commands/forget.rs | 49 ++++++++++++----------- src/commands/init.rs | 4 +- src/commands/key.rs | 17 ++++---- src/commands/list.rs | 2 +- src/commands/ls.rs | 2 +- src/commands/mod.rs | 62 ++++++++++++++++++++--------- src/commands/prune.rs | 45 +++++++++++---------- src/commands/restore.rs | 40 ++++++++++--------- src/commands/snapshots.rs | 8 ++-- src/commands/tag.rs | 83 +++++++++++++++++++++++++-------------- src/repo/snapshotfile.rs | 4 +- 17 files changed, 216 insertions(+), 150 deletions(-) diff --git a/src/backend/ignore.rs b/src/backend/ignore.rs index de9512b..7ef56eb 100644 --- a/src/backend/ignore.rs +++ b/src/backend/ignore.rs @@ -31,11 +31,11 @@ pub struct LocalSourceOptions { #[clap(long, short = 'g')] glob: Vec, - /// Read glob patterns to exclude/include from a file (can be specified multiple times) + /// Read glob patterns to exclude/include from this file (can be specified multiple times) #[clap(long, value_name = "FILE")] glob_file: Vec, - /// Exclude contents of directories containing filename (can be specified multiple times) + /// Exclude contents of directories containing this filename (can be specified multiple times) #[clap(long, value_name = "FILE")] exclude_if_present: Vec, diff --git a/src/commands/backup.rs b/src/commands/backup.rs index 8a80088..eef0d0a 100644 --- a/src/commands/backup.rs +++ b/src/commands/backup.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use anyhow::{anyhow, Result}; use chrono::{Duration, Local}; -use clap::Parser; +use clap::{AppSettings, Parser}; use gethostname::gethostname; use path_absolutize::*; use vlog::*; @@ -17,6 +17,7 @@ use crate::index::IndexBackend; use crate::repo::{ConfigFile, DeleteOption, SnapshotFile, SnapshotSummary, StringList}; #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(super) struct Opts { /// Do not upload or write any data, just show what would be done #[clap(long, short = 'n')] @@ -45,7 +46,7 @@ pub(super) struct Opts { #[clap(flatten)] ignore_opts: LocalSourceOptions, - /// backup source + /// Backup source source: String, } diff --git a/src/commands/cat.rs b/src/commands/cat.rs index 08e4dcd..3e808c2 100644 --- a/src/commands/cat.rs +++ b/src/commands/cat.rs @@ -19,24 +19,29 @@ pub(super) struct Opts { #[derive(Subcommand)] enum Command { + /// Display a tree blob TreeBlob(IdOpt), + /// Display a data blob DataBlob(IdOpt), + /// Display the config file Config, + /// Display an index file Index(IdOpt), + /// Display a snapshot file Snapshot(IdOpt), - /// display a tree within a snapshot + /// Display a tree within a snapshot Tree(TreeOpts), } #[derive(Default, Parser)] struct IdOpt { - /// id to cat + /// Id to display id: String, } #[derive(Parser)] struct TreeOpts { - /// snapshot/path to restore + /// Snapshot/path of the tree to display #[clap(value_name = "SNAPSHOT[:PATH]")] snap: String, } diff --git a/src/commands/check.rs b/src/commands/check.rs index c821ef6..fa31a50 100644 --- a/src/commands/check.rs +++ b/src/commands/check.rs @@ -14,11 +14,11 @@ use crate::repo::{IndexFile, IndexPack, SnapshotFile}; #[derive(Parser)] pub(super) struct Opts { - /// don't verify the data saved in the cache + /// Don't verify the data saved in the cache #[clap(long, conflicts_with = "no-cache")] trust_cache: bool, - /// read all data blobs + /// Read all data blobs #[clap(long)] read_data: bool, } diff --git a/src/commands/config.rs b/src/commands/config.rs index 9b146c0..dce182d 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -1,6 +1,6 @@ use anyhow::{bail, Result}; use bytesize::ByteSize; -use clap::Parser; +use clap::{AppSettings, Parser}; use crate::backend::{DecryptBackend, DecryptFullBackend, DecryptWriteBackend, WriteBackend}; use crate::repo::ConfigFile; @@ -40,12 +40,14 @@ pub(super) async fn execute( } #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(super) struct ConfigOpts { - /// set compression level, 0 equals no compression + /// Set compression level. Allowed levels are 1 to 22 and -1 to -7, see https://facebook.github.io/zstd/. + /// Note that 0 equals to no compression #[clap(long, value_name = "LEVEL")] pub set_compression: Option, - /// set repository version + /// Set repository version. Allowed versions: 1,2 #[clap(long, value_name = "VERSION")] pub set_version: Option, @@ -61,9 +63,10 @@ pub(super) struct ConfigOpts { #[clap(long, value_name = "SIZE")] pub set_treepack_size_limit: Option, - /// Set grow factor for tree packs. The default packsize grows by the square root of the reposize - /// multiplied with this factor. This means 32 kiB times this factor per square root of reposize in GiB. - /// Defaults to 32 (= 1MB per sqare root of reposize in GiB) if not set. + /// Set grow factor for tree packs. The default packsize grows by the square root of the total size of all + /// tree packs multiplied with this factor. This means 32 kiB times this factor per square root of total + /// treesize in GiB. + /// Defaults to 32 (= 1MB per sqare root of total treesize in GiB) if not set. #[clap(long, value_name = "FACTOR")] pub set_treepack_growfactor: Option, @@ -73,9 +76,10 @@ pub(super) struct ConfigOpts { #[clap(long, value_name = "SIZE")] pub set_datapack_size: Option, - /// set grow factor for data packs. The default packsize grows by the square root of the reposize - /// multiplied with this factor. This means 32 kiB times this factor per square root of reposize in GiB. - /// Defaults to 32 (= 1MB per sqare root of reposize in GiB) if not set. + /// Set grow factor for data packs. The default packsize grows by the square root of the total size of all + /// data packs multiplied with this factor. This means 32 kiB times this factor per square root of total + /// datasize in GiB. + /// Defaults to 32 (= 1MB per sqare root of total datasize in GiB) if not set. #[clap(long, value_name = "FACTOR")] pub set_datapack_growfactor: Option, diff --git a/src/commands/diff.rs b/src/commands/diff.rs index 32dabbe..298646e 100644 --- a/src/commands/diff.rs +++ b/src/commands/diff.rs @@ -13,11 +13,11 @@ use crate::repo::SnapshotFile; #[derive(Parser)] pub(super) struct Opts { - /// reference snapshot/path + /// Reference snapshot/path #[clap(value_name = "SNAPSHOT1[:PATH1]")] snap1: String, - /// new snapshot/path [default for PATH2: PATH1] + /// New snapshot/path [default for PATH2: PATH1] #[clap(value_name = "SNAPSHOT2[:PATH2]")] snap2: String, } diff --git a/src/commands/forget.rs b/src/commands/forget.rs index 48e119f..f7cd495 100644 --- a/src/commands/forget.rs +++ b/src/commands/forget.rs @@ -1,6 +1,6 @@ use anyhow::Result; use chrono::{DateTime, Datelike, Duration, Local, Timelike}; -use clap::Parser; +use clap::{AppSettings, Parser}; use derivative::Derivative; use prettytable::{format, row, Table}; @@ -11,11 +11,9 @@ use crate::repo::{ }; #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(super) struct Opts { - #[clap(flatten)] - filter: SnapshotFilter, - - /// group snapshots by any combination of host,paths,tags + /// Group snapshots by any combination of host,paths,tags #[clap( long, short = 'g', @@ -24,17 +22,20 @@ pub(super) struct Opts { )] group_by: SnapshotGroupCriterion, - #[clap(flatten)] + #[clap(flatten, help_heading = "SNAPSHOT FILTER OPTIONS")] + filter: SnapshotFilter, + + #[clap(flatten, help_heading = "RETENTION OPTIONS")] keep: KeepOptions, - /// also prune the repository + /// Also prune the repository #[clap(long)] prune: bool, - #[clap(flatten)] + #[clap(flatten, help_heading = "PRUNE OPTIONS (only when used with --prune)")] prune_opts: prune::Opts, - /// don't remove anything, only show what would be done + /// Don't remove anything, only show what would be done #[clap(skip)] dry_run: bool, @@ -137,64 +138,64 @@ pub(super) async fn execute( #[derive(Clone, PartialEq, Derivative, Parser)] #[derivative(Default)] struct KeepOptions { - /// keep snapshots with this taglist (can be specified multiple times) - #[clap(long, value_name = "TAGS")] + /// Keep snapshots with this taglist (can be specified multiple times) + #[clap(long, value_name = "TAG[,TAG,..]")] keep_tags: Vec, - /// keep snapshots ids that start with ID (can be specified multiple times) + /// Keep snapshots ids that start with ID (can be specified multiple times) #[clap(long = "keep-id", value_name = "ID")] keep_ids: Vec, - /// keep the last N snapshots + /// Keep the last N snapshots #[clap(long, short = 'l', value_name = "N", default_value = "0")] keep_last: u32, - /// keep the last N hourly snapshots + /// Keep the last N hourly snapshots #[clap(long, short = 'H', value_name = "N", default_value = "0")] keep_hourly: u32, - /// keep the last N daily snapshots + /// Keep the last N daily snapshots #[clap(long, short = 'd', value_name = "N", default_value = "0")] keep_daily: u32, - /// keep the last N weekly snapshots + /// Keep the last N weekly snapshots #[clap(long, short = 'w', value_name = "N", default_value = "0")] keep_weekly: u32, - /// keep the last N monthly snapshots + /// Keep the last N monthly snapshots #[clap(long, short = 'm', value_name = "N", default_value = "0")] keep_monthly: u32, - /// keep the last N yearly snapshots + /// Keep the last N yearly snapshots #[clap(long, short = 'y', value_name = "N", default_value = "0")] keep_yearly: u32, - /// keep snapshots newer than DURATION relative to latest snapshot + /// Keep snapshots newer than DURATION relative to latest snapshot #[clap(long, value_name = "DURATION", default_value = "0h")] #[derivative(Default(value = "std::time::Duration::ZERO.into()"))] keep_within: humantime::Duration, - /// keep hourly snapshots newer than DURATION relative to latest snapshot + /// Keep hourly snapshots newer than DURATION relative to latest snapshot #[clap(long, value_name = "DURATION", default_value = "0h")] #[derivative(Default(value = "std::time::Duration::ZERO.into()"))] keep_within_hourly: humantime::Duration, - /// keep daily snapshots newer than DURATION relative to latest snapshot + /// Keep daily snapshots newer than DURATION relative to latest snapshot #[clap(long, value_name = "DURATION", default_value = "0d")] #[derivative(Default(value = "std::time::Duration::ZERO.into()"))] keep_within_daily: humantime::Duration, - /// keep weekly snapshots newer than DURATION relative to latest snapshot + /// Keep weekly snapshots newer than DURATION relative to latest snapshot #[clap(long, value_name = "DURATION", default_value = "0w")] #[derivative(Default(value = "std::time::Duration::ZERO.into()"))] keep_within_weekly: humantime::Duration, - /// keep monthly snapshots newer than DURATION relative to latest snapshot + /// Keep monthly snapshots newer than DURATION relative to latest snapshot #[clap(long, value_name = "DURATION", default_value = "0m")] #[derivative(Default(value = "std::time::Duration::ZERO.into()"))] keep_within_monthly: humantime::Duration, - /// keep yearly snapshots newer than DURATION relative to latest snapshot + /// Keep yearly snapshots newer than DURATION relative to latest snapshot #[clap(long, value_name = "DURATION", default_value = "0y")] #[derivative(Default(value = "std::time::Duration::ZERO.into()"))] keep_within_yearly: humantime::Duration, diff --git a/src/commands/init.rs b/src/commands/init.rs index f5bae89..582643a 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -16,10 +16,10 @@ use crate::repo::{ConfigFile, KeyFile}; #[derive(Parser)] pub(super) struct Opts { - #[clap(flatten)] + #[clap(flatten, help_heading = "KEY OPTIONS")] key_opts: AddOpts, - #[clap(flatten)] + #[clap(flatten, help_heading = "CONFIG OPTIONS")] config_opts: ConfigOpts, } diff --git a/src/commands/key.rs b/src/commands/key.rs index 76d0cf3..751087d 100644 --- a/src/commands/key.rs +++ b/src/commands/key.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::BufReader; use anyhow::Result; -use clap::{Parser, Subcommand}; +use clap::{AppSettings, Parser, Subcommand}; use rpassword::{prompt_password, read_password_from_bufread}; use crate::backend::{FileType, WriteBackend}; @@ -21,22 +21,23 @@ enum Command { } #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(crate) struct AddOpts { - /// set 'hostname' in public key information + /// File from which to read the new password + #[clap(long)] + pub(crate) new_password_file: Option, + + /// Set 'hostname' in public key information #[clap(long)] pub(crate) hostname: Option, - /// set 'username' in public key information + /// Set 'username' in public key information #[clap(long)] pub(crate) username: Option, - /// add 'created' date in public key information + /// Add 'created' date in public key information #[clap(long)] pub(crate) with_created: bool, - - /// file from which to read the new password - #[clap(long)] - pub(crate) new_password_file: Option, } pub(super) async fn execute(be: &impl WriteBackend, key: Key, opts: Opts) -> Result<()> { diff --git a/src/commands/list.rs b/src/commands/list.rs index d5dde65..e75acd7 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -8,7 +8,7 @@ use crate::repo::IndexFile; #[derive(Parser)] pub(super) struct Opts { - /// file type to list + /// File type to list #[clap(possible_values=["blobs", "index", "packs", "snapshots", "keys"])] tpe: String, } diff --git a/src/commands/ls.rs b/src/commands/ls.rs index e1223d8..224dc07 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -11,7 +11,7 @@ use crate::repo::SnapshotFile; #[derive(Parser)] pub(super) struct Opts { - /// snapshot/path to ls + /// Snapshot/path to list #[clap(value_name = "SNAPSHOT[:PATH]")] snap: String, } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 3509dfe..6b4ebb1 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -34,11 +34,22 @@ use vlog::*; #[clap(about, version)] struct Opts { /// Repository to use - #[clap(short, long, global = true, env = "RUSTIC_REPOSITORY")] + #[clap( + short, + long, + global = true, + env = "RUSTIC_REPOSITORY", + help_heading = "GLOBAL OPTIONS" + )] repository: Option, /// Repository to use as hot storage - #[clap(long, global = true, env = "RUSTIC_REPO_HOT")] + #[clap( + long, + global = true, + env = "RUSTIC_REPO_HOT", + help_heading = "GLOBAL OPTIONS" + )] repo_hot: Option, /// File to read the password from @@ -47,11 +58,19 @@ struct Opts { long, global = true, parse(from_os_str), - env = "RUSTIC_PASSWORD_FILE" + env = "RUSTIC_PASSWORD_FILE", + help_heading = "GLOBAL OPTIONS" )] password_file: Option, + /// Increase verbosity (can be used multiple times) - #[clap(long, short = 'v', global = true, parse(from_occurrences))] + #[clap( + long, + short = 'v', + global = true, + parse(from_occurrences), + help_heading = "GLOBAL OPTIONS" + )] verbose: i8, /// Don't be verbose at all @@ -60,21 +79,28 @@ struct Opts { short = 'q', global = true, parse(from_occurrences), - conflicts_with = "verbose" + conflicts_with = "verbose", + help_heading = "GLOBAL OPTIONS" )] quiet: i8, /// Don't use a cache. - #[clap(long, global = true, env = "RUSTIC_NO_CACHE")] + #[clap( + long, + global = true, + env = "RUSTIC_NO_CACHE", + help_heading = "GLOBAL OPTIONS" + )] no_cache: bool, - /// Use this dir as cache dir. If not given, rustic searches for rustic cache dirs + /// Use this dir as cache dir instead of the standard cache dir #[clap( long, global = true, parse(from_os_str), conflicts_with = "no-cache", - env = "RUSTIC_CACHE_DIR" + env = "RUSTIC_CACHE_DIR", + help_heading = "GLOBAL OPTIONS" )] cache_dir: Option, @@ -87,16 +113,16 @@ enum Command { /// Backup to the repository Backup(backup::Opts), - /// Cat repository files and blobs + /// Show raw data of repository files and blobs Cat(cat::Opts), - /// Change repo configuration + /// Change the repository configuration Config(config::Opts), - /// Check repository + /// Check the repository Check(check::Opts), - /// Compare two snapshots + /// Compare two snapshots/paths Diff(diff::Opts), /// Remove snapshots from the repository @@ -111,22 +137,22 @@ enum Command { /// List repository files List(list::Opts), - /// Ls snapshots + /// List file contents of a snapshot Ls(ls::Opts), - /// Show snapshots + /// Show a detailed overview of the snapshots within the repository Snapshots(snapshots::Opts), - /// update to the latest rustic release + /// Update to the latest rustic release SelfUpdate(self_update::Opts), - /// Remove unused data + /// Remove unused data or repack repository pack files Prune(prune::Opts), - /// Restore snapshot + /// Restore a snapshot/path Restore(restore::Opts), - /// Show general information about repository + /// Show general information about the repository Repoinfo(repoinfo::Opts), /// Change tags of snapshots diff --git a/src/commands/prune.rs b/src/commands/prune.rs index 00a634f..14b63a5 100644 --- a/src/commands/prune.rs +++ b/src/commands/prune.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use anyhow::{anyhow, bail, Result}; use bytesize::ByteSize; use chrono::{DateTime, Duration, Local}; -use clap::Parser; +use clap::{AppSettings, Parser}; use derive_more::Add; use futures::{future, TryStreamExt}; use vlog::*; @@ -18,58 +18,61 @@ use crate::index::{IndexBackend, IndexCollector, IndexType, IndexedBackend, Inde use crate::repo::{ConfigFile, IndexBlob, IndexFile, IndexPack, SnapshotFile}; #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(super) struct Opts { - /// define maximum data to repack in % of reposize or as size (e.g. '5b', '2 kB', '3M', '4TiB') or 'unlimited' + /// Don't remove anything, only show what would be done + #[clap(long, short = 'n')] + pub(crate) dry_run: bool, + + /// Define maximum data to repack in % of reposize or as size (e.g. '5b', '2 kB', '3M', '4TiB') or 'unlimited' #[clap(long, value_name = "LIMIT", default_value = "unlimited")] max_repack: LimitOption, - /// tolerate limit of unused data in % of reposize after pruning or as size (e.g. '5b', '2 kB', '3M', '4TiB') or 'unlimited' + /// Tolerate limit of unused data in % of reposize after pruning or as size (e.g. '5b', '2 kB', '3M', '4TiB') or 'unlimited' #[clap(long, value_name = "LIMIT", default_value = "5%")] max_unused: LimitOption, - /// only repack packs which are cacheable [default: true for a hot/cold repository, else false] - #[clap(long, value_name = "TRUE/FALSE")] - repack_cacheable_only: Option, + /// Minimum duration (e.g. 90d) to keep packs before repacking or removing. More recently created + /// packs won't be repacked or marked for deletion within this prune run. + #[clap(long, value_name = "DURATION", default_value = "0d")] + keep_pack: humantime::Duration, - /// minimum duration (e.g. 10m) to keep packs marked for deletion + /// Minimum duration (e.g. 10m) to keep packs marked for deletion. More recently marked packs won't be + /// deleted within this prune run. #[clap(long, value_name = "DURATION", default_value = "23h")] keep_delete: humantime::Duration, - /// delete files immediately instead of marking them. This also removes all already marked files. + /// Delete files immediately instead of marking them. This also removes all files already marked for deletion. /// WARNING: Only use if you are sure the repository is not accessed by parallel processes! #[clap(long)] instant_delete: bool, - /// minimum duration (e.g. 90d) to keep packs before repacking or removing - #[clap(long, value_name = "DURATION", default_value = "0d")] - keep_pack: humantime::Duration, - - /// only remove unneded pack file from local cache + /// Only remove unneded pack file from local cache. Do not change the repository at all. #[clap(long)] cache_only: bool, - /// simply copy blobs when repacking instead of decrypting; possibly compressing; encrypting + /// Simply copy blobs when repacking instead of decrypting; possibly compressing; encrypting #[clap(long)] fast_repack: bool, - /// repack packs containing uncompressed blobs. This cannot be used with --fast-repack. + /// Repack packs containing uncompressed blobs. This cannot be used with --fast-repack. /// Implies --max-unused=0. #[clap(long, conflicts_with = "fast-repack")] repack_uncompressed: bool, - /// don't remove anything, only show what would be done - #[clap(long, short = 'n')] - pub(crate) dry_run: bool, + /// Only repack packs which are cacheable [default: true for a hot/cold repository, else false] + #[clap(long, value_name = "TRUE/FALSE")] + repack_cacheable_only: Option, - /// warm up needed data pack files by only requesting them without processing + /// Warm up needed data pack files by only requesting them without processing #[clap(long)] warm_up: bool, - /// warm up needed data pack files by running the command with %id replaced by pack id + /// Warm up needed data pack files by running the command with %id replaced by pack id #[clap(long, conflicts_with = "warm-up")] warm_up_command: Option, - /// duration (e.g. 10m) to wait after warm up before doing the actual restore + /// Duration (e.g. 10m) to wait after warm up before doing the actual restore #[clap(long, value_name = "DURATION", conflicts_with = "dry-run")] warm_up_wait: Option, } diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 9e90842..a7df2af 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -5,7 +5,7 @@ use std::num::NonZeroU32; use std::path::{Path, PathBuf}; use anyhow::{anyhow, bail, Result}; -use clap::Parser; +use clap::{AppSettings, Parser}; use derive_getters::Dissolve; use futures::{stream::FuturesUnordered, TryStreamExt}; use ignore::{DirEntry, WalkBuilder}; @@ -21,37 +21,39 @@ use crate::index::{IndexBackend, IndexedBackend}; use crate::repo::SnapshotFile; #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(super) struct Opts { - /// dry-run: don't restore, only show what would be done + /// Dry-run: don't restore, only show what would be done #[clap(long, short = 'n')] dry_run: bool, - /// warm up needed data pack files by only requesting them without processing - #[clap(long)] - warm_up: bool, - - /// warm up needed data pack files by running the command with %id replaced by pack id - #[clap(long, conflicts_with = "warm-up")] - warm_up_command: Option, - - /// duration (e.g. 10m) to wait after warm up before doing the actual restore - #[clap(long, value_name = "DURATION", conflicts_with = "dry-run")] - warm_up_wait: Option, - - /// remove all files/dirs destination which are not contained in snapshot. - /// Warning: Use with care, maybe first try this with --dry-run? + /// Remove all files/dirs in destination which are not contained in snapshot. + /// WARNING: Use with care, maybe first try this first with --dry-run? #[clap(long)] delete: bool, - /// use numeric ids instead of user/groug when restoring uid/gui + /// Use numeric ids instead of user/group when restoring uid/gui #[clap(long)] numeric_id: bool, - /// snapshot/path to restore + /// Warm up needed data pack files by only requesting them without processing + #[clap(long)] + warm_up: bool, + + /// Warm up needed data pack files by running the command with %id replaced by pack id + #[clap(long, conflicts_with = "warm-up")] + warm_up_command: Option, + + /// Duration (e.g. 10m) to wait after warm up before doing the actual restore + #[clap(long, value_name = "DURATION", conflicts_with = "dry-run")] + warm_up_wait: Option, + + /// Snapshot/path to restore #[clap(value_name = "SNAPSHOT[:PATH]")] snap: String, - /// restore destination + /// Restore destination + #[clap(value_name = "DESTINATION")] dest: String, } diff --git a/src/commands/snapshots.rs b/src/commands/snapshots.rs index 5b7340e..d2aac36 100644 --- a/src/commands/snapshots.rs +++ b/src/commands/snapshots.rs @@ -13,18 +13,18 @@ use crate::repo::{ #[derive(Parser)] pub(super) struct Opts { - #[clap(flatten)] + #[clap(flatten, help_heading = "SNAPSHOT FILTER OPTIONS")] filter: SnapshotFilter, - /// group snapshots by any combination of host,paths,tags + /// Group snapshots by any combination of host,paths,tags #[clap(long, short = 'g', value_name = "CRITERION", default_value = "")] group_by: SnapshotGroupCriterion, - /// show detailed information about snapshots + /// Show detailed information about snapshots #[clap(long)] long: bool, - /// Snapshots to list + /// Snapshots to show #[clap(value_name = "ID")] ids: Vec, } diff --git a/src/commands/tag.rs b/src/commands/tag.rs index 1fa48a3..8cf8305 100644 --- a/src/commands/tag.rs +++ b/src/commands/tag.rs @@ -1,45 +1,68 @@ use anyhow::Result; use chrono::{Duration, Local}; -use clap::Parser; +use clap::{AppSettings, Parser}; use super::progress_counter; use crate::backend::{DecryptFullBackend, FileType}; use crate::repo::{DeleteOption, SnapshotFile, SnapshotFilter, StringList}; #[derive(Parser)] +#[clap(global_setting(AppSettings::DeriveDisplayOrder))] pub(super) struct Opts { - #[clap(flatten)] - filter: SnapshotFilter, - - /// Tags to add (can be specified multiple times) - #[clap(long, value_name = "TAG[,TAG,..]", conflicts_with = "remove")] - add: Vec, - - /// Tags to remove (can be specified multiple times) - #[clap(long, value_name = "TAG[,TAG,..]")] - remove: Vec, - - /// Tag list to set (can be specified multiple times) - #[clap(long, value_name = "TAG[,TAG,..]", conflicts_with = "remove")] - set: Vec, - - /// Remove any delete mark - #[clap(long, conflicts_with_all = &["set-delete-never", "set-delete-after"])] - remove_delete: bool, - - /// Mark snapshot as uneraseable - #[clap(long, conflicts_with = "set-delete-after")] - set_delete_never: bool, - - /// Mark snapshot to be deleted after given duration (e.g. 10d) - #[clap(long, value_name = "DURATION")] - set_delete_after: Option, - - /// don't change any snapshot, only show which would be modified + /// Don't change any snapshot, only show which would be modified #[clap(long, short = 'n')] dry_run: bool, - /// Snapshots to change tags + #[clap( + flatten, + help_heading = "SNAPSHOT FILTER OPTIONS (if no snapshot is given)" + )] + filter: SnapshotFilter, + + /// Tags to add (can be specified multiple times) + #[clap( + long, + value_name = "TAG[,TAG,..]", + conflicts_with = "remove", + help_heading = "TAG OPTIONS" + )] + add: Vec, + + /// Tags to remove (can be specified multiple times) + #[clap(long, value_name = "TAG[,TAG,..]", help_heading = "TAG OPTIONS")] + remove: Vec, + + /// Tag list to set (can be specified multiple times) + #[clap( + long, + value_name = "TAG[,TAG,..]", + conflicts_with = "remove", + help_heading = "TAG OPTIONS" + )] + set: Vec, + + /// Remove any delete mark + #[clap( + long, + conflicts_with_all = &["set-delete-never", "set-delete-after"], + help_heading = "DELETE MARK OPTIONS" + )] + remove_delete: bool, + + /// Mark snapshot as uneraseable + #[clap( + long, + conflicts_with = "set-delete-after", + help_heading = "DELETE MARK OPTIONS" + )] + set_delete_never: bool, + + /// Mark snapshot to be deleted after given duration (e.g. 10d) + #[clap(long, value_name = "DURATION", help_heading = "DELETE MARK OPTIONS")] + set_delete_after: Option, + + /// Snapshots to change tags. If none is given, use filter to filter from all + /// snapshots. #[clap(value_name = "ID")] ids: Vec, } diff --git a/src/repo/snapshotfile.rs b/src/repo/snapshotfile.rs index c69bdcc..51a6023 100644 --- a/src/repo/snapshotfile.rs +++ b/src/repo/snapshotfile.rs @@ -311,11 +311,11 @@ impl Ord for SnapshotFile { #[derive(Parser)] pub struct SnapshotFilter { /// Path list to filter (can be specified multiple times) - #[clap(long = "filter-paths")] + #[clap(long = "filter-paths", value_name = "PATH[,PATH,..]")] paths: Vec, /// Tag list to filter (can be specified multiple times) - #[clap(long = "filter-tags")] + #[clap(long = "filter-tags", value_name = "TAG[,TAG,..]")] tags: Vec, /// Hostname to filter (can be specified multiple times)