summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-11-10 07:30:32 +0200
committerLars Wirzenius <liw@liw.fi>2020-11-10 10:46:07 +0200
commit6a5a9854eb90b767b668403928e2c64091929b51 (patch)
treee17847eea9be6df26da86669008185b2ac2ec967 /src/bin
parent6707f65cc6152bc1a5f54331e921d4fac5f597fc (diff)
downloadobnam2-6a5a9854eb90b767b668403928e2c64091929b51.tar.gz
feat: restore a generation
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/obnam-backup.rs2
-rw-r--r--src/bin/obnam-restore.rs95
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(())
+}