From 8a57476da374df943d3af2e740125a7b79e8ca8e Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Thu, 13 Apr 2017 14:10:11 +0200 Subject: [PATCH] Remove folders of backups (re #5) --- docs/man/zvault-remove.1.md | 10 +++++++++- src/cli/args.rs | 7 +++++-- src/cli/mod.rs | 14 +++++++++++++- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/man/zvault-remove.1.md b/docs/man/zvault-remove.1.md index 93a7c87..f767c2a 100644 --- a/docs/man/zvault-remove.1.md +++ b/docs/man/zvault-remove.1.md @@ -3,7 +3,7 @@ zvault-remove(1) -- Remove a backup or a subtree ## SYNOPSIS -`zvault remove ` +`zvault remove [OPTIONS] ` ## DESCRIPTION @@ -17,6 +17,9 @@ If `repository` is omitted, the default repository location is used instead. If a backup is referenced, this backup will be deleted. If a subtree is given, the backup is instead rewritten to not include that subtree anymore. +If a folder of backups is referenced by `BACKUP` the flag `--force` must be set +in order to remove all backups in that folder (also recursively). + Note: When removing backup subtrees, the meta information of that backup is left unchanged and still contains the data (e.g. duration and size) of the original backup run. @@ -32,6 +35,11 @@ data of the deleted backups becomes inaccessible and can not be restored.** ## OPTIONS + * `-f`, `--force`: + + Remove multiple backups in a backup folder + + * `-h`, `--help`: Prints help information diff --git a/src/cli/args.rs b/src/cli/args.rs index 1c76529..88915c2 100644 --- a/src/cli/args.rs +++ b/src/cli/args.rs @@ -37,7 +37,8 @@ pub enum Arguments { Remove { repo_path: String, backup_name: String, - inode: Option + inode: Option, + force: bool }, Prune { repo_path: String, @@ -318,6 +319,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> { .arg(Arg::from_usage(" 'Destination path for backup'") .validator(validate_existing_path))) .subcommand(SubCommand::with_name("remove").aliases(&["rm", "delete", "del"]).about("Remove a backup or a subtree") + .arg(Arg::from_usage("-f --force 'Remove multiple backups in a backup folder'")) .arg(Arg::from_usage(" 'The backup/subtree path, [repository]::backup[::subtree]'") .validator(|val| validate_repo_path(val, true, Some(true), None)))) .subcommand(SubCommand::with_name("prune").about("Remove backups based on age") @@ -468,7 +470,8 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> { Arguments::Remove { repo_path: repository.to_string(), backup_name: backup.unwrap().to_string(), - inode: inode.map(|v| v.to_string()) + inode: inode.map(|v| v.to_string()), + force: args.is_present("force") } }, ("prune", Some(args)) => { diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 4315cdb..634c125 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -386,13 +386,25 @@ pub fn run() -> Result<(), ErrorCode> { } info!("Restore finished"); }, - Arguments::Remove{repo_path, backup_name, inode} => { + Arguments::Remove{repo_path, backup_name, inode, force} => { let mut repo = try!(open_repository(&repo_path)); if let Some(inode) = inode { let mut backup = try!(get_backup(&repo, &backup_name)); checked!(repo.remove_backup_path(&mut backup, inode), "remove backup subpath", ErrorCode::RemoveRun); checked!(repo.save_backup(&backup, &backup_name), "save backup file", ErrorCode::SaveBackup); info!("The backup subpath has been deleted, run vacuum to reclaim space"); + } else if repo.layout.backups_path().join(&backup_name).is_dir() { + let backups = checked!(repo.get_backups(&backup_name), "retrieve backups", ErrorCode::RemoveRun); + if force { + for name in backups.keys() { + checked!(repo.delete_backup(&format!("{}/{}", &backup_name, name)), "delete backup", ErrorCode::RemoveRun); + } + } else { + error!("Denying to remove multiple backups (use --force):"); + for name in backups.keys() { + println!(" - {}/{}", backup_name, name); + } + } } else { checked!(repo.delete_backup(&backup_name), "delete backup", ErrorCode::RemoveRun); info!("The backup has been deleted, run vacuum to reclaim space");