diff options
author | Lars Wirzenius <liw@liw.fi> | 2020-11-10 07:30:32 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2020-11-10 10:46:07 +0200 |
commit | 6a5a9854eb90b767b668403928e2c64091929b51 (patch) | |
tree | e17847eea9be6df26da86669008185b2ac2ec967 /src/bin | |
parent | 6707f65cc6152bc1a5f54331e921d4fac5f597fc (diff) | |
download | obnam2-6a5a9854eb90b767b668403928e2c64091929b51.tar.gz |
feat: restore a generation
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/obnam-backup.rs | 2 | ||||
-rw-r--r-- | src/bin/obnam-restore.rs | 95 |
2 files changed, 80 insertions, 17 deletions
diff --git a/src/bin/obnam-backup.rs b/src/bin/obnam-backup.rs index f5d6b43..7d7e07e 100644 --- a/src/bin/obnam-backup.rs +++ b/src/bin/obnam-backup.rs @@ -17,7 +17,7 @@ fn main() -> anyhow::Result<()> { let client = BackupClient::new(&config.server_name, config.server_port)?; { - let mut gen = Generation::new(&config.dbname)?; + let mut gen = Generation::create(&config.dbname)?; gen.insert_iter(FsIterator::new(&config.root).map(|entry| match entry { Err(err) => Err(err), Ok(entry) => client.upload_filesystem_entry(entry, BUFFER_SIZE), diff --git a/src/bin/obnam-restore.rs b/src/bin/obnam-restore.rs index 21cc096..442104a 100644 --- a/src/bin/obnam-restore.rs +++ b/src/bin/obnam-restore.rs @@ -1,5 +1,7 @@ use log::{debug, info}; use obnam::client::BackupClient; +use obnam::fsentry::{FilesystemEntry, FilesystemKind}; +use obnam::generation::Generation; //use obnam::chunkmeta::ChunkMeta; use serde::Deserialize; use std::fs::File; @@ -7,19 +9,6 @@ use std::io::prelude::*; use std::path::{Path, PathBuf}; use structopt::StructOpt; -#[derive(Debug, StructOpt)] -#[structopt(name = "obnam-backup", about = "Simplistic backup client")] -struct Opt { - #[structopt(parse(from_os_str))] - config: PathBuf, - - #[structopt()] - gen_id: String, - - #[structopt(parse(from_os_str))] - dbname: PathBuf, -} - fn main() -> anyhow::Result<()> { pretty_env_logger::init(); @@ -31,19 +20,41 @@ fn main() -> anyhow::Result<()> { info!("config: {:?}", config); let client = BackupClient::new(&config.server_name, config.server_port)?; - let gen = client.fetch_generation(&opt.gen_id)?; - debug!("gen: {:?}", gen); + let gen_chunk = client.fetch_generation(&opt.gen_id)?; + debug!("gen: {:?}", gen_chunk); { let mut dbfile = File::create(&opt.dbname)?; - for id in gen.chunk_ids() { + for id in gen_chunk.chunk_ids() { let chunk = client.fetch_chunk(id)?; dbfile.write_all(chunk.data())?; } } + info!("downloaded generation to {}", opt.dbname.display()); + + let gen = Generation::open(&opt.dbname)?; + for (fileid, entry) in gen.files()? { + restore(&client, &gen, fileid, entry, &opt.to)?; + } Ok(()) } +#[derive(Debug, StructOpt)] +#[structopt(name = "obnam-backup", about = "Simplistic backup client")] +struct Opt { + #[structopt(parse(from_os_str))] + config: PathBuf, + + #[structopt()] + gen_id: String, + + #[structopt(parse(from_os_str))] + dbname: PathBuf, + + #[structopt(parse(from_os_str))] + to: PathBuf, +} + #[derive(Debug, Deserialize, Clone)] pub struct Config { pub server_name: String, @@ -57,3 +68,55 @@ impl Config { Ok(config) } } + +fn restore( + client: &BackupClient, + gen: &Generation, + fileid: u64, + entry: FilesystemEntry, + to: &Path, +) -> anyhow::Result<()> { + println!("restoring {}:{}", fileid, entry.path().display()); + + let path = if entry.path().is_absolute() { + entry.path().strip_prefix("/")? + } else { + entry.path() + }; + let to = to.join(path); + debug!(" to: {}", to.display()); + + match entry.kind() { + FilesystemKind::Regular => restore_regular(client, &gen, &to, fileid, &entry)?, + FilesystemKind::Directory => restore_directory(&to)?, + } + Ok(()) +} + +fn restore_directory(path: &Path) -> anyhow::Result<()> { + debug!("restoring directory {}", path.display()); + std::fs::create_dir_all(path)?; + Ok(()) +} + +fn restore_regular( + client: &BackupClient, + gen: &Generation, + path: &Path, + fileid: u64, + _entry: &FilesystemEntry, +) -> anyhow::Result<()> { + debug!("restoring regular {}", path.display()); + let parent = path.parent().unwrap(); + debug!(" mkdir {}", parent.display()); + std::fs::create_dir_all(parent)?; + { + let mut file = std::fs::File::create(path)?; + for chunkid in gen.chunkids(fileid)? { + let chunk = client.fetch_chunk(&chunkid)?; + file.write_all(chunk.data())?; + } + } + debug!("restored regular {}", path.display()); + Ok(()) +} |