From 2b2340deeca86c2616e401f2dc85802f5f7d47e7 Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Mon, 12 Jun 2023 12:32:22 +0200 Subject: [PATCH] adapt rustic to Progress trait in rustic_core --- src/commands/backup.rs | 2 +- src/commands/cat.rs | 8 +++--- src/commands/check.rs | 11 ++++---- src/commands/copy.rs | 7 ++--- src/commands/diff.rs | 10 ++++---- src/commands/dump.rs | 2 +- src/commands/forget.rs | 10 ++++++-- src/commands/list.rs | 3 +-- src/commands/ls.rs | 2 +- src/commands/merge.rs | 9 ++++--- src/commands/prune.rs | 8 +++--- src/commands/repair.rs | 13 +++++----- src/commands/repoinfo.rs | 6 ++--- src/commands/restore.rs | 6 ++--- src/commands/snapshots.rs | 5 +++- src/commands/tag.rs | 5 ++-- src/config/progress_options.rs | 47 ++++++++++++++++++++++++++++------ src/helpers.rs | 16 +++++++----- 18 files changed, 108 insertions(+), 62 deletions(-) diff --git a/src/commands/backup.rs b/src/commands/backup.rs index cbfa645..b439f98 100644 --- a/src/commands/backup.rs +++ b/src/commands/backup.rs @@ -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(); diff --git a/src/commands/cat.rs b/src/commands/cat.rs index 8cefb57..b68b09d 100644 --- a/src/commands/cat.rs +++ b/src/commands/cat.rs @@ -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)?; diff --git a/src/commands/check.rs b/src/commands/check.rs index 379b411..e05ebde 100644 --- a/src/commands/check.rs +++ b/src/commands/check.rs @@ -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::(p.clone())? { + for index in be.stream_all::(&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::(p.clone())? + .stream_all::(&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(); diff --git a/src/commands/copy.rs b/src/commands/copy.rs index 9db474d..a7204f9 100644 --- a/src/commands/copy.rs +++ b/src/commands/copy.rs @@ -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()?; diff --git a/src/commands/diff.rs b/src/commands/diff.rs index c1395d4..c1e13db 100644 --- a/src/commands/diff.rs +++ b/src/commands/diff.rs @@ -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); diff --git a/src/commands/dump.rs b/src/commands/dump.rs index 2cd7436..7f1d231 100644 --- a/src/commands/dump.rs +++ b/src/commands/dump.rs @@ -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 { diff --git a/src/commands/forget.rs b/src/commands/forget.rs index d260ff5..d6802fa 100644 --- a/src/commands/forget.rs +++ b/src/commands/forget.rs @@ -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] }; diff --git a/src/commands/list.rs b/src/commands/list.rs index fcf00f4..1e69148 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -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::(ProgressBar::hidden())? + .stream_all::(&config.global.progress_options.progress_hidden())? .into_iter() .for_each(|index| { match index { diff --git a/src/commands/ls.rs b/src/commands/ls.rs index bbd3224..ee1d548 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -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 { diff --git a/src/commands/merge.rs b/src/commands/merge.rs index aba7f76..adf169f 100644 --- a/src/commands/merge.rs +++ b/src/commands/merge.rs @@ -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( diff --git a/src/commands/prune.rs b/src/commands/prune.rs index 957a4be..a3a61aa 100644 --- a/src/commands/prune.rs +++ b/src/commands/prune.rs @@ -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::(p.clone())? + be.stream_all::(&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::(list, p.clone())? + .stream_list::(list, &p)? .into_iter() .map_ok(|(_, snap)| snap.tree) .try_collect()?; diff --git a/src/commands/repair.rs b/src/commands/repair.rs index 42b0a29..376bc03 100644 --- a/src/commands/repair.rs +++ b/src/commands/repair.rs @@ -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::(p.clone())? + be.stream_all::(&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(), diff --git a/src/commands/repoinfo.rs b/src/commands/repoinfo.rs index d425014..7f6a1bc 100644 --- a/src/commands/repoinfo.rs +++ b/src/commands/repoinfo.rs @@ -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::(p.clone())? + .stream_all::(&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, diff --git a/src/commands/restore.rs b/src/commands/restore.rs index ac86bac..45ea8a3 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -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())?; diff --git a/src/commands/snapshots.rs b/src/commands/snapshots.rs index d499eba..c36b73d 100644 --- a/src/commands/snapshots.rs +++ b/src/commands/snapshots.rs @@ -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] } diff --git a/src/commands/tag.rs b/src/commands/tag.rs index 832d4e6..cfd24d1 100644 --- a/src/commands/tag.rs +++ b/src/commands/tag.rs @@ -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 ( diff --git a/src/config/progress_options.rs b/src/config/progress_options.rs index 09eca2e..7cc74b1 100644 --- a/src/config/progress_options.rs +++ b/src/config/progress_options.rs @@ -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>) -> ProgressBar { + pub fn progress_spinner(&self, prefix: impl Into>) -> 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>) -> ProgressBar { + pub fn progress_counter(&self, prefix: impl Into>) -> 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>) -> ProgressBar { + pub fn no_progress() -> RusticProgress { + RusticProgress(ProgressBar::hidden()) + } + + pub fn progress_bytes(&self, prefix: impl Into>) -> 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"); } } diff --git a/src/helpers.rs b/src/helpers.rs index 5c15277..938f446 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -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( snaps: &[SnapshotFile], dest_repo: &OpenRepository, filter: F, + p: &impl Progress, ) -> Result> 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();