mirror of https://github.com/dswd/zvault
Restore and list
This commit is contained in:
parent
ba68fc2fda
commit
9fc70ea0fb
15
src/main.rs
15
src/main.rs
|
@ -34,6 +34,7 @@ Usage:
|
|||
zvault check [--full] <repo>
|
||||
zvault backups <repo>
|
||||
zvault info <backup>
|
||||
zvault list <backup> <path>
|
||||
zvault stats <repo>
|
||||
zvault bundles <repo>
|
||||
zvault algotest <path>
|
||||
|
@ -57,6 +58,7 @@ struct Args {
|
|||
|
||||
cmd_backups: bool,
|
||||
cmd_info: bool,
|
||||
cmd_list: bool,
|
||||
|
||||
cmd_stats: bool,
|
||||
cmd_bundles: bool,
|
||||
|
@ -187,5 +189,18 @@ fn main() {
|
|||
|
||||
if args.cmd_restore {
|
||||
repo.restore_backup(&backup, &args.arg_path.unwrap()).unwrap();
|
||||
return
|
||||
}
|
||||
|
||||
if args.cmd_list {
|
||||
let inode = repo.get_backup_inode(&backup, &args.arg_path.unwrap()).unwrap();
|
||||
println!("{}", inode.format_one_line());
|
||||
if let Some(children) = inode.children {
|
||||
for chunks in children.values() {
|
||||
let inode = repo.get_inode(&chunks).unwrap();
|
||||
println!("- {}", inode.format_one_line());
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use super::{Repository, Chunk, RepositoryError};
|
||||
use super::metadata::FileType;
|
||||
use super::metadata::{FileType, Inode};
|
||||
|
||||
use ::util::*;
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
use std::path::{self, Path};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use chrono::prelude::*;
|
||||
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Backup {
|
||||
pub root: Vec<Chunk>,
|
||||
pub total_data_size: u64, // Sum of all raw sizes of all entities
|
||||
|
@ -73,9 +73,18 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn restore_backup<P: AsRef<Path>>(&mut self, backup: &Backup, path: P) -> Result<(), RepositoryError> {
|
||||
let inode = try!(self.get_inode(&backup.root));
|
||||
try!(self.save_inode_at(&inode, path));
|
||||
//FIXME: recurse
|
||||
let mut queue = VecDeque::new();
|
||||
queue.push_back((path.as_ref().to_owned(), try!(self.get_inode(&backup.root))));
|
||||
while let Some((path, inode)) = queue.pop_front() {
|
||||
try!(self.save_inode_at(&inode, &path));
|
||||
if inode.file_type == FileType::Directory {
|
||||
let path = path.join(inode.name);
|
||||
for chunks in inode.children.unwrap().values() {
|
||||
let inode = try!(self.get_inode(&chunks));
|
||||
queue.push_back((path.clone(), inode));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -147,4 +156,19 @@ impl Repository {
|
|||
backup.avg_chunk_size = backup.deduplicated_data_size as f32 / backup.chunk_count as f32;
|
||||
Ok(backup)
|
||||
}
|
||||
|
||||
pub fn get_backup_inode<P: AsRef<Path>>(&mut self, backup: &Backup, path: P) -> Result<Inode, RepositoryError> {
|
||||
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)) {
|
||||
inode = try!(self.get_inode(&chunks));
|
||||
} else {
|
||||
return Err(RepositoryError::NoSuchFileInBackup(backup.clone(), path.as_ref().to_owned()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(inode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::backup::Backup;
|
||||
use super::bundle_map::BundleMapError;
|
||||
use super::config::ConfigError;
|
||||
use super::integrity::RepositoryIntegrityError;
|
||||
|
@ -62,5 +63,9 @@ quick_error!{
|
|||
description("Invalid file type")
|
||||
display("{:?} has an invalid file type", path)
|
||||
}
|
||||
NoSuchFileInBackup(backup: Backup, path: PathBuf) {
|
||||
description("No such file in backup")
|
||||
display("The backup does not contain the file {:?}", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,6 +143,14 @@ impl Inode {
|
|||
// https://crates.io/crates/filetime
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
pub fn format_one_line(&self) -> String {
|
||||
match self.file_type {
|
||||
FileType::Directory => format!("{:25}\t{} entries", format!("{}/", self.name), self.children.as_ref().unwrap().len()),
|
||||
FileType::File => format!("{:25}\t{}", self.name, to_file_size(self.size)),
|
||||
FileType::Symlink => format!("{:25}\t -> {}", self.name, self.symlink_target.as_ref().unwrap()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue