rustic_rs/commands/
cat.rs1use crate::{Application, RUSTIC_APP, status_err};
4
5use abscissa_core::{Command, Runnable, Shutdown};
6
7use anyhow::Result;
8
9use rustic_core::repofile::{BlobType, FileType};
10
11#[derive(clap::Parser, Command, Debug)]
15pub(crate) struct CatCmd {
16 #[clap(subcommand)]
17 cmd: CatSubCmd,
18}
19
20#[derive(clap::Subcommand, Debug)]
22enum CatSubCmd {
23 TreeBlob(IdOpt),
25 DataBlob(IdOpt),
27 Config,
29 Index(IdOpt),
31 Snapshot(IdOpt),
33 Tree(TreeOpts),
35 Masterkey,
37}
38
39#[derive(Default, clap::Parser, Debug)]
40struct IdOpt {
41 id: String,
43}
44
45#[derive(clap::Parser, Debug)]
46struct TreeOpts {
47 #[clap(value_name = "SNAPSHOT[:PATH]")]
49 snap: String,
50}
51
52impl Runnable for CatCmd {
53 fn run(&self) {
54 if let Err(err) = self.inner_run() {
55 status_err!("{}", err);
56 RUSTIC_APP.shutdown(Shutdown::Crash);
57 };
58 }
59}
60
61impl CatCmd {
62 fn inner_run(&self) -> Result<()> {
63 let config = RUSTIC_APP.config();
64 let data = match &self.cmd {
65 CatSubCmd::Config => config
66 .repository
67 .run_open(|repo| Ok(repo.cat_file(FileType::Config, "")?))?,
68 CatSubCmd::Index(opt) => config
69 .repository
70 .run_open(|repo| Ok(repo.cat_file(FileType::Index, &opt.id)?))?,
71 CatSubCmd::Snapshot(opt) => config
72 .repository
73 .run_open(|repo| Ok(repo.cat_file(FileType::Snapshot, &opt.id)?))?,
74 CatSubCmd::TreeBlob(opt) => config
75 .repository
76 .run_indexed(|repo| Ok(repo.cat_blob(BlobType::Tree, &opt.id)?))?,
77 CatSubCmd::DataBlob(opt) => config
78 .repository
79 .run_indexed(|repo| Ok(repo.cat_blob(BlobType::Data, &opt.id)?))?,
80 CatSubCmd::Tree(opt) => config.repository.run_indexed(|repo| {
81 Ok(repo.cat_tree(&opt.snap, |sn| config.snapshot_filter.matches(sn))?)
82 })?,
83 CatSubCmd::Masterkey => config
84 .repository
85 .run_open(|repo| Ok(serde_json::to_vec(&repo.key())?.into()))?,
86 };
87 println!("{}", String::from_utf8(data.to_vec())?);
88
89 Ok(())
90 }
91}