adapt rustic to Progress trait in rustic_core

This commit is contained in:
Alexander Weiss 2023-06-12 12:32:22 +02:00
parent 1f29a84a4f
commit 2b2340deec
18 changed files with 108 additions and 62 deletions

View File

@ -195,7 +195,7 @@ impl BackupCmd {
};
let index =
IndexBackend::only_full_trees(&repo.dbe, progress_options.progress_counter(""))?;
IndexBackend::only_full_trees(&repo.dbe, &progress_options.progress_counter(""))?;
for source in sources {
let mut opts = self.clone();

View File

@ -13,8 +13,6 @@ use std::path::Path;
use anyhow::{anyhow, Result};
use indicatif::ProgressBar;
use rustic_core::{
BlobType, DecryptReadBackend, FileType, Id, IndexBackend, IndexedBackend, SnapshotFile, Tree,
};
@ -96,8 +94,10 @@ fn cat_file(be: &impl DecryptReadBackend, tpe: FileType, opt: &IdOpt) -> Result<
}
fn cat_blob(be: &impl DecryptReadBackend, tpe: BlobType, opt: &IdOpt) -> Result<()> {
let config = RUSTIC_APP.config();
let id = Id::from_hex(&opt.id)?;
let data = IndexBackend::new(be, ProgressBar::hidden())?.blob_from_backend(tpe, &id)?;
let data = IndexBackend::new(be, &config.global.progress_options.progress_hidden())?
.blob_from_backend(tpe, &id)?;
print!("{}", String::from_utf8(data.to_vec())?);
Ok(())
@ -113,7 +113,7 @@ fn cat_tree(be: &impl DecryptReadBackend, opts: &TreeOpts) -> Result<()> {
|sn| config.snapshot_filter.matches(sn),
&config.global.progress_options.progress_counter(""),
)?;
let index = IndexBackend::new(be, config.global.progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &config.global.progress_options.progress_counter(""))?;
let node = Tree::node_from_path(&index, snap.tree, Path::new(path))?;
let id = node.subtree.ok_or_else(|| anyhow!("{path} is no dir"))?;
let data = index.blob_from_backend(BlobType::Tree, &id)?;

View File

@ -15,7 +15,6 @@ use std::collections::HashMap;
use anyhow::Result;
use bytes::Bytes;
use indicatif::ProgressBar;
use itertools::Itertools;
use rayon::prelude::{IntoParallelIterator, ParallelBridge, ParallelIterator};
use zstd::stream::decode_all;
@ -23,7 +22,7 @@ use zstd::stream::decode_all;
use rustic_core::{
hash, BlobType, Cache, DecryptReadBackend, FileType, Id, IndexBackend, IndexCollector,
IndexFile, IndexPack, IndexType, IndexedBackend, NodeType, PackHeader, PackHeaderLength,
PackHeaderRef, ReadBackend, SnapshotFile, TreeStreamerOnce,
PackHeaderRef, Progress, ReadBackend, SnapshotFile, TreeStreamerOnce,
};
/// `check` subcommand
@ -172,7 +171,7 @@ fn check_cache_files(
cache: &Cache,
be: &impl ReadBackend,
file_type: FileType,
p: &ProgressBar,
p: &impl Progress,
) -> Result<()> {
let files = cache.list_with_size(file_type)?;
@ -259,7 +258,7 @@ fn check_packs(
let progress_options = &RUSTIC_APP.config().global.progress_options;
let p = progress_options.progress_counter("reading index...");
for index in be.stream_all::<IndexFile>(p.clone())? {
for index in be.stream_all::<IndexFile>(&p)? {
let index = index?.1;
index_collector.extend(index.packs.clone());
for p in index.packs {
@ -308,7 +307,7 @@ fn check_snapshots(index: &impl IndexedBackend) -> Result<()> {
let p = progress_options.progress_counter("reading snapshots...");
let snap_trees: Vec<_> = index
.be()
.stream_all::<SnapshotFile>(p.clone())?
.stream_all::<SnapshotFile>(&p)?
.iter()
.map_ok(|(_, snap)| snap.tree)
.try_collect()?;
@ -365,7 +364,7 @@ fn check_pack(
be: &impl DecryptReadBackend,
index_pack: IndexPack,
mut data: Bytes,
p: &mut ProgressBar,
p: &impl Progress,
) -> Result<()> {
let id = index_pack.id;
let size = index_pack.pack_size();

View File

@ -61,16 +61,17 @@ impl CopyCmd {
}
let be = &repo.dbe;
let p = config.global.progress_options.progress_hidden();
let mut snapshots = if self.ids.is_empty() {
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn))?
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn), &p)?
} else {
SnapshotFile::from_ids(be, &self.ids)?
SnapshotFile::from_ids(be, &self.ids, &p)?
};
// sort for nicer output
snapshots.sort_unstable();
let be = &repo.dbe;
let index = IndexBackend::new(be, config.global.progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &config.global.progress_options.progress_counter(""))?;
let poly = repo.config.poly()?;

View File

@ -16,8 +16,8 @@ use anyhow::{anyhow, bail, Context, Result};
use rustic_core::{
hash, IndexBackend, LocalDestination, LocalSource, LocalSourceFilterOptions,
LocalSourceSaveOptions, Node, NodeStreamer, NodeType, ReadIndex, ReadSourceEntry, RusticResult,
SnapshotFile, Tree,
LocalSourceSaveOptions, Node, NodeStreamer, NodeType, Progress, ReadIndex, ReadSourceEntry,
RusticResult, SnapshotFile, Tree,
};
/// `diff` subcommand
@ -68,13 +68,13 @@ impl DiffCmd {
(Some(id1), Some(id2)) => {
// diff between two snapshots
let p = progress_options.progress_spinner("getting snapshots...");
let snaps = SnapshotFile::from_ids(be, &[id1.to_string(), id2.to_string()])?;
let snaps = SnapshotFile::from_ids(be, &[id1.to_string(), id2.to_string()], &p)?;
p.finish();
let snap1 = &snaps[0];
let snap2 = &snaps[1];
let index = IndexBackend::new(be, progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &progress_options.progress_counter(""))?;
let node1 = Tree::node_from_path(&index, snap1.tree, Path::new(path1))?;
let node2 = Tree::node_from_path(&index, snap2.tree, Path::new(path2))?;
@ -93,7 +93,7 @@ impl DiffCmd {
SnapshotFile::from_str(be, id1, |sn| config.snapshot_filter.matches(sn), &p)?;
p.finish();
let index = IndexBackend::new(be, progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &progress_options.progress_counter(""))?;
let node1 = Tree::node_from_path(&index, snap1.tree, Path::new(path1))?;
let local = LocalDestination::new(path2, false, !node1.is_dir())?;
let path2 = PathBuf::from(path2);

View File

@ -47,7 +47,7 @@ impl DumpCmd {
|sn| config.snapshot_filter.matches(sn),
&progress_options.progress_counter(""),
)?;
let index = IndexBackend::new(be, progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &progress_options.progress_counter(""))?;
let node = Tree::node_from_path(&index, snap.tree, Path::new(path))?;
if node.node_type != NodeType::File {

View File

@ -107,12 +107,18 @@ impl ForgetCmd {
.group_by
.unwrap_or_else(|| SnapshotGroupCriterion::from_str("host,label,paths").unwrap());
let p = progress_options.progress_hidden();
let groups = if self.ids.is_empty() {
SnapshotFile::group_from_backend(be, |sn| config.forget.filter.matches(sn), &group_by)?
SnapshotFile::group_from_backend(
be,
|sn| config.forget.filter.matches(sn),
&group_by,
&p,
)?
} else {
let item = (
SnapshotGroup::default(),
SnapshotFile::from_ids(be, &self.ids)?,
SnapshotFile::from_ids(be, &self.ids, &p)?,
);
vec![item]
};

View File

@ -10,7 +10,6 @@ use crate::{
use abscissa_core::{Command, Runnable, Shutdown};
use anyhow::{bail, Result};
use indicatif::ProgressBar;
use rustic_core::{DecryptReadBackend, FileType, IndexFile, ReadBackend};
@ -41,7 +40,7 @@ impl ListCmd {
// special treatment for listing blobs: read the index and display it
"blobs" => {
repo.dbe
.stream_all::<IndexFile>(ProgressBar::hidden())?
.stream_all::<IndexFile>(&config.global.progress_options.progress_hidden())?
.into_iter()
.for_each(|index| {
match index {

View File

@ -58,7 +58,7 @@ impl LsCmd {
|sn| config.snapshot_filter.matches(sn),
&progress_options.progress_counter(""),
)?;
let index = IndexBackend::new(be, progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &progress_options.progress_counter(""))?;
let node = Tree::node_from_path(&index, snap.tree, Path::new(path))?;
if recursive {

View File

@ -14,7 +14,7 @@ use chrono::Local;
use rustic_core::{
merge_trees, BlobType, DecryptWriteBackend, FileType, Id, IndexBackend, Indexer, Node, Packer,
PathList, ReadIndex, SnapshotFile, SnapshotOptions, Tree,
PathList, Progress, ReadIndex, SnapshotFile, SnapshotOptions, Tree,
};
/// `merge` subcommand
@ -61,13 +61,14 @@ impl MergeCmd {
let be = &repo.dbe;
let p = progress_options.progress_hidden();
let snapshots = if self.ids.is_empty() {
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn))?
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn), &p)?
} else {
SnapshotFile::from_ids(be, &self.ids)?
SnapshotFile::from_ids(be, &self.ids, &p)?
};
let index =
IndexBackend::only_full_trees(&be.clone(), progress_options.progress_counter(""))?;
IndexBackend::only_full_trees(&be.clone(), &progress_options.progress_counter(""))?;
let indexer = Indexer::new(be.clone()).into_shared();
let packer = Packer::new(

View File

@ -30,8 +30,8 @@ use crate::helpers::warm_up_wait;
use rustic_core::{
bytes_size_to_string, BlobType, BlobTypeMap, DecryptReadBackend, DecryptWriteBackend, FileType,
HeaderEntry, Id, IndexBackend, IndexBlob, IndexCollector, IndexFile, IndexPack, IndexType,
IndexedBackend, Indexer, Initialize, NodeType, OpenRepository, PackSizer, ReadBackend,
ReadIndex, Repacker, SnapshotFile, Sum, TreeStreamerOnce,
IndexedBackend, Indexer, Initialize, NodeType, OpenRepository, PackSizer, Progress,
ReadBackend, ReadIndex, Repacker, SnapshotFile, Sum, TreeStreamerOnce,
};
pub(super) mod constants {
@ -117,7 +117,7 @@ impl PruneCmd {
let p = progress_options.progress_counter("reading index...");
let mut index_collector = IndexCollector::new(IndexType::OnlyTrees);
be.stream_all::<IndexFile>(p.clone())?
be.stream_all::<IndexFile>(&p)?
.into_iter()
.for_each(|index| {
let (id, index) = match index {
@ -1159,7 +1159,7 @@ fn find_used_blobs(
.collect();
let snap_trees: Vec<_> = index
.be()
.stream_list::<SnapshotFile>(list, p.clone())?
.stream_list::<SnapshotFile>(list, &p)?
.into_iter()
.map_ok(|(_, snap)| snap.tree)
.try_collect()?;

View File

@ -15,8 +15,8 @@ use anyhow::Result;
use rustic_core::{
BlobType, DecryptReadBackend, DecryptWriteBackend, FileType, Id, IndexBackend, IndexFile,
IndexPack, IndexedBackend, Indexer, NodeType, PackHeader, PackHeaderRef, Packer, ReadBackend,
ReadIndex, SnapshotFile, StringList, Tree, WriteBackend,
IndexPack, IndexedBackend, Indexer, NodeType, PackHeader, PackHeaderRef, Packer, Progress,
ReadBackend, ReadIndex, SnapshotFile, StringList, Tree, WriteBackend,
};
use crate::helpers::warm_up_wait;
@ -139,7 +139,7 @@ impl IndexSubCmd {
};
let p = progress_options.progress_counter("reading index...");
be.stream_all::<IndexFile>(p.clone())?
be.stream_all::<IndexFile>(&p)?
.into_iter()
.for_each(|index| {
let (index_id, index) = match index {
@ -247,17 +247,18 @@ impl SnapSubCmd {
let be = &repo.dbe;
let config_file = &repo.config;
let p = progress_options.progress_hidden();
let snapshots = if self.ids.is_empty() {
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn))?
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn), &p)?
} else {
SnapshotFile::from_ids(be, &self.ids)?
SnapshotFile::from_ids(be, &self.ids, &p)?
};
let mut replaced = HashMap::new();
let mut seen = HashSet::new();
let mut delete = Vec::new();
let index = IndexBackend::new(&be.clone(), progress_options.progress_counter(""))?;
let index = IndexBackend::new(&be.clone(), &progress_options.progress_counter(""))?;
let indexer = Indexer::new(be.clone()).into_shared();
let mut packer = Packer::new(
be.clone(),

View File

@ -13,7 +13,7 @@ use anyhow::Result;
use rustic_core::helpers::table_output::{print_file_info, table_right_from};
use rustic_core::{
bytes_size_to_string, BlobType, BlobTypeMap, DecryptReadBackend, IndexEntry, IndexFile,
RepoInfo, Sum,
Progress, RepoInfo, Sum,
};
/// `repoinfo` subcommand
@ -50,7 +50,7 @@ impl RepoInfoCmd {
.progress_options
.progress_counter("scanning index...");
repo.dbe
.stream_all::<IndexFile>(p.clone())?
.stream_all::<IndexFile>(&p)?
.into_iter()
.for_each(|index| {
let index = match index {
@ -77,7 +77,7 @@ impl RepoInfoCmd {
}
}
});
p.finish_with_message("done");
p.finish();
let mut table = table_right_from(
1,

View File

@ -22,8 +22,8 @@ use rayon::ThreadPoolBuilder;
use rustic_core::{
bytes_size_to_string, AddFileResult, DecryptReadBackend, FileInfos, FileType, IndexBackend,
IndexedBackend, LocalDestination, Node, NodeStreamer, NodeType, RestoreStats, SnapshotFile,
Tree, TreeStreamerOptions,
IndexedBackend, LocalDestination, Node, NodeStreamer, NodeType, Progress, RestoreStats,
SnapshotFile, Tree, TreeStreamerOptions,
};
use crate::{filtering::SnapshotFilter, helpers::warm_up_wait};
@ -94,7 +94,7 @@ impl RestoreCmd {
&progress_options.progress_counter(""),
)?;
let index = IndexBackend::new(be, progress_options.progress_counter(""))?;
let index = IndexBackend::new(be, &progress_options.progress_counter(""))?;
let node = Tree::node_from_path(&index, snap.tree, Path::new(path))?;
let dest = LocalDestination::new(&self.dest, true, !node.is_dir())?;

View File

@ -57,16 +57,19 @@ impl SnapshotCmd {
let repo = open_repository(get_repository(&config));
let p = config.global.progress_options.progress_hidden();
let groups = match &self.ids[..] {
[] => SnapshotFile::group_from_backend(
&repo.dbe,
|sn| config.snapshot_filter.matches(sn),
&self.group_by,
&p,
)?,
[id] if id == "latest" => SnapshotFile::group_from_backend(
&repo.dbe,
|sn| config.snapshot_filter.matches(sn),
&self.group_by,
&p,
)?
.into_iter()
.map(|(group, mut snaps)| {
@ -80,7 +83,7 @@ impl SnapshotCmd {
_ => {
let item = (
SnapshotGroup::default(),
SnapshotFile::from_ids(&repo.dbe, &self.ids)?,
SnapshotFile::from_ids(&repo.dbe, &self.ids, &p)?,
);
vec![item]
}

View File

@ -81,10 +81,11 @@ impl TagCmd {
let be = &repo.dbe;
let p = config.global.progress_options.progress_hidden();
let snapshots = if self.ids.is_empty() {
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn))?
SnapshotFile::all_from_backend(be, |sn| config.snapshot_filter.matches(sn), &p)?
} else {
SnapshotFile::from_ids(be, &self.ids)?
SnapshotFile::from_ids(be, &self.ids, &p)?
};
let delete = match (

View File

@ -10,6 +10,8 @@ use merge::Merge;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
use rustic_core::Progress;
#[serde_as]
#[derive(Default, Debug, Parser, Clone, Copy, Deserialize, Serialize, Merge)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
@ -36,7 +38,7 @@ impl ProgressOptions {
self.progress_interval.map_or(Duration::ZERO, |i| *i)
}
pub fn progress_spinner(&self, prefix: impl Into<Cow<'static, str>>) -> ProgressBar {
pub fn progress_spinner(&self, prefix: impl Into<Cow<'static, str>>) -> RusticProgress {
if self.no_progress {
return Self::no_progress();
}
@ -47,10 +49,10 @@ impl ProgressOptions {
);
p.set_prefix(prefix);
p.enable_steady_tick(self.progress_interval());
p
RusticProgress(p)
}
pub fn progress_counter(&self, prefix: impl Into<Cow<'static, str>>) -> ProgressBar {
pub fn progress_counter(&self, prefix: impl Into<Cow<'static, str>>) -> RusticProgress {
if self.no_progress {
return Self::no_progress();
}
@ -61,14 +63,18 @@ impl ProgressOptions {
);
p.set_prefix(prefix);
p.enable_steady_tick(self.progress_interval());
p
RusticProgress(p)
}
pub fn no_progress() -> ProgressBar {
ProgressBar::hidden()
pub fn progress_hidden(&self) -> RusticProgress {
Self::no_progress()
}
pub fn progress_bytes(&self, prefix: impl Into<Cow<'static, str>>) -> ProgressBar {
pub fn no_progress() -> RusticProgress {
RusticProgress(ProgressBar::hidden())
}
pub fn progress_bytes(&self, prefix: impl Into<Cow<'static, str>>) -> RusticProgress {
if self.no_progress {
return Self::no_progress();
}
@ -84,6 +90,31 @@ impl ProgressOptions {
);
p.set_prefix(prefix);
p.enable_steady_tick(self.progress_interval());
p
RusticProgress(p)
}
}
#[derive(Debug, Clone)]
pub struct RusticProgress(ProgressBar);
impl Progress for RusticProgress {
fn is_hidden(&self) -> bool {
self.0.is_hidden()
}
fn set_length(&self, len: u64) {
self.0.set_length(len);
}
fn set_title(&self, title: &'static str) {
self.0.set_prefix(title);
}
fn inc(&self, inc: u64) {
self.0.inc(inc);
}
fn finish(&self) {
self.0.finish_with_message("done");
}
}

View File

@ -11,7 +11,7 @@ use rayon::{
use rustic_core::{
parse_command, table_with_titles, BlobType, DecryptWriteBackend, FileType, Id, IndexBackend,
IndexedBackend, Indexer, NodeType, OpenRepository, Packer, ReadBackend, ReadIndex,
IndexedBackend, Indexer, NodeType, OpenRepository, Packer, Progress, ReadBackend, ReadIndex,
SnapshotFile, TreeStreamerOnce,
};
@ -102,9 +102,12 @@ pub(crate) fn copy(
let be_dest = &repo_dest.dbe;
let progress_options = &config.global.progress_options;
let snapshots = relevant_snapshots(snapshots, repo_dest, |sn| {
config.snapshot_filter.matches(sn)
})?;
let snapshots = relevant_snapshots(
snapshots,
repo_dest,
|sn| config.snapshot_filter.matches(sn),
&progress_options.progress_hidden(),
)?;
match (snapshots.len(), config.global.dry_run) {
(count, true) => {
@ -120,7 +123,7 @@ pub(crate) fn copy(
let snap_trees: Vec<_> = snapshots.iter().map(|sn| sn.tree).collect();
let index_dest = IndexBackend::new(be_dest, progress_options.progress_counter(""))?;
let index_dest = IndexBackend::new(be_dest, &progress_options.progress_counter(""))?;
let indexer = Indexer::new(be_dest.clone()).into_shared();
let data_packer = Packer::new(
@ -198,12 +201,13 @@ pub(crate) fn relevant_snapshots<F>(
snaps: &[SnapshotFile],
dest_repo: &OpenRepository,
filter: F,
p: &impl Progress,
) -> Result<Vec<SnapshotFile>>
where
F: FnMut(&SnapshotFile) -> bool,
{
// save snapshots in destination in BTreeSet, as we want to efficiently search within to filter out already existing snapshots before copying.
let snapshots_dest: BTreeSet<_> = SnapshotFile::all_from_backend(&dest_repo.dbe, filter)?
let snapshots_dest: BTreeSet<_> = SnapshotFile::all_from_backend(&dest_repo.dbe, filter, p)?
.into_iter()
.map(SnapshotFile::clear_ids)
.collect();