mirror of
https://github.com/rustic-rs/rustic.git
synced 2025-10-26 11:18:51 +00:00
Merge pull request #676 from rustic-rs/refactor-cat
move cat functions to rustic_core
This commit is contained in:
commit
02f87ab477
@ -1 +1,2 @@
|
||||
pub mod cat;
|
||||
pub mod check;
|
||||
|
||||
43
crates/rustic_core/src/commands/cat.rs
Normal file
43
crates/rustic_core/src/commands/cat.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use std::path::Path;
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
use crate::{
|
||||
error::CommandErrorKind, BlobType, DecryptReadBackend, FileType, Id, IndexBackend,
|
||||
IndexedBackend, OpenRepository, ProgressBars, ReadBackend, RusticResult, SnapshotFile, Tree,
|
||||
};
|
||||
|
||||
pub fn cat_file(repo: &OpenRepository, 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(
|
||||
repo: &OpenRepository,
|
||||
tpe: BlobType,
|
||||
id: &str,
|
||||
pb: &impl ProgressBars,
|
||||
) -> RusticResult<Bytes> {
|
||||
let id = Id::from_hex(id)?;
|
||||
let data = IndexBackend::new(&repo.dbe, &pb.progress_hidden())?.blob_from_backend(tpe, &id)?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn cat_tree(
|
||||
repo: &OpenRepository,
|
||||
snap: &str,
|
||||
sn_filter: impl FnMut(&SnapshotFile) -> bool + Send + Sync,
|
||||
pb: &impl ProgressBars,
|
||||
) -> RusticResult<Bytes> {
|
||||
let (id, path) = snap.split_once(':').unwrap_or((snap, ""));
|
||||
let snap = SnapshotFile::from_str(&repo.dbe, id, sn_filter, &pb.progress_counter(""))?;
|
||||
let index = IndexBackend::new(&repo.dbe, &pb.progress_counter(""))?;
|
||||
let node = Tree::node_from_path(&index, snap.tree, Path::new(path))?;
|
||||
let id = node
|
||||
.subtree
|
||||
.ok_or_else(|| CommandErrorKind::PathIsNoDir(path.to_string()))?;
|
||||
let data = index.blob_from_backend(BlobType::Tree, &id)?;
|
||||
Ok(data)
|
||||
}
|
||||
@ -42,6 +42,10 @@ impl RusticError {
|
||||
#[non_exhaustive]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RusticErrorKind {
|
||||
/// [`CommandErrorKind`] describes the errors that can happen while executing a high-level command
|
||||
#[error(transparent)]
|
||||
Command(#[from] CommandErrorKind),
|
||||
|
||||
/// [`CryptoErrorKind`] describes the errors that can happen while dealing with Cryptographic functions
|
||||
#[error(transparent)]
|
||||
Crypto(#[from] CryptoErrorKind),
|
||||
@ -135,6 +139,13 @@ pub enum RusticErrorKind {
|
||||
StdIo(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
/// [`CommandErrorKind`] describes the errors that can happen while executing a high-level command
|
||||
#[derive(Error, Debug, Display)]
|
||||
pub enum CommandErrorKind {
|
||||
/// path is no dir: `{0:?}`
|
||||
PathIsNoDir(String),
|
||||
}
|
||||
|
||||
/// [`CryptoErrorKind`] describes the errors that can happen while dealing with Cryptographic functions
|
||||
#[derive(Error, Debug, Display, Copy, Clone)]
|
||||
pub enum CryptoErrorKind {
|
||||
@ -741,6 +752,7 @@ impl RusticErrorMarker for ProviderErrorKind {}
|
||||
impl RusticErrorMarker for RestErrorKind {}
|
||||
impl RusticErrorMarker for StdInErrorKind {}
|
||||
impl RusticErrorMarker for ArchiverErrorKind {}
|
||||
impl RusticErrorMarker for CommandErrorKind {}
|
||||
impl RusticErrorMarker for std::io::Error {}
|
||||
|
||||
impl<E> From<E> for RusticError
|
||||
|
||||
@ -120,7 +120,10 @@ pub use crate::{
|
||||
BlobLocation, BlobType, BlobTypeMap, Initialize, Sum,
|
||||
},
|
||||
chunker::random_poly,
|
||||
commands::check::CheckOpts,
|
||||
commands::{
|
||||
cat::{cat_blob, cat_file, cat_tree},
|
||||
check::CheckOpts,
|
||||
},
|
||||
crypto::{aespoly1305::Key, hasher::hash},
|
||||
error::{RusticError, RusticResult},
|
||||
file::{AddFileResult, FileInfos, RestoreStats},
|
||||
|
||||
@ -9,14 +9,9 @@ use crate::{
|
||||
|
||||
use abscissa_core::{Command, Runnable, Shutdown};
|
||||
|
||||
use std::path::Path;
|
||||
use anyhow::Result;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
use rustic_core::{
|
||||
BlobType, DecryptReadBackend, FileType, Id, IndexBackend, IndexedBackend, ProgressBars,
|
||||
SnapshotFile, Tree,
|
||||
};
|
||||
use rustic_core::{cat_blob, cat_file, cat_tree, BlobType, FileType};
|
||||
|
||||
/// `cat` subcommand
|
||||
#[derive(clap::Parser, Command, Debug)]
|
||||
@ -66,59 +61,27 @@ impl Runnable for CatCmd {
|
||||
impl CatCmd {
|
||||
fn inner_run(&self) -> Result<()> {
|
||||
let config = RUSTIC_APP.config();
|
||||
let po = config.global.progress_options;
|
||||
|
||||
let repo = open_repository(get_repository(&config));
|
||||
|
||||
let be = &repo.dbe;
|
||||
|
||||
match &self.cmd {
|
||||
CatSubCmd::Config => cat_file(be, FileType::Config, &IdOpt::default()),
|
||||
CatSubCmd::Index(opt) => cat_file(be, FileType::Index, opt),
|
||||
CatSubCmd::Snapshot(opt) => cat_file(be, FileType::Snapshot, opt),
|
||||
// special treatment for catingg blobs: read the index and use it to locate the blob
|
||||
CatSubCmd::TreeBlob(opt) => cat_blob(be, BlobType::Tree, opt),
|
||||
CatSubCmd::DataBlob(opt) => cat_blob(be, BlobType::Data, opt),
|
||||
let data = match &self.cmd {
|
||||
CatSubCmd::Config => cat_file(&repo, FileType::Config, "")?,
|
||||
CatSubCmd::Index(opt) => cat_file(&repo, FileType::Index, &opt.id)?,
|
||||
CatSubCmd::Snapshot(opt) => cat_file(&repo, FileType::Snapshot, &opt.id)?,
|
||||
// special treatment for cating blobs: read the index and use it to locate the blob
|
||||
CatSubCmd::TreeBlob(opt) => cat_blob(&repo, BlobType::Tree, &opt.id, &po)?,
|
||||
CatSubCmd::DataBlob(opt) => cat_blob(&repo, BlobType::Data, &opt.id, &po)?,
|
||||
// special treatment for cating a tree within a snapshot
|
||||
CatSubCmd::Tree(opts) => cat_tree(be, opts),
|
||||
}?;
|
||||
CatSubCmd::Tree(opt) => cat_tree(
|
||||
&repo,
|
||||
&opt.snap,
|
||||
|sn| config.snapshot_filter.matches(sn),
|
||||
&po,
|
||||
)?,
|
||||
};
|
||||
println!("{}", String::from_utf8(data.to_vec())?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn cat_file(be: &impl DecryptReadBackend, tpe: FileType, opt: &IdOpt) -> Result<()> {
|
||||
let id = be.find_id(tpe, &opt.id)?;
|
||||
let data = be.read_encrypted_full(tpe, &id)?;
|
||||
println!("{}", String::from_utf8(data.to_vec())?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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, &config.global.progress_options.progress_hidden())?
|
||||
.blob_from_backend(tpe, &id)?;
|
||||
print!("{}", String::from_utf8(data.to_vec())?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cat_tree(be: &impl DecryptReadBackend, opts: &TreeOpts) -> Result<()> {
|
||||
let config = RUSTIC_APP.config();
|
||||
|
||||
let (id, path) = opts.snap.split_once(':').unwrap_or((&opts.snap, ""));
|
||||
let snap = SnapshotFile::from_str(
|
||||
be,
|
||||
id,
|
||||
|sn| config.snapshot_filter.matches(sn),
|
||||
&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)?;
|
||||
println!("{}", String::from_utf8(data.to_vec())?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user