Remove backup subpath

pull/10/head
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 - http://mahkoh.github.io/posix/doc/posix/sys/time/fn.utimes.html
### CLI functionality ### CLI functionality
- Remove backup subtrees
- list --tree - list --tree
### Other ### Other

View File

@ -193,11 +193,12 @@ pub fn run() {
} }
}, },
Arguments::Remove{repo_path, backup_name, inode} => { Arguments::Remove{repo_path, backup_name, inode} => {
let repo = open_repository(&repo_path); let mut repo = open_repository(&repo_path);
if let Some(_inode) = inode { if let Some(inode) = inode {
let _backup = get_backup(&repo, &backup_name); let mut backup = get_backup(&repo, &backup_name);
error!("Removing backup subtrees is not implemented yet"); checked(repo.remove_backup_path(&mut backup, inode), "remove backup subpath");
return checked(repo.save_backup(&backup, &backup_name), "save backup file");
info!("The backup subpath has been deleted, run vacuum to reclaim space");
} else { } else {
checked(repo.delete_backup(&backup_name), "delete backup"); checked(repo.delete_backup(&backup_name), "delete backup");
info!("The backup has been deleted, run vacuum to reclaim space"); info!("The backup has been deleted, run vacuum to reclaim space");
@ -220,7 +221,6 @@ pub fn run() {
if !force { if !force {
info!("Run with --force to actually execute this command"); info!("Run with --force to actually execute this command");
} }
return
}, },
Arguments::Check{repo_path, backup_name, inode, full} => { Arguments::Check{repo_path, backup_name, inode, full} => {
let mut repo = open_repository(&repo_path); let mut repo = open_repository(&repo_path);
@ -235,6 +235,7 @@ pub fn run() {
} else { } else {
checked(repo.check(full), "check repository") checked(repo.check(full), "check repository")
} }
info!("Integrity verified")
}, },
Arguments::List{repo_path, backup_name, inode} => { Arguments::List{repo_path, backup_name, inode} => {
let mut repo = open_repository(&repo_path); let mut repo = open_repository(&repo_path);
@ -269,7 +270,6 @@ pub fn run() {
let backup = get_backup(&repo, &backup_name); let backup = get_backup(&repo, &backup_name);
if let Some(_inode) = inode { if let Some(_inode) = inode {
error!("Displaying information on single inodes is not implemented yet"); error!("Displaying information on single inodes is not implemented yet");
return
} else { } else {
print_backup(&backup); print_backup(&backup);
} }

View File

@ -179,11 +179,16 @@ impl Backup {
quick_error!{ quick_error!{
#[derive(Debug)] #[derive(Debug)]
#[allow(unknown_lints,large_enum_variant)]
pub enum BackupError { pub enum BackupError {
FailedPaths(backup: Backup, failed: Vec<PathBuf>) { FailedPaths(backup: Backup, failed: Vec<PathBuf>) {
description("Some paths could not be backed up") description("Some paths could not be backed up")
display("Backup error: 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)); let mut inode = try!(self.get_inode(&backup.root));
for c in path.as_ref().components() { for c in path.as_ref().components() {
if let path::Component::Normal(name) = c { if let path::Component::Normal(name) = c {
let name = name.to_string_lossy(); let name = name.to_string_lossy();
if let Some(chunks) = inode.children.as_mut().and_then(|c| c.remove(&name as &str)) { 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)); inode = try!(self.get_inode(&chunks));
} else { } else {
return Err(RepositoryError::NoSuchFileInBackup(backup.clone(), path.as_ref().to_owned())); 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())
} }
} }