From b72f798ba505ec3fa6a5368fbeeea739a1a5d4e5 Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Thu, 3 Mar 2022 02:40:12 +0100 Subject: [PATCH] add filter for SnapshotFile::latest, add hostname --- Cargo.toml | 1 + src/archiver/archiver.rs | 5 +++-- src/commands/backup.rs | 29 +++++++++++++++++++++-------- src/commands/ls.rs | 2 +- src/commands/restore.rs | 2 +- src/repo/snapshot.rs | 14 +++++++++++--- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8ee27b9..0df89a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ boomphf = {version = "0.5", optional = true} walkdir = "2" ignore = "0.4" # commands +gethostname = "0.2" bytesize = "1" clap = { version = "3", features = ["derive"] } rpassword = "5" diff --git a/src/archiver/archiver.rs b/src/archiver/archiver.rs index ed24519..1bcf2d2 100644 --- a/src/archiver/archiver.rs +++ b/src/archiver/archiver.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::ffi::OsString; use std::io::BufRead; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -145,7 +146,7 @@ impl Archiver { Ok(()) } - pub fn finalize_snapshot(&mut self, backup_path: PathBuf) -> Result<()> { + pub fn finalize_snapshot(&mut self, backup_path: PathBuf, hostname: OsString) -> Result<()> { self.finish_trees(&PathBuf::from("/"))?; let chunk = self.tree.serialize()?; @@ -165,7 +166,7 @@ impl Archiver { .to_str() .ok_or(anyhow!("non-unicode path {:?}", backup_path))? .to_string()], - "host".to_string(), + hostname.to_str().unwrap().to_string(), "user".to_string(), 0, 0, diff --git a/src/commands/backup.rs b/src/commands/backup.rs index 8446791..00be26e 100644 --- a/src/commands/backup.rs +++ b/src/commands/backup.rs @@ -1,9 +1,10 @@ +use gethostname::gethostname; use std::fs::{read_link, File}; use std::io::{BufRead, BufReader}; use std::os::unix::fs::MetadataExt; use std::path::PathBuf; -use anyhow::Result; +use anyhow::{anyhow, Result}; use chrono::{TimeZone, Utc}; use clap::Parser; use ignore::{DirEntry, WalkBuilder}; @@ -34,17 +35,29 @@ pub(super) fn execute(opts: Opts, be: &impl DecryptFullBackend) -> Result<()> { let poly = u64::from_str_radix(config.chunker_polynomial(), 16)?; let backup_path = PathBuf::from(&opts.source); let backup_path = backup_path.absolutize()?; + let backup_path_str = backup_path + .to_str() + .ok_or(anyhow!("non-unicode path {:?}", backup_path))? + .to_string(); - println! {"reading index..."} - let index = IndexBackend::new(be)?; - let parent_tree = match opts.parent { - None => None, - Some(parent) => { - let snap = SnapshotFile::from_str(be, &parent)?; + let parent = match opts.parent { + None => SnapshotFile::latest(be, |snap| snap.paths.contains(&backup_path_str)).ok(), + Some(parent) => SnapshotFile::from_id(be, &parent).ok(), + }; + let parent_tree = match parent { + Some(snap) => { println!("using parent {}", snap.id); Some(snap.tree) } + None => { + println!("using no parent"); + None + } }; + + println! {"reading index..."} + let index = IndexBackend::new(be)?; + let parent = Parent::new(&index, parent_tree.as_ref()); let mut archiver = Archiver::new(be.clone(), index, poly, parent)?; @@ -62,7 +75,7 @@ pub(super) fn execute(opts: Opts, be: &impl DecryptFullBackend) -> Result<()> { let (path, node, r) = res?; archiver.add_entry(&path, node, r)?; } - archiver.finalize_snapshot(backup_path.to_path_buf())?; + archiver.finalize_snapshot(backup_path.to_path_buf(), gethostname())?; Ok(()) } diff --git a/src/commands/ls.rs b/src/commands/ls.rs index 61e9efd..953b50c 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -13,7 +13,7 @@ pub(super) struct Opts { } pub(super) fn execute(be: &impl DecryptReadBackend, opts: Opts) -> Result<()> { - let snap = SnapshotFile::from_str(be, &opts.id)?; + let snap = SnapshotFile::from_str(be, &opts.id, |_| true)?; let index = IndexBackend::new(be)?; let tree_iter = tree_iterator(&index, vec![snap.tree])?.filter_map(Result::ok); diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 60ab670..4a2b4ba 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -34,7 +34,7 @@ pub(super) struct Opts { pub(super) fn execute(be: &impl DecryptReadBackend, opts: Opts) -> Result<()> { println!("getting snapshot..."); - let snap = SnapshotFile::from_str(be, &opts.id)?; + let snap = SnapshotFile::from_str(be, &opts.id, |_| true)?; let dest = LocalBackend::new(&opts.dest); diff --git a/src/repo/snapshot.rs b/src/repo/snapshot.rs index 89bc7dc..ad1f415 100644 --- a/src/repo/snapshot.rs +++ b/src/repo/snapshot.rs @@ -62,22 +62,30 @@ impl SnapshotFile { Ok(snap) } - pub fn from_str(be: &B, string: &str) -> Result { + pub fn from_str( + be: &B, + string: &str, + predicate: impl FnMut(&Self) -> bool, + ) -> Result { match string { - "latest" => Self::latest(be), + "latest" => Self::latest(be, predicate), _ => Self::from_id(be, string), } } /// Get the latest SnapshotFile from the backend - pub fn latest(be: &B) -> Result { + pub fn latest(be: &B, predicate: impl FnMut(&Self) -> bool) -> Result { let mut latest: Option = None; + let mut pred = predicate; for snap in be .list(FileType::Snapshot)? .iter() .map(|id| SnapshotFile::from_backend(be, &id)) { let snap = snap?; + if !pred(&snap) { + continue; + } match &latest { Some(l) if l.time > snap.time => {} _ => {