Remove folders of backups (re #5)

Dennis Schwerdel 6 years ago
parent 650ab331c0
commit 8a57476da3
  1. 10
  2. 7
  3. 14

@ -3,7 +3,7 @@ zvault-remove(1) -- Remove a backup or a subtree
`zvault remove <BACKUP>`
`zvault remove [OPTIONS] <BACKUP>`
@ -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.**
* `-f`, `--force`:
Remove multiple backups in a backup folder
* `-h`, `--help`:
Prints help information

@ -37,7 +37,8 @@ pub enum Arguments {
Remove {
repo_path: String,
backup_name: String,
inode: Option<String>
inode: Option<String>,
force: bool
Prune {
repo_path: String,
@ -318,6 +319,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
.arg(Arg::from_usage("<DST> 'Destination path for backup'")
.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("<BACKUP> '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:|v| v.to_string())
inode:|v| v.to_string()),
force: args.is_present("force")
("prune", Some(args)) => {

@ -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");