Remove backup subpath

This commit is contained in:
Dennis Schwerdel 2017-03-23 08:24:27 +01:00
parent b346f6e291
commit 05290f3198
3 changed files with 41 additions and 10 deletions

View File

@ -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

View File

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

View File

@ -179,11 +179,16 @@ impl Backup {
quick_error!{
#[derive(Debug)]
#[allow(unknown_lints,large_enum_variant)]
pub enum BackupError {
FailedPaths(backup: Backup, failed: Vec<PathBuf>) {
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<P: AsRef<Path>>(&mut self, backup: &Backup, path: P) -> Result<Inode, RepositoryError> {
pub fn remove_backup_path<P: AsRef<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<P: AsRef<Path>>(&mut self, backup: &Backup, path: P) -> Result<Vec<Inode>, 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<P: AsRef<Path>>(&mut self, backup: &Backup, path: P) -> Result<Inode, RepositoryError> {
self.get_backup_path(backup, path).map(|mut inodes| inodes.pop().unwrap())
}
}