mirror of
https://github.com/rustic-rs/rustic.git
synced 2025-10-26 11:18:51 +00:00
use Repository states
This commit is contained in:
parent
fc90098670
commit
d3f2e73dc8
@ -7,9 +7,11 @@ fn main() {
|
||||
let _ = SimpleLogger::init(LevelFilter::Info, Config::default());
|
||||
|
||||
// Open repository
|
||||
let mut repo_opts = RepositoryOptions::default();
|
||||
repo_opts.repository = Some("/tmp/repo".to_string());
|
||||
repo_opts.password = Some("test".to_string());
|
||||
let repo_opts = RepositoryOptions {
|
||||
repository: Some("/tmp/repo".to_string()),
|
||||
password: Some("test".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let repo = Repository::new(&repo_opts).unwrap().open().unwrap();
|
||||
|
||||
// Check respository with standard options
|
||||
|
||||
@ -7,9 +7,11 @@ fn main() {
|
||||
let _ = SimpleLogger::init(LevelFilter::Info, Config::default());
|
||||
|
||||
// Open repository
|
||||
let mut repo_opts = RepositoryOptions::default();
|
||||
repo_opts.repository = Some("/tmp/repo".to_string());
|
||||
repo_opts.password = Some("test".to_string());
|
||||
let repo_opts = RepositoryOptions {
|
||||
repository: Some("/tmp/repo".to_string()),
|
||||
password: Some("test".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let repo = Repository::new(&repo_opts).unwrap().open().unwrap();
|
||||
|
||||
// Check respository with standard options
|
||||
|
||||
@ -7,9 +7,11 @@ fn main() {
|
||||
let _ = SimpleLogger::init(LevelFilter::Info, Config::default());
|
||||
|
||||
// Open repository
|
||||
let mut repo_opts = RepositoryOptions::default();
|
||||
repo_opts.repository = Some("/tmp/repo".to_string());
|
||||
repo_opts.password = Some("test".to_string());
|
||||
let repo_opts = RepositoryOptions {
|
||||
repository: Some("/tmp/repo".to_string()),
|
||||
password: Some("test".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let repo = Repository::new(&repo_opts).unwrap().open().unwrap();
|
||||
|
||||
let prune_opts = PruneOpts::default();
|
||||
|
||||
@ -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<P>(repo: &OpenRepository<P>, tpe: FileType, id: &str) -> RusticResult<Bytes> {
|
||||
let id = repo.dbe.find_id(tpe, id)?;
|
||||
let data = repo.dbe.read_encrypted_full(tpe, &id)?;
|
||||
pub(crate) fn cat_file<P, S: Open>(
|
||||
repo: &Repository<P, S>,
|
||||
tpe: FileType,
|
||||
id: &str,
|
||||
) -> RusticResult<Bytes> {
|
||||
let id = repo.dbe().find_id(tpe, id)?;
|
||||
let data = repo.dbe().read_encrypted_full(tpe, &id)?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn cat_blob<P>(repo: &IndexedRepository<P>, tpe: BlobType, id: &str) -> RusticResult<Bytes> {
|
||||
pub(crate) fn cat_blob<P, S: Indexed>(
|
||||
repo: &Repository<P, S>,
|
||||
tpe: BlobType,
|
||||
id: &str,
|
||||
) -> RusticResult<Bytes> {
|
||||
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<P: ProgressBars>(
|
||||
repo: &IndexedRepository<P>,
|
||||
pub(crate) fn cat_tree<P: ProgressBars, S: Indexed>(
|
||||
repo: &Repository<P, S>,
|
||||
snap: &str,
|
||||
sn_filter: impl FnMut(&SnapshotFile) -> bool + Send + Sync,
|
||||
) -> RusticResult<Bytes> {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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<P: ProgressBars>(self, repo: &OpenRepository<P>) -> RusticResult<()> {
|
||||
let be = &repo.dbe;
|
||||
let cache = &repo.cache;
|
||||
pub(crate) fn run<P: ProgressBars, S: Open>(self, repo: &Repository<P, S>) -> RusticResult<()> {
|
||||
let be = repo.dbe();
|
||||
let cache = repo.cache();
|
||||
let hot_be = &repo.be_hot;
|
||||
let raw_be = &repo.be;
|
||||
let pb = &repo.pb;
|
||||
|
||||
@ -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<P>(
|
||||
repo: &IndexedRepository<P>,
|
||||
pub(crate) fn dump<P, S: Indexed>(
|
||||
repo: &Repository<P, S>,
|
||||
node: &Node,
|
||||
w: &mut impl Write,
|
||||
) -> RusticResult<()> {
|
||||
@ -16,7 +17,7 @@ pub(crate) fn dump<P>(
|
||||
|
||||
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(())
|
||||
|
||||
@ -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<P: ProgressBars>(
|
||||
repo: &OpenRepository<P>,
|
||||
pub(crate) fn get_forget_snapshots<P: ProgressBars, S: Open>(
|
||||
repo: &Repository<P, S>,
|
||||
keep: &KeepOptions,
|
||||
group_by: SnapshotGroupCriterion,
|
||||
filter: impl FnMut(&SnapshotFile) -> bool,
|
||||
|
||||
@ -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<P: ProgressBars>(&self, repo: &OpenRepository<P>) -> RusticResult<PrunePlan> {
|
||||
pub fn get_plan<P: ProgressBars, S: Open>(
|
||||
&self,
|
||||
repo: &Repository<P, S>,
|
||||
) -> RusticResult<PrunePlan> {
|
||||
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<P: ProgressBars>(
|
||||
pub fn do_prune<P: ProgressBars, S: Open>(
|
||||
self,
|
||||
repo: &OpenRepository<P>,
|
||||
repo: &Repository<P, S>,
|
||||
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<HashMap<Id, u8>> {
|
||||
|
||||
@ -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<P: ProgressBars>(
|
||||
repo: &OpenRepository<P>,
|
||||
pub(crate) fn collect_index_infos<P: ProgressBars, S: Open>(
|
||||
repo: &Repository<P, S>,
|
||||
) -> RusticResult<IndexInfos> {
|
||||
let mut blob_info = BlobTypeMap::<()>::default().map(|blob_type, _| BlobInfo {
|
||||
blob_type,
|
||||
@ -72,7 +73,7 @@ pub(crate) fn collect_index_infos<P: ProgressBars>(
|
||||
let mut pack_info_delete = pack_info;
|
||||
|
||||
let p = repo.pb.progress_counter("scanning index...");
|
||||
for index in repo.dbe.stream_all::<IndexFile>(&p)? {
|
||||
for index in repo.dbe().stream_all::<IndexFile>(&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<Vec<RepoF
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
pub fn collect_file_infos<P: ProgressBars>(repo: &Repository<P>) -> RusticResult<RepoFileInfos> {
|
||||
pub fn collect_file_infos<P: ProgressBars, S>(
|
||||
repo: &Repository<P, S>,
|
||||
) -> RusticResult<RepoFileInfos> {
|
||||
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()?;
|
||||
|
||||
@ -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<P: ProgressBars>(
|
||||
repo: &OpenRepository<P>,
|
||||
pub(crate) fn get_snapshot_group<P: ProgressBars, S: Open>(
|
||||
repo: &Repository<P, S>,
|
||||
ids: &[String],
|
||||
group_by: SnapshotGroupCriterion,
|
||||
filter: impl FnMut(&SnapshotFile) -> bool,
|
||||
) -> RusticResult<Vec<(SnapshotGroup, Vec<SnapshotFile>)>> {
|
||||
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::<Vec<_>>()
|
||||
}
|
||||
[] => 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::<Vec<_>>(),
|
||||
_ => {
|
||||
let item = (
|
||||
SnapshotGroup::default(),
|
||||
SnapshotFile::from_ids(&repo.dbe, ids, &p)?,
|
||||
SnapshotFile::from_ids(dbe, ids, &p)?,
|
||||
);
|
||||
vec![item]
|
||||
}
|
||||
|
||||
@ -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},
|
||||
};
|
||||
|
||||
@ -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<String
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Repository<P> {
|
||||
pub struct Repository<P, S> {
|
||||
name: String,
|
||||
pub be: HotColdBackend<ChooseBackend>,
|
||||
pub be_hot: Option<ChooseBackend>,
|
||||
opts: RepositoryOptions,
|
||||
pub(crate) pb: P,
|
||||
status: S,
|
||||
}
|
||||
|
||||
impl Repository<NoProgressBars> {
|
||||
impl Repository<NoProgressBars, ()> {
|
||||
pub fn new(opts: &RepositoryOptions) -> RusticResult<Self> {
|
||||
Self::new_with_progress(opts, NoProgressBars {})
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> Repository<P> {
|
||||
impl<P> Repository<P, ()> {
|
||||
pub fn new_with_progress(opts: &RepositoryOptions, pb: P) -> RusticResult<Self> {
|
||||
let be = match &opts.repository {
|
||||
Some(repo) => ChooseBackend::from_url(repo)?,
|
||||
@ -226,6 +228,7 @@ impl<P> Repository<P> {
|
||||
be_hot,
|
||||
opts: opts.clone(),
|
||||
pb,
|
||||
status: (),
|
||||
})
|
||||
}
|
||||
|
||||
@ -276,11 +279,11 @@ impl<P> Repository<P> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(self) -> RusticResult<OpenRepository<P>> {
|
||||
let config_ids = match self.be.list(FileType::Config) {
|
||||
Ok(val) => val,
|
||||
Err(_e) => return Err(RepositoryErrorKind::ListingRepositoryConfigFileFailed.into()),
|
||||
};
|
||||
pub fn open(self) -> RusticResult<Repository<P, OpenStatus>> {
|
||||
let config_ids = self
|
||||
.be
|
||||
.list(FileType::Config)
|
||||
.map_err(|_| RepositoryErrorKind::ListingRepositoryConfigFileFailed)?;
|
||||
|
||||
match config_ids.len() {
|
||||
1 => {} // ok, continue
|
||||
@ -320,24 +323,35 @@ impl<P> Repository<P> {
|
||||
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<P: ProgressBars> Repository<P> {
|
||||
impl<P: ProgressBars, S> Repository<P, S> {
|
||||
pub fn infos_files(&self) -> RusticResult<RepoFileInfos> {
|
||||
commands::repoinfo::collect_file_infos(self)
|
||||
}
|
||||
pub fn warm_up(&self, packs: impl ExactSizeIterator<Item = Id>) -> RusticResult<()> {
|
||||
warm_up(self, packs)
|
||||
}
|
||||
|
||||
pub fn warm_up_wait(&self, packs: impl ExactSizeIterator<Item = Id>) -> RusticResult<()> {
|
||||
warm_up_wait(self, packs)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_key(be: &impl ReadBackend, password: Option<String>) -> RusticResult<Key> {
|
||||
@ -366,20 +380,56 @@ pub(crate) fn get_key(be: &impl ReadBackend, password: Option<String>) -> Rustic
|
||||
Err(RepositoryErrorKind::IncorrectPassword.into())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OpenRepository<P> {
|
||||
pub name: String,
|
||||
pub be: HotColdBackend<ChooseBackend>,
|
||||
pub be_hot: Option<ChooseBackend>,
|
||||
pub key: Key,
|
||||
pub cache: Option<Cache>,
|
||||
pub dbe: DecryptBackend<CachedBackend<HotColdBackend<ChooseBackend>>, Key>,
|
||||
pub config: ConfigFile,
|
||||
pub opts: RepositoryOptions,
|
||||
pub(crate) pb: P,
|
||||
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<P: ProgressBars> OpenRepository<P> {
|
||||
impl<P, S: Open> Open for Repository<P, S> {
|
||||
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 OpenStatus {
|
||||
key: Key,
|
||||
cache: Option<Cache>,
|
||||
dbe: DecryptBackend<CachedBackend<HotColdBackend<ChooseBackend>>, Key>,
|
||||
config: ConfigFile,
|
||||
}
|
||||
|
||||
impl Open for OpenStatus {
|
||||
type DBE = DecryptBackend<CachedBackend<HotColdBackend<ChooseBackend>>, 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<P: ProgressBars, S: Open> Repository<P, S> {
|
||||
pub fn get_snapshot_group(
|
||||
&self,
|
||||
ids: &[String],
|
||||
@ -391,7 +441,7 @@ impl<P: ProgressBars> OpenRepository<P> {
|
||||
|
||||
pub fn get_snapshots(&self, ids: &[String]) -> RusticResult<Vec<SnapshotFile>> {
|
||||
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<P: ProgressBars> OpenRepository<P> {
|
||||
|
||||
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<P: ProgressBars> OpenRepository<P> {
|
||||
opts.get_plan(self)
|
||||
}
|
||||
|
||||
pub fn to_indexed(self) -> RusticResult<IndexedRepository<P>> {
|
||||
let index = IndexBackend::new(&self.dbe, &self.pb.progress_counter(""))?;
|
||||
Ok(IndexedRepository { repo: self, index })
|
||||
pub fn to_indexed(self) -> RusticResult<Repository<P, IndexedStatus<S>>> {
|
||||
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<IndexInfos> {
|
||||
commands::repoinfo::collect_index_infos(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warm_up(&self, packs: impl ExactSizeIterator<Item = Id>) -> 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<Item = Id>) -> RusticResult<()> {
|
||||
warm_up_wait(self, packs)
|
||||
impl<P, S: Indexed> Indexed for Repository<P, S> {
|
||||
type I = S::I;
|
||||
fn index(&self) -> &Self::I {
|
||||
self.status.index()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IndexedRepository<P> {
|
||||
pub(crate) repo: OpenRepository<P>,
|
||||
pub(crate) index:
|
||||
IndexBackend<DecryptBackend<CachedBackend<HotColdBackend<ChooseBackend>>, Key>>,
|
||||
pub struct IndexedStatus<S: Open> {
|
||||
open: S,
|
||||
index: IndexBackend<S::DBE>,
|
||||
}
|
||||
|
||||
impl<P: ProgressBars> IndexedRepository<P> {
|
||||
impl<S: Open> Indexed for IndexedStatus<S> {
|
||||
type I = IndexBackend<S::DBE>;
|
||||
|
||||
fn index(&self) -> &Self::I {
|
||||
&self.index
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Open> Open for IndexedStatus<S> {
|
||||
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<P: ProgressBars, S: Indexed> Repository<P, S> {
|
||||
pub fn node_from_snapshot_path(
|
||||
&self,
|
||||
snap_path: &str,
|
||||
@ -455,10 +544,10 @@ impl<P: ProgressBars> IndexedRepository<P> {
|
||||
) -> RusticResult<Node> {
|
||||
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<Bytes> {
|
||||
|
||||
@ -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<P: ProgressBars>(
|
||||
repo: &OpenRepository<P>,
|
||||
pub(crate) fn warm_up_wait<P: ProgressBars, S>(
|
||||
repo: &Repository<P, S>,
|
||||
packs: impl ExactSizeIterator<Item = Id>,
|
||||
) -> RusticResult<()> {
|
||||
warm_up(repo, packs)?;
|
||||
@ -27,8 +27,8 @@ pub(crate) fn warm_up_wait<P: ProgressBars>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn warm_up<P: ProgressBars>(
|
||||
repo: &OpenRepository<P>,
|
||||
pub(crate) fn warm_up<P: ProgressBars, S>(
|
||||
repo: &Repository<P, S>,
|
||||
packs: impl ExactSizeIterator<Item = Id>,
|
||||
) -> RusticResult<()> {
|
||||
if let Some(command) = &repo.opts.warm_up_command {
|
||||
@ -61,8 +61,8 @@ fn warm_up_command<P: ProgressBars>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn warm_up_access<P: ProgressBars>(
|
||||
repo: &OpenRepository<P>,
|
||||
fn warm_up_access<P: ProgressBars, S>(
|
||||
repo: &Repository<P, S>,
|
||||
packs: impl ExactSizeIterator<Item = Id>,
|
||||
) -> RusticResult<()> {
|
||||
let mut be = repo.be.clone();
|
||||
|
||||
@ -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<RusticConfig> for EntryPoint {
|
||||
}
|
||||
}
|
||||
|
||||
fn open_repository<P>(repo: Repository<P>) -> OpenRepository<P> {
|
||||
fn open_repository<P>(repo: Repository<P, ()>) -> Repository<P, OpenStatus> {
|
||||
match repo.open() {
|
||||
Ok(it) => it,
|
||||
Err(err) => {
|
||||
@ -177,7 +177,7 @@ fn open_repository<P>(repo: Repository<P>) -> OpenRepository<P> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_repository(config: &Arc<RusticConfig>) -> Repository<ProgressOptions> {
|
||||
fn get_repository(config: &Arc<RusticConfig>) -> Repository<ProgressOptions, ()> {
|
||||
let po = config.global.progress_options;
|
||||
match Repository::new_with_progress(&config.repository, po) {
|
||||
Ok(it) => it,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)?;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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())?;
|
||||
|
||||
@ -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::<IndexFile>(&config.global.progress_options.progress_hidden())?
|
||||
.into_iter()
|
||||
.for_each(|index| {
|
||||
|
||||
@ -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(|| {
|
||||
|
||||
@ -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),
|
||||
)?;
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -131,13 +131,11 @@ fn get_config_paths(filename: &str) -> Vec<PathBuf> {
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn get_global_config_path() -> Option<PathBuf> {
|
||||
if let Some(program_data) = std::env::var_os("PROGRAMDATA") {
|
||||
std::env::var_os("PROGRAMDATA").map(|program_data| {
|
||||
let mut path = PathBuf::from(program_data);
|
||||
path.push(r"rustic\config");
|
||||
Some(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
path
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "ios", target_arch = "wasm32"))]
|
||||
|
||||
@ -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<P>(
|
||||
pub(crate) fn copy<P, S: Open>(
|
||||
snapshots: &[SnapshotFile],
|
||||
index: &impl IndexedBackend,
|
||||
repo_dest: &OpenRepository<P>,
|
||||
repo_dest: &Repository<P, S>,
|
||||
) -> 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<P>(
|
||||
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<P>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn relevant_snapshots<F, P>(
|
||||
pub(crate) fn relevant_snapshots<F, P, S: Open>(
|
||||
snaps: &[SnapshotFile],
|
||||
dest_repo: &OpenRepository<P>,
|
||||
dest_repo: &Repository<P, S>,
|
||||
filter: F,
|
||||
p: &impl Progress,
|
||||
) -> Result<Vec<SnapshotFile>>
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user