#![warn(bare_trait_objects)]
use std::{fs::File, path::Path};
pub use crate::{
errors::{Error, Result},
hashes::Estimate,
node::{
compare_trees, fs, load_from, HashCombiner, HashUpdater, NodeWriter, ReadIterator, Source,
SureNode,
},
progress::{log_init, Progress},
show::show_tree,
store::{parse_store, Store, StoreTags, StoreVersion, TempLoader, Version},
suretree::AttMap,
};
mod errors;
mod escape;
mod hashes;
pub mod node;
mod progress;
mod show;
mod store;
mod surefs;
mod suretree;
pub fn update<P: AsRef<Path>>(
dir: P,
store: &dyn Store,
is_update: bool,
tags: &StoreTags,
) -> Result<()> {
let dir = dir.as_ref();
let mut estimate = Estimate { files: 0, bytes: 0 };
let tmp = if is_update {
let scan_temp = {
let mut tmp = store.make_temp()?;
let src = fs::scan_fs(dir)?;
node::save_to(&mut tmp, src)?;
tmp
}
.into_loader()?;
let latest = store.load_iter(Version::Latest)?;
let tmp = {
let mut tmp = store.make_temp()?;
let loader = Loader(&*scan_temp);
let combiner = HashCombiner::new(latest, loader.iter()?)?.inspect(|node| {
if let Ok(n @ SureNode::File { .. }) = node {
if n.needs_hash() {
estimate.files += 1;
estimate.bytes += n.size();
}
}
});
node::save_to(&mut tmp, combiner)?;
tmp
};
tmp
} else {
let mut tmp = store.make_temp()?;
let src = fs::scan_fs(dir)?.inspect(|node| {
if let Ok(n @ SureNode::File { .. }) = node {
if n.needs_hash() {
estimate.files += 1;
estimate.bytes += n.size();
}
}
});
node::save_to(&mut tmp, src)?;
tmp
}
.into_loader()?;
let loader = Loader(&*tmp);
let hu = HashUpdater::new(loader, store);
let hm = hu.compute_parallel(dir.to_str().unwrap(), &estimate)?;
let mut tmp2 = store.make_new(tags)?;
hm.merge(&mut NodeWriter::new(&mut tmp2)?)?;
tmp2.commit()?;
Ok(())
}
struct Loader<'a>(&'a dyn TempLoader);
impl<'a> Source for Loader<'a> {
fn iter(&self) -> Result<Box<dyn Iterator<Item = Result<SureNode>> + Send>> {
let rd = File::open(self.0.path_ref())?;
Ok(Box::new(load_from(rd)?))
}
}