diff --git a/README.md b/README.md index faaf980..fcaf02c 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,6 @@ Recommended: Brotli/2-7 - http://mahkoh.github.io/posix/doc/posix/sys/time/fn.utimes.html ### CLI functionality -- Remove backup subtrees - list --tree ### Other diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 6b48049..f0fcf2a 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -193,11 +193,12 @@ pub fn run() { } }, Arguments::Remove{repo_path, backup_name, inode} => { - let repo = open_repository(&repo_path); - if let Some(_inode) = inode { - let _backup = get_backup(&repo, &backup_name); - error!("Removing backup subtrees is not implemented yet"); - return + let mut repo = open_repository(&repo_path); + if let Some(inode) = inode { + let mut backup = get_backup(&repo, &backup_name); + checked(repo.remove_backup_path(&mut backup, inode), "remove backup subpath"); + checked(repo.save_backup(&backup, &backup_name), "save backup file"); + info!("The backup subpath has been deleted, run vacuum to reclaim space"); } else { checked(repo.delete_backup(&backup_name), "delete backup"); info!("The backup has been deleted, run vacuum to reclaim space"); @@ -220,7 +221,6 @@ pub fn run() { if !force { info!("Run with --force to actually execute this command"); } - return }, Arguments::Check{repo_path, backup_name, inode, full} => { let mut repo = open_repository(&repo_path); @@ -235,6 +235,7 @@ pub fn run() { } else { checked(repo.check(full), "check repository") } + info!("Integrity verified") }, Arguments::List{repo_path, backup_name, inode} => { let mut repo = open_repository(&repo_path); @@ -269,7 +270,6 @@ pub fn run() { let backup = get_backup(&repo, &backup_name); if let Some(_inode) = inode { error!("Displaying information on single inodes is not implemented yet"); - return } else { print_backup(&backup); } diff --git a/src/repository/backup.rs b/src/repository/backup.rs index 46782d6..67af73a 100644 --- a/src/repository/backup.rs +++ b/src/repository/backup.rs @@ -179,11 +179,16 @@ impl Backup { quick_error!{ #[derive(Debug)] + #[allow(unknown_lints,large_enum_variant)] pub enum BackupError { FailedPaths(backup: Backup, failed: Vec) { description("Some paths could not be backed up") display("Backup error: some paths could not be backed up") } + RemoveRoot { + description("The root of a backup can not be removed") + display("Backup error: the root of a backup can not be removed") + } } } @@ -421,18 +426,45 @@ impl Repository { } } - pub fn get_backup_inode>(&mut self, backup: &Backup, path: P) -> Result { + pub fn remove_backup_path>(&mut self, backup: &mut Backup, path: P) -> Result<(), RepositoryError> { + let mut inodes = try!(self.get_backup_path(backup, path)); + let to_remove = inodes.pop().unwrap(); + let mut remove_from = match inodes.pop() { + Some(inode) => inode, + None => return Err(BackupError::RemoveRoot.into()) + }; + remove_from.children.as_mut().unwrap().remove(&to_remove.name); + let mut last_inode_chunks = try!(self.put_inode(&remove_from)); + let mut last_inode_name = remove_from.name; + while let Some(mut inode) = inodes.pop() { + inode.children.as_mut().unwrap().insert(last_inode_name, last_inode_chunks); + last_inode_chunks = try!(self.put_inode(&inode)); + last_inode_name = inode.name; + } + backup.root = last_inode_chunks; + Ok(()) + } + + pub fn get_backup_path>(&mut self, backup: &Backup, path: P) -> Result, RepositoryError> { + let mut inodes = vec![]; let mut inode = try!(self.get_inode(&backup.root)); for c in path.as_ref().components() { if let path::Component::Normal(name) = c { let name = name.to_string_lossy(); if let Some(chunks) = inode.children.as_mut().and_then(|c| c.remove(&name as &str)) { + inodes.push(inode); inode = try!(self.get_inode(&chunks)); } else { return Err(RepositoryError::NoSuchFileInBackup(backup.clone(), path.as_ref().to_owned())); } } } - Ok(inode) + inodes.push(inode); + Ok(inodes) + } + + #[inline] + pub fn get_backup_inode>(&mut self, backup: &Backup, path: P) -> Result { + self.get_backup_path(backup, path).map(|mut inodes| inodes.pop().unwrap()) } }