add filter for SnapshotFile::latest, add hostname

This commit is contained in:
Alexander Weiss 2022-03-03 02:40:12 +01:00
parent 6ce09c8634
commit b72f798ba5
6 changed files with 38 additions and 15 deletions

View File

@ -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"

View File

@ -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<BE: DecryptWriteBackend, I: IndexedBackend> Archiver<BE, I> {
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<BE: DecryptWriteBackend, I: IndexedBackend> Archiver<BE, I> {
.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,

View File

@ -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(())
}

View File

@ -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);

View File

@ -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);

View File

@ -62,22 +62,30 @@ impl SnapshotFile {
Ok(snap)
}
pub fn from_str<B: ReadBackend>(be: &B, string: &str) -> Result<Self> {
pub fn from_str<B: ReadBackend>(
be: &B,
string: &str,
predicate: impl FnMut(&Self) -> bool,
) -> Result<Self> {
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<B: ReadBackend>(be: &B) -> Result<Self> {
pub fn latest<B: ReadBackend>(be: &B, predicate: impl FnMut(&Self) -> bool) -> Result<Self> {
let mut latest: Option<Self> = 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 => {}
_ => {