From 50847a3ac49f85e888fb9db8bc138a5dd95c40b0 Mon Sep 17 00:00:00 2001 From: Alexander Weiss Date: Thu, 29 Jun 2023 23:42:42 +0200 Subject: [PATCH] use Repository states --- crates/rustic_core/src/commands/cat.rs | 37 ++-- crates/rustic_core/src/commands/check.rs | 16 +- crates/rustic_core/src/commands/dump.rs | 11 +- crates/rustic_core/src/commands/forget.rs | 6 +- crates/rustic_core/src/commands/prune.rs | 35 ++-- crates/rustic_core/src/commands/repoinfo.rs | 15 +- crates/rustic_core/src/commands/snapshots.rs | 34 ++-- crates/rustic_core/src/lib.rs | 2 +- crates/rustic_core/src/repository.rs | 167 ++++++++++++++----- crates/rustic_core/src/repository/warm_up.rs | 14 +- src/commands.rs | 6 +- src/commands/backup.rs | 8 +- src/commands/config.rs | 17 +- src/commands/copy.rs | 13 +- src/commands/diff.rs | 4 +- src/commands/key.rs | 8 +- src/commands/list.rs | 4 +- src/commands/ls.rs | 4 +- src/commands/merge.rs | 8 +- src/commands/repair.rs | 10 +- src/commands/restore.rs | 4 +- src/commands/tag.rs | 4 +- src/helpers.rs | 20 +-- 23 files changed, 277 insertions(+), 170 deletions(-) diff --git a/crates/rustic_core/src/commands/cat.rs b/crates/rustic_core/src/commands/cat.rs index 644afc175..bfd9e852d 100644 --- a/crates/rustic_core/src/commands/cat.rs +++ b/crates/rustic_core/src/commands/cat.rs @@ -3,40 +3,49 @@ use std::path::Path; use bytes::Bytes; use crate::{ - error::CommandErrorKind, repository::IndexedRepository, BlobType, DecryptReadBackend, FileType, - Id, IndexedBackend, OpenRepository, ProgressBars, ReadBackend, RusticResult, SnapshotFile, - Tree, + error::CommandErrorKind, + repository::{Indexed, Open, Repository}, + BlobType, DecryptReadBackend, FileType, Id, IndexedBackend, ProgressBars, ReadBackend, + RusticResult, SnapshotFile, Tree, }; -pub fn cat_file

