Merge pull request #676 from rustic-rs/refactor-cat

move cat functions to rustic_core
This commit is contained in:
aawsome 2023-06-13 00:03:13 +02:00 committed by GitHub
commit 02f87ab477
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 56 deletions

View File

@ -1 +1,2 @@
pub mod cat;
pub mod check;

View 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)
}

View File

@ -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

View File

@ -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},

View File

@ -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(())
}