(repo: &OpenRepository

, tpe: FileType, id: &str) -> RusticResult { - let id = repo.dbe.find_id(tpe, id)?; - let data = repo.dbe.read_encrypted_full(tpe, &id)?; +pub(crate) fn cat_file( + repo: &Repository, + tpe: FileType, + id: &str, +) -> RusticResult { + let id = repo.dbe().find_id(tpe, id)?; + let data = repo.dbe().read_encrypted_full(tpe, &id)?; Ok(data) } -pub fn cat_blob

(repo: &IndexedRepository

, tpe: BlobType, id: &str) -> RusticResult { +pub(crate) fn cat_blob( + repo: &Repository, + tpe: BlobType, + id: &str, +) -> RusticResult { let id = Id::from_hex(id)?; - let data = repo.index.blob_from_backend(tpe, &id)?; + let data = repo.index().blob_from_backend(tpe, &id)?; Ok(data) } -pub fn cat_tree( - repo: &IndexedRepository

, +pub(crate) fn cat_tree( + repo: &Repository, snap: &str, sn_filter: impl FnMut(&SnapshotFile) -> bool + Send + Sync, ) -> RusticResult { let (id, path) = snap.split_once(':').unwrap_or((snap, "")); let snap = SnapshotFile::from_str( - &repo.repo.dbe, + repo.dbe(), id, sn_filter, - &repo.repo.pb.progress_counter("getting snapshot..."), + &repo.pb.progress_counter("getting snapshot..."), )?; - let node = Tree::node_from_path(&repo.index, snap.tree, Path::new(path))?; + let node = Tree::node_from_path(repo.index(), snap.tree, Path::new(path))?; let id = node .subtree .ok_or_else(|| CommandErrorKind::PathIsNoDir(path.to_string()))?; - let data = repo.index.blob_from_backend(BlobType::Tree, &id)?; + let data = repo.index().blob_from_backend(BlobType::Tree, &id)?; Ok(data) } diff --git a/crates/rustic_core/src/commands/check.rs b/crates/rustic_core/src/commands/check.rs index 13977a76b..d7c624ad6 100644 --- a/crates/rustic_core/src/commands/check.rs +++ b/crates/rustic_core/src/commands/check.rs @@ -8,10 +8,12 @@ use rayon::prelude::{IntoParallelIterator, ParallelBridge, ParallelIterator}; use zstd::stream::decode_all; use crate::{ - hash, progress::ProgressBars, BlobType, Cache, DecryptReadBackend, FileType, Id, IndexBackend, - IndexCollector, IndexFile, IndexPack, IndexType, IndexedBackend, NodeType, OpenRepository, - PackHeader, PackHeaderLength, PackHeaderRef, Progress, ReadBackend, RusticResult, SnapshotFile, - TreeStreamerOnce, + hash, + progress::ProgressBars, + repository::{Open, Repository}, + BlobType, Cache, DecryptReadBackend, FileType, Id, IndexBackend, IndexCollector, IndexFile, + IndexPack, IndexType, IndexedBackend, NodeType, PackHeader, PackHeaderLength, PackHeaderRef, + Progress, ReadBackend, RusticResult, SnapshotFile, TreeStreamerOnce, }; /// `check` subcommand @@ -28,9 +30,9 @@ pub struct CheckOpts { } impl CheckOpts { - pub fn run(self, repo: &OpenRepository

) -> RusticResult<()> { - let be = &repo.dbe; - let cache = &repo.cache; + pub(crate) fn run(self, repo: &Repository) -> RusticResult<()> { + let be = repo.dbe(); + let cache = repo.cache(); let hot_be = &repo.be_hot; let raw_be = &repo.be; let pb = &repo.pb; diff --git a/crates/rustic_core/src/commands/dump.rs b/crates/rustic_core/src/commands/dump.rs index 374f24f57..fd499b38e 100644 --- a/crates/rustic_core/src/commands/dump.rs +++ b/crates/rustic_core/src/commands/dump.rs @@ -1,12 +1,13 @@ use std::io::Write; use crate::{ - error::CommandErrorKind, repository::IndexedRepository, BlobType, IndexedBackend, Node, - NodeType, RusticResult, + error::CommandErrorKind, + repository::{Indexed, Repository}, + BlobType, IndexedBackend, Node, NodeType, RusticResult, }; -pub(crate) fn dump

( - repo: &IndexedRepository

, +pub(crate) fn dump( + repo: &Repository, node: &Node, w: &mut impl Write, ) -> RusticResult<()> { @@ -16,7 +17,7 @@ pub(crate) fn dump

( for id in node.content.as_ref().unwrap() { // TODO: cache blobs which are needed later - let data = repo.index.blob_from_backend(BlobType::Data, id)?; + let data = repo.index().blob_from_backend(BlobType::Data, id)?; w.write_all(&data)?; } Ok(()) diff --git a/crates/rustic_core/src/commands/forget.rs b/crates/rustic_core/src/commands/forget.rs index aaeba767a..76eb27a69 100644 --- a/crates/rustic_core/src/commands/forget.rs +++ b/crates/rustic_core/src/commands/forget.rs @@ -6,7 +6,7 @@ use serde::Deserialize; use serde_with::{serde_as, DisplayFromStr}; use crate::{ - Id, OpenRepository, ProgressBars, RusticResult, SnapshotFile, SnapshotGroup, + repository::Open, Id, ProgressBars, Repository, RusticResult, SnapshotFile, SnapshotGroup, SnapshotGroupCriterion, StringList, }; @@ -41,8 +41,8 @@ impl ForgetGroups { } } -pub(crate) fn get_forget_snapshots( - repo: &OpenRepository

, +pub(crate) fn get_forget_snapshots( + repo: &Repository, keep: &KeepOptions, group_by: SnapshotGroupCriterion, filter: impl FnMut(&SnapshotFile) -> bool, diff --git a/crates/rustic_core/src/commands/prune.rs b/crates/rustic_core/src/commands/prune.rs index bfaa53cd9..7b25a789c 100644 --- a/crates/rustic_core/src/commands/prune.rs +++ b/crates/rustic_core/src/commands/prune.rs @@ -19,11 +19,11 @@ use itertools::Itertools; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use crate::{ - error::CommandErrorKind, BlobType, BlobTypeMap, DecryptReadBackend, DecryptWriteBackend, - FileType, HeaderEntry, Id, IndexBackend, IndexBlob, IndexCollector, IndexFile, IndexPack, - IndexType, IndexedBackend, Indexer, Initialize, NodeType, OpenRepository, PackSizer, Progress, - ProgressBars, ReadBackend, ReadIndex, Repacker, RusticResult, SnapshotFile, Sum, - TreeStreamerOnce, + error::CommandErrorKind, repository::Open, BlobType, BlobTypeMap, DecryptReadBackend, + DecryptWriteBackend, FileType, HeaderEntry, Id, IndexBackend, IndexBlob, IndexCollector, + IndexFile, IndexPack, IndexType, IndexedBackend, Indexer, Initialize, NodeType, PackSizer, + Progress, ProgressBars, ReadBackend, ReadIndex, Repacker, Repository, RusticResult, + SnapshotFile, Sum, TreeStreamerOnce, }; pub(super) mod constants { @@ -115,11 +115,14 @@ impl Default for PruneOpts { } impl PruneOpts { - pub fn get_plan(&self, repo: &OpenRepository

) -> RusticResult { + pub fn get_plan( + &self, + repo: &Repository, + ) -> RusticResult { let pb = &repo.pb; - let be = &repo.dbe; + let be = repo.dbe(); - if repo.config.version < 2 && self.repack_uncompressed { + if repo.config().version < 2 && self.repack_uncompressed { return Err(CommandErrorKind::RepackUncompressedRepoV1.into()); } @@ -158,9 +161,9 @@ impl PruneOpts { pruner.check()?; let repack_cacheable_only = self .repack_cacheable_only - .unwrap_or_else(|| repo.config.is_hot == Some(true)); + .unwrap_or_else(|| repo.config().is_hot == Some(true)); let pack_sizer = - total_size.map(|tpe, size| PackSizer::from_config(&repo.config, tpe, size)); + total_size.map(|tpe, size| PackSizer::from_config(&repo.config(), tpe, size)); pruner.decide_packs( Duration::from_std(*self.keep_pack).map_err(CommandErrorKind::FromOutOfRangeError)?, Duration::from_std(*self.keep_delete).map_err(CommandErrorKind::FromOutOfRangeError)?, @@ -745,13 +748,13 @@ impl PrunePlan { } #[allow(clippy::significant_drop_tightening)] - pub fn do_prune( + pub fn do_prune( self, - repo: &OpenRepository

, + repo: &Repository, opts: &PruneOpts, ) -> RusticResult<()> { repo.warm_up_wait(self.repack_packs().into_iter())?; - let be = &repo.dbe; + let be = repo.dbe(); let pb = &repo.pb; let indexer = Indexer::new_unindexed(be.clone()).into_shared(); @@ -776,7 +779,7 @@ impl PrunePlan { be.clone(), BlobType::Tree, indexer.clone(), - &repo.config, + repo.config(), size_after_prune[BlobType::Tree], )?; @@ -784,7 +787,7 @@ impl PrunePlan { be.clone(), BlobType::Data, indexer.clone(), - &repo.config, + repo.config(), size_after_prune[BlobType::Data], )?; @@ -1050,7 +1053,7 @@ impl PackInfo { // find used blobs in repo fn find_used_blobs( - index: &(impl IndexedBackend + Unpin), + index: &impl IndexedBackend, ignore_snaps: &[Id], pb: &impl ProgressBars, ) -> RusticResult> { diff --git a/crates/rustic_core/src/commands/repoinfo.rs b/crates/rustic_core/src/commands/repoinfo.rs index 3d4197e02..b8117bed1 100644 --- a/crates/rustic_core/src/commands/repoinfo.rs +++ b/crates/rustic_core/src/commands/repoinfo.rs @@ -3,8 +3,9 @@ use serde::{Deserialize, Serialize}; use crate::{ index::IndexEntry, repofile::indexfile::{IndexFile, IndexPack}, - BlobType, BlobTypeMap, DecryptReadBackend, FileType, OpenRepository, Progress, ProgressBars, - ReadBackend, Repository, RusticResult, ALL_FILE_TYPES, + repository::Open, + BlobType, BlobTypeMap, DecryptReadBackend, FileType, Progress, ProgressBars, ReadBackend, + Repository, RusticResult, ALL_FILE_TYPES, }; #[derive(Default, Clone, Debug, Serialize, Deserialize)] @@ -53,8 +54,8 @@ impl PackInfo { } } -pub(crate) fn collect_index_infos( - repo: &OpenRepository

, +pub(crate) fn collect_index_infos( + repo: &Repository, ) -> RusticResult { let mut blob_info = BlobTypeMap::<()>::default().map(|blob_type, _| BlobInfo { blob_type, @@ -72,7 +73,7 @@ pub(crate) fn collect_index_infos( let mut pack_info_delete = pack_info; let p = repo.pb.progress_counter("scanning index..."); - for index in repo.dbe.stream_all::(&p)? { + for index in repo.dbe().stream_all::(&p)? { let index = index?.1; for pack in &index.packs { let tpe = pack.blob_type(); @@ -130,7 +131,9 @@ pub(crate) fn collect_file_info(be: &impl ReadBackend) -> RusticResult(repo: &Repository

) -> RusticResult { +pub fn collect_file_infos( + repo: &Repository, +) -> RusticResult { let p = repo.pb.progress_spinner("scanning files..."); let files = collect_file_info(&repo.be)?; let files_hot = repo.be_hot.as_ref().map(collect_file_info).transpose()?; diff --git a/crates/rustic_core/src/commands/snapshots.rs b/crates/rustic_core/src/commands/snapshots.rs index 3d9211be1..58b3925a0 100644 --- a/crates/rustic_core/src/commands/snapshots.rs +++ b/crates/rustic_core/src/commands/snapshots.rs @@ -1,35 +1,35 @@ //! `smapshot` subcommand use crate::{ - OpenRepository, ProgressBars, RusticResult, SnapshotFile, SnapshotGroup, SnapshotGroupCriterion, + repository::Open, ProgressBars, Repository, RusticResult, SnapshotFile, SnapshotGroup, + SnapshotGroupCriterion, }; -pub(crate) fn get_snapshot_group( - repo: &OpenRepository

, +pub(crate) fn get_snapshot_group( + repo: &Repository, ids: &[String], group_by: SnapshotGroupCriterion, filter: impl FnMut(&SnapshotFile) -> bool, ) -> RusticResult)>> { let pb = &repo.pb; + let dbe = repo.dbe(); let p = pb.progress_counter("getting snapshots..."); let groups = match ids { - [] => SnapshotFile::group_from_backend(&repo.dbe, filter, group_by, &p)?, - [id] if id == "latest" => { - SnapshotFile::group_from_backend(&repo.dbe, filter, group_by, &p)? - .into_iter() - .map(|(group, mut snaps)| { - snaps.sort_unstable(); - let last_idx = snaps.len() - 1; - snaps.swap(0, last_idx); - snaps.truncate(1); - (group, snaps) - }) - .collect::>() - } + [] => SnapshotFile::group_from_backend(dbe, filter, group_by, &p)?, + [id] if id == "latest" => SnapshotFile::group_from_backend(dbe, filter, group_by, &p)? + .into_iter() + .map(|(group, mut snaps)| { + snaps.sort_unstable(); + let last_idx = snaps.len() - 1; + snaps.swap(0, last_idx); + snaps.truncate(1); + (group, snaps) + }) + .collect::>(), _ => { let item = ( SnapshotGroup::default(), - SnapshotFile::from_ids(&repo.dbe, ids, &p)?, + SnapshotFile::from_ids(dbe, ids, &p)?, ); vec![item] } diff --git a/crates/rustic_core/src/lib.rs b/crates/rustic_core/src/lib.rs index 72ed03617..a87674771 100644 --- a/crates/rustic_core/src/lib.rs +++ b/crates/rustic_core/src/lib.rs @@ -147,5 +147,5 @@ pub use crate::{ }, RepoFile, }, - repository::{read_password_from_reader, OpenRepository, Repository, RepositoryOptions}, + repository::{read_password_from_reader, Open, OpenStatus, Repository, RepositoryOptions}, }; diff --git a/crates/rustic_core/src/repository.rs b/crates/rustic_core/src/repository.rs index 4080ee1ce..97dbe22d1 100644 --- a/crates/rustic_core/src/repository.rs +++ b/crates/rustic_core/src/repository.rs @@ -37,8 +37,9 @@ use crate::{ crypto::aespoly1305::Key, error::RepositoryErrorKind, repofile::{configfile::ConfigFile, keyfile::find_key_in_backend}, - BlobType, Id, IndexBackend, NoProgressBars, Node, ProgressBars, PruneOpts, PrunePlan, - RusticResult, SnapshotFile, SnapshotGroup, SnapshotGroupCriterion, Tree, + BlobType, DecryptFullBackend, Id, IndexBackend, IndexedBackend, NoProgressBars, Node, + ProgressBars, PruneOpts, PrunePlan, RusticResult, SnapshotFile, SnapshotGroup, + SnapshotGroupCriterion, Tree, }; pub(super) mod constants { @@ -176,21 +177,22 @@ pub fn read_password_from_reader(file: &mut impl BufRead) -> RusticResult { +pub struct Repository { name: String, pub be: HotColdBackend, pub be_hot: Option, opts: RepositoryOptions, pub(crate) pb: P, + status: S, } -impl Repository { +impl Repository { pub fn new(opts: &RepositoryOptions) -> RusticResult { Self::new_with_progress(opts, NoProgressBars {}) } } -impl

Repository

{ +impl

Repository { pub fn new_with_progress(opts: &RepositoryOptions, pb: P) -> RusticResult { let be = match &opts.repository { Some(repo) => ChooseBackend::from_url(repo)?, @@ -226,6 +228,7 @@ impl

Repository

{ be_hot, opts: opts.clone(), pb, + status: (), }) } @@ -276,7 +279,7 @@ impl

Repository

{ } } - pub fn open(self) -> RusticResult> { + pub fn open(self) -> RusticResult> { let config_ids = match self.be.list(FileType::Config) { Ok(val) => val, Err(_e) => return Err(RepositoryErrorKind::ListingRepositoryConfigFileFailed.into()), @@ -320,24 +323,35 @@ impl

Repository

{ let zstd = config.zstd()?; dbe.set_zstd(zstd); - Ok(OpenRepository { - name: self.name, + let open = OpenStatus { key, dbe, cache, + config, + }; + + Ok(Repository { + name: self.name, be: self.be, be_hot: self.be_hot, - config, opts: self.opts, pb: self.pb, + status: open, }) } } -impl Repository

{ +impl Repository { pub fn infos_files(&self) -> RusticResult { commands::repoinfo::collect_file_infos(self) } + pub fn warm_up(&self, packs: impl ExactSizeIterator) -> RusticResult<()> { + warm_up(self, packs) + } + + pub fn warm_up_wait(&self, packs: impl ExactSizeIterator) -> RusticResult<()> { + warm_up_wait(self, packs) + } } pub(crate) fn get_key(be: &impl ReadBackend, password: Option) -> RusticResult { @@ -366,20 +380,56 @@ pub(crate) fn get_key(be: &impl ReadBackend, password: Option) -> Rustic Err(RepositoryErrorKind::IncorrectPassword.into()) } +pub trait Open { + type DBE: DecryptFullBackend; + fn key(&self) -> &Key; + fn cache(&self) -> Option<&Cache>; + fn dbe(&self) -> &Self::DBE; + fn config(&self) -> &ConfigFile; +} + +impl Open for Repository { + type DBE = S::DBE; + fn key(&self) -> &Key { + self.status.key() + } + fn cache(&self) -> Option<&Cache> { + self.status.cache() + } + fn dbe(&self) -> &Self::DBE { + self.status.dbe() + } + fn config(&self) -> &ConfigFile { + self.status.config() + } +} + #[derive(Debug)] -pub struct OpenRepository

{ - pub name: String, - pub be: HotColdBackend, - pub be_hot: Option, - pub key: Key, - pub cache: Option, - pub dbe: DecryptBackend>, Key>, - pub config: ConfigFile, - pub opts: RepositoryOptions, - pub(crate) pb: P, +pub struct OpenStatus { + key: Key, + cache: Option, + dbe: DecryptBackend>, Key>, + config: ConfigFile, +} + +impl Open for OpenStatus { + type DBE = DecryptBackend>, Key>; + + fn key(&self) -> &Key { + &self.key + } + fn cache(&self) -> Option<&Cache> { + self.cache.as_ref() + } + fn dbe(&self) -> &Self::DBE { + &self.dbe + } + fn config(&self) -> &ConfigFile { + &self.config + } } -impl OpenRepository

{ +impl Repository { pub fn get_snapshot_group( &self, ids: &[String], @@ -391,7 +441,7 @@ impl OpenRepository

{ pub fn get_snapshots(&self, ids: &[String]) -> RusticResult> { let p = self.pb.progress_counter("getting snapshots..."); - SnapshotFile::from_ids(&self.dbe, ids, &p) + SnapshotFile::from_ids(self.dbe(), ids, &p) } pub fn get_forget_snapshots( @@ -405,7 +455,7 @@ impl OpenRepository

{ pub fn delete_snapshots(&self, ids: &[Id]) -> RusticResult<()> { let p = self.pb.progress_counter("removing snapshots..."); - self.dbe + self.dbe() .delete_list(FileType::Snapshot, true, ids.iter(), p)?; Ok(()) } @@ -422,32 +472,71 @@ impl OpenRepository

{ opts.get_plan(self) } - pub fn to_indexed(self) -> RusticResult> { - let index = IndexBackend::new(&self.dbe, &self.pb.progress_counter(""))?; - Ok(IndexedRepository { repo: self, index }) + pub fn to_indexed(self) -> RusticResult>> { + let index = IndexBackend::new(self.dbe(), &self.pb.progress_counter(""))?; + let status = IndexedStatus { + open: self.status, + index, + }; + Ok(Repository { + name: self.name, + be: self.be, + be_hot: self.be_hot, + opts: self.opts, + pb: self.pb, + status, + }) } pub fn infos_index(&self) -> RusticResult { commands::repoinfo::collect_index_infos(self) } +} - pub fn warm_up(&self, packs: impl ExactSizeIterator) -> RusticResult<()> { - warm_up(self, packs) - } +pub trait Indexed: Open { + type I: IndexedBackend; + fn index(&self) -> &Self::I; +} - pub fn warm_up_wait(&self, packs: impl ExactSizeIterator) -> RusticResult<()> { - warm_up_wait(self, packs) +impl Indexed for Repository { + type I = S::I; + fn index(&self) -> &Self::I { + self.status.index() } } #[derive(Debug)] -pub struct IndexedRepository

{ - pub(crate) repo: OpenRepository

, - pub(crate) index: - IndexBackend>, Key>>, +pub struct IndexedStatus { + open: S, + index: IndexBackend, +} + +impl Indexed for IndexedStatus { + type I = IndexBackend; + + fn index(&self) -> &Self::I { + &self.index + } +} + +impl Open for IndexedStatus { + type DBE = S::DBE; + + fn key(&self) -> &Key { + self.open.key() + } + fn cache(&self) -> Option<&Cache> { + self.open.cache() + } + fn dbe(&self) -> &Self::DBE { + self.open.dbe() + } + fn config(&self) -> &ConfigFile { + self.open.config() + } } -impl IndexedRepository

{ +impl Repository { pub fn node_from_snapshot_path( &self, snap_path: &str, @@ -455,10 +544,10 @@ impl IndexedRepository

{ ) -> RusticResult { let (id, path) = snap_path.split_once(':').unwrap_or((snap_path, "")); - let p = &self.repo.pb.progress_counter("getting snapshot..."); - let snap = SnapshotFile::from_str(&self.repo.dbe, id, filter, p)?; + let p = &self.pb.progress_counter("getting snapshot..."); + let snap = SnapshotFile::from_str(self.dbe(), id, filter, p)?; - Tree::node_from_path(&self.index, snap.tree, Path::new(path)) + Tree::node_from_path(self.index(), snap.tree, Path::new(path)) } pub fn cat_blob(&self, tpe: BlobType, id: &str) -> RusticResult { diff --git a/crates/rustic_core/src/repository/warm_up.rs b/crates/rustic_core/src/repository/warm_up.rs index 433005cd0..7c70ca020 100644 --- a/crates/rustic_core/src/repository/warm_up.rs +++ b/crates/rustic_core/src/repository/warm_up.rs @@ -6,7 +6,7 @@ use rayon::ThreadPoolBuilder; use super::parse_command; use crate::{ - error::RepositoryErrorKind, FileType, Id, OpenRepository, Progress, ProgressBars, ReadBackend, + error::RepositoryErrorKind, FileType, Id, Progress, ProgressBars, ReadBackend, Repository, RusticResult, }; @@ -14,8 +14,8 @@ pub(super) mod constants { pub(super) const MAX_READER_THREADS_NUM: usize = 20; } -pub(crate) fn warm_up_wait( - repo: &OpenRepository

, +pub(crate) fn warm_up_wait( + repo: &Repository, packs: impl ExactSizeIterator, ) -> RusticResult<()> { warm_up(repo, packs)?; @@ -27,8 +27,8 @@ pub(crate) fn warm_up_wait( Ok(()) } -pub(crate) fn warm_up( - repo: &OpenRepository

, +pub(crate) fn warm_up( + repo: &Repository, packs: impl ExactSizeIterator, ) -> RusticResult<()> { if let Some(command) = &repo.opts.warm_up_command { @@ -61,8 +61,8 @@ fn warm_up_command( Ok(()) } -fn warm_up_access( - repo: &OpenRepository

, +fn warm_up_access( + repo: &Repository, packs: impl ExactSizeIterator, ) -> RusticResult<()> { let mut be = repo.be.clone(); diff --git a/src/commands.rs b/src/commands.rs index 731284c52..26f0b045a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -41,7 +41,7 @@ use crate::{ use abscissa_core::{ config::Override, status_err, Command, Configurable, FrameworkError, Runnable, Shutdown, }; -use rustic_core::{OpenRepository, Repository}; +use rustic_core::{OpenStatus, Repository}; /// Rustic Subcommands /// Subcommands need to be listed in an enum. @@ -167,7 +167,7 @@ impl Configurable for EntryPoint { } } -fn open_repository

(repo: Repository

) -> OpenRepository

{ +fn open_repository

(repo: Repository) -> Repository { match repo.open() { Ok(it) => it, Err(err) => { @@ -177,7 +177,7 @@ fn open_repository

(repo: Repository

) -> OpenRepository

{ } } -fn get_repository(config: &Arc) -> Repository { +fn get_repository(config: &Arc) -> Repository { let po = config.global.progress_options; match Repository::new_with_progress(&config.repository, po) { Ok(it) => it, diff --git a/src/commands/backup.rs b/src/commands/backup.rs index 26293087b..6a81ea0d7 100644 --- a/src/commands/backup.rs +++ b/src/commands/backup.rs @@ -22,7 +22,7 @@ use serde::Deserialize; use rustic_core::{ Archiver, DryRunBackend, IndexBackend, LocalSource, LocalSourceFilterOptions, - LocalSourceSaveOptions, PathList, ProgressBars, SnapshotFile, SnapshotGroup, + LocalSourceSaveOptions, Open, PathList, ProgressBars, SnapshotFile, SnapshotGroup, SnapshotGroupCriterion, SnapshotOptions, StdinSource, }; @@ -196,7 +196,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(); @@ -230,7 +230,7 @@ impl BackupCmd { // merge "backup" section from config file, if given opts.merge(config.backup.clone()); - let be = DryRunBackend::new(repo.dbe.clone(), config.global.dry_run); + let be = DryRunBackend::new(repo.dbe().clone(), config.global.dry_run); info!("starting to backup {source}..."); let as_path = opts.as_path.map(|p| { match p.parse_dot() { @@ -283,7 +283,7 @@ impl BackupCmd { let archiver = Archiver::new( be, index, - &repo.config, + repo.config(), parent_tree, opts.ignore_ctime, opts.ignore_inode, diff --git a/src/commands/config.rs b/src/commands/config.rs index b8c811c2d..3e13d008e 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -12,7 +12,7 @@ use abscissa_core::{Command, Runnable, Shutdown}; use anyhow::{bail, Result}; use bytesize::ByteSize; -use rustic_core::{ConfigFile, DecryptBackend, DecryptWriteBackend}; +use rustic_core::{ConfigFile, DecryptBackend, DecryptWriteBackend, Open}; /// `config` subcommand #[derive(clap::Parser, Command, Debug)] @@ -33,23 +33,24 @@ impl Runnable for ConfigCmd { impl ConfigCmd { fn inner_run(&self) -> Result<()> { let config = RUSTIC_APP.config(); - let mut repo = open_repository(get_repository(&config)); + let repo = open_repository(get_repository(&config)); - let mut new_config = repo.config.clone(); + let mut new_config = repo.config().clone(); self.config_opts.apply(&mut new_config)?; - if new_config == repo.config { + if &new_config == repo.config() { println!("config is unchanged"); } else { new_config.is_hot = None; // don't compress the config file - repo.dbe.set_zstd(None); + let mut dbe = repo.dbe().clone(); + dbe.set_zstd(None); // for hot/cold backend, this only saves the config to the cold repo. - _ = repo.dbe.save_file(&new_config)?; + _ = dbe.save_file(&new_config)?; - if let Some(hot_be) = repo.be_hot { + if let Some(hot_be) = repo.be_hot.clone() { // save config to hot repo - let mut dbe = DecryptBackend::new(&hot_be, repo.key); + let mut dbe = DecryptBackend::new(&hot_be, *repo.key()); // don't compress the config file dbe.set_zstd(None); new_config.is_hot = Some(true); diff --git a/src/commands/copy.rs b/src/commands/copy.rs index 0ff7cee51..32380bacf 100644 --- a/src/commands/copy.rs +++ b/src/commands/copy.rs @@ -16,7 +16,7 @@ use serde::Deserialize; use crate::commands::key::KeyOpts; use rustic_core::{ - FileType, Id, IndexBackend, ProgressBars, ReadBackend, Repository, RepositoryOptions, + FileType, Id, IndexBackend, Open, ProgressBars, ReadBackend, Repository, RepositoryOptions, SnapshotFile, }; @@ -61,7 +61,7 @@ impl CopyCmd { RUSTIC_APP.shutdown(Shutdown::Crash); } - let be = &repo.dbe; + 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), &p)? @@ -71,16 +71,15 @@ impl CopyCmd { // sort for nicer output snapshots.sort_unstable(); - let be = &repo.dbe; let index = IndexBackend::new(be, &config.global.progress_options.progress_counter(""))?; - let poly = repo.config.poly()?; + let poly = repo.config().poly()?; for target_opt in &config.copy.targets { let repo_dest = Repository::new(target_opt)?; if self.init && repo_dest.be.list(FileType::Config)?.is_empty() { - let mut config_dest = repo.config.clone(); + let mut config_dest = repo.config().clone(); config_dest.id = Id::random(); save_config( config_dest, @@ -92,8 +91,8 @@ impl CopyCmd { } let repo_dest = repo_dest.open()?; - info!("copying to target {}...", repo_dest.name); - if poly != repo_dest.config.poly()? { + info!("copying to target {:?}...", repo_dest); // TODO: repo_dest.name + if poly != repo_dest.config().poly()? { bail!("cannot copy to repository with different chunker parameter (re-chunking not implemented)!"); } copy(&snapshots, &index, &repo_dest)?; diff --git a/src/commands/diff.rs b/src/commands/diff.rs index b1c6e42fc..0614718e5 100644 --- a/src/commands/diff.rs +++ b/src/commands/diff.rs @@ -16,7 +16,7 @@ use anyhow::{anyhow, bail, Context, Result}; use rustic_core::{ hash, IndexBackend, LocalDestination, LocalSource, LocalSourceFilterOptions, - LocalSourceSaveOptions, Node, NodeStreamer, NodeType, Progress, ProgressBars, ReadIndex, + LocalSourceSaveOptions, Node, NodeStreamer, NodeType, Open, Progress, ProgressBars, ReadIndex, ReadSourceEntry, RusticResult, SnapshotFile, Tree, }; @@ -58,7 +58,7 @@ impl DiffCmd { let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; + let be = repo.dbe(); let (id1, path1) = arg_to_snap_path(&self.snap1, ""); let (id2, path2) = arg_to_snap_path(&self.snap2, path1); diff --git a/src/commands/key.rs b/src/commands/key.rs index 94607ab20..132558c06 100644 --- a/src/commands/key.rs +++ b/src/commands/key.rs @@ -14,7 +14,7 @@ use std::{fs::File, io::BufReader}; use dialoguer::Password; -use rustic_core::{hash, read_password_from_reader, FileType, KeyFile, WriteBackend}; +use rustic_core::{hash, read_password_from_reader, FileType, KeyFile, Open, WriteBackend}; /// `key` subcommand #[derive(clap::Parser, Command, Debug)] @@ -75,8 +75,8 @@ impl AddCmd { let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; - let key = repo.key; + let be = repo.dbe(); + let key = repo.key(); let pass = self.new_password_file.as_ref().map_or_else( || match Password::new() @@ -109,7 +109,7 @@ impl AddCmd { }, ); let ko = self.key_opts.clone(); - let keyfile = KeyFile::generate(key, &pass, ko.hostname, ko.username, ko.with_created)?; + let keyfile = KeyFile::generate(*key, &pass, ko.hostname, ko.username, ko.with_created)?; let data = serde_json::to_vec(&keyfile)?; let id = hash(&data); be.write_bytes(FileType::Key, &id, false, data.into())?; diff --git a/src/commands/list.rs b/src/commands/list.rs index e9b6d1ec7..eae7d5163 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -11,7 +11,7 @@ use abscissa_core::{Command, Runnable, Shutdown}; use anyhow::{bail, Result}; -use rustic_core::{DecryptReadBackend, FileType, IndexFile, ProgressBars, ReadBackend}; +use rustic_core::{DecryptReadBackend, FileType, IndexFile, Open, ProgressBars, ReadBackend}; /// `list` subcommand #[derive(clap::Parser, Command, Debug)] @@ -39,7 +39,7 @@ impl ListCmd { let tpe = match self.tpe.as_str() { // special treatment for listing blobs: read the index and display it "blobs" => { - repo.dbe + repo.dbe() .stream_all::(&config.global.progress_options.progress_hidden())? .into_iter() .for_each(|index| { diff --git a/src/commands/ls.rs b/src/commands/ls.rs index 8558ce9e8..d45deee39 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -13,7 +13,7 @@ use anyhow::Result; use std::path::Path; use rustic_core::{ - IndexBackend, NodeStreamer, ProgressBars, SnapshotFile, Tree, TreeStreamerOptions, + IndexBackend, NodeStreamer, Open, ProgressBars, SnapshotFile, Tree, TreeStreamerOptions, }; /// `ls` subcommand @@ -47,7 +47,7 @@ impl LsCmd { let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; + let be = repo.dbe(); let mut recursive = self.recursive; let (id, path) = self.snap.split_once(':').unwrap_or_else(|| { diff --git a/src/commands/merge.rs b/src/commands/merge.rs index 3904ea16b..e2156fb24 100644 --- a/src/commands/merge.rs +++ b/src/commands/merge.rs @@ -13,8 +13,8 @@ use log::info; use chrono::Local; use rustic_core::{ - merge_trees, BlobType, DecryptWriteBackend, FileType, Id, IndexBackend, Indexer, Node, Packer, - PathList, Progress, ProgressBars, ReadIndex, SnapshotFile, SnapshotOptions, Tree, + merge_trees, BlobType, DecryptWriteBackend, FileType, Id, IndexBackend, Indexer, Node, Open, + Packer, PathList, Progress, ProgressBars, ReadIndex, SnapshotFile, SnapshotOptions, Tree, }; /// `merge` subcommand @@ -59,7 +59,7 @@ impl MergeCmd { let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; + let be = repo.dbe(); let p = progress_options.progress_hidden(); let snapshots = if self.ids.is_empty() { @@ -75,7 +75,7 @@ impl MergeCmd { be.clone(), BlobType::Tree, indexer.clone(), - &repo.config, + repo.config(), index.total_size(BlobType::Tree), )?; diff --git a/src/commands/repair.rs b/src/commands/repair.rs index 5ebfa85e5..775109dd9 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, Progress, - ProgressBars, ReadBackend, ReadIndex, SnapshotFile, StringList, Tree, WriteBackend, + IndexPack, IndexedBackend, Indexer, NodeType, Open, PackHeader, PackHeaderRef, Packer, + Progress, ProgressBars, ReadBackend, ReadIndex, SnapshotFile, StringList, Tree, WriteBackend, }; /// `repair` subcommand @@ -89,7 +89,7 @@ impl IndexSubCmd { let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; + let be = repo.dbe(); let p = progress_options.progress_spinner("listing packs..."); let mut packs: HashMap<_, _> = be.list_with_size(FileType::Pack)?.into_iter().collect(); p.finish(); @@ -237,8 +237,8 @@ impl SnapSubCmd { let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; - let config_file = &repo.config; + let be = repo.dbe(); + let config_file = repo.config(); let p = progress_options.progress_hidden(); let snapshots = if self.ids.is_empty() { diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 568771b86..3a9c75027 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -29,7 +29,7 @@ use rayon::ThreadPoolBuilder; use rustic_core::{ hash, DecryptReadBackend, FileType, Id, IndexBackend, IndexedBackend, LocalDestination, Node, - NodeStreamer, NodeType, Progress, ProgressBars, RestoreStats, SnapshotFile, Tree, + NodeStreamer, NodeType, Open, Progress, ProgressBars, RestoreStats, SnapshotFile, Tree, TreeStreamerOptions, }; @@ -91,7 +91,7 @@ impl RestoreCmd { let config = RUSTIC_APP.config(); let progress_options = &config.global.progress_options; let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; + let be = repo.dbe(); let (id, path) = self.snap.split_once(':').unwrap_or((&self.snap, "")); let snap = SnapshotFile::from_str( diff --git a/src/commands/tag.rs b/src/commands/tag.rs index 14a26d065..1836884e1 100644 --- a/src/commands/tag.rs +++ b/src/commands/tag.rs @@ -12,7 +12,7 @@ use abscissa_core::{Command, Runnable, Shutdown}; use chrono::{Duration, Local}; use rustic_core::{ - DecryptWriteBackend, DeleteOption, FileType, Id, ProgressBars, SnapshotFile, StringList, + DecryptWriteBackend, DeleteOption, FileType, Id, Open, ProgressBars, SnapshotFile, StringList, }; /// `tag` subcommand @@ -81,7 +81,7 @@ impl TagCmd { let config = RUSTIC_APP.config(); let repo = open_repository(get_repository(&config)); - let be = &repo.dbe; + let be = repo.dbe(); let p = config.global.progress_options.progress_hidden(); let snapshots = if self.ids.is_empty() { diff --git a/src/helpers.rs b/src/helpers.rs index 8375cb6e1..9fb22039d 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -11,19 +11,19 @@ use log::{info, trace}; use rayon::prelude::{IntoParallelRefIterator, ParallelBridge, ParallelIterator}; use rustic_core::{ - BlobType, DecryptWriteBackend, IndexBackend, IndexedBackend, Indexer, NodeType, OpenRepository, - Packer, Progress, ProgressBars, ReadIndex, SnapshotFile, TreeStreamerOnce, + BlobType, DecryptWriteBackend, IndexBackend, IndexedBackend, Indexer, NodeType, Open, Packer, + Progress, ProgressBars, ReadIndex, Repository, SnapshotFile, TreeStreamerOnce, }; use crate::application::RUSTIC_APP; -pub(crate) fn copy

( +pub(crate) fn copy( snapshots: &[SnapshotFile], index: &impl IndexedBackend, - repo_dest: &OpenRepository

, + repo_dest: &Repository, ) -> Result<()> { let config = RUSTIC_APP.config(); - let be_dest = &repo_dest.dbe; + let be_dest = repo_dest.dbe(); let progress_options = &config.global.progress_options; let snapshots = relevant_snapshots( @@ -54,14 +54,14 @@ pub(crate) fn copy

( be_dest.clone(), BlobType::Data, indexer.clone(), - &repo_dest.config, + repo_dest.config(), index.total_size(BlobType::Data), )?; let tree_packer = Packer::new( be_dest.clone(), BlobType::Tree, indexer.clone(), - &repo_dest.config, + repo_dest.config(), index.total_size(BlobType::Tree), )?; @@ -121,9 +121,9 @@ pub(crate) fn copy

( Ok(()) } -pub(crate) fn relevant_snapshots( +pub(crate) fn relevant_snapshots( snaps: &[SnapshotFile], - dest_repo: &OpenRepository

, + dest_repo: &Repository, filter: F, p: &impl Progress, ) -> Result> @@ -131,7 +131,7 @@ 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, p)? + let snapshots_dest: BTreeSet<_> = SnapshotFile::all_from_backend(dest_repo.dbe(), filter, p)? .into_iter() .map(SnapshotFile::clear_ids) .collect();