Skip to main content

rustic_rs/commands/
cat.rs

1//! `cat` subcommand
2
3use 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/// `cat` subcommand
12///
13/// Output the contents of a file or blob
14#[derive(clap::Parser, Command, Debug)]
15pub(crate) struct CatCmd {
16    #[clap(subcommand)]
17    cmd: CatSubCmd,
18}
19
20/// `cat` subcommands
21#[derive(clap::Subcommand, Debug)]
22enum CatSubCmd {
23    /// Display a tree blob
24    TreeBlob(IdOpt),
25    /// Display a data blob
26    DataBlob(IdOpt),
27    /// Display the config file
28    Config,
29    /// Display an index file
30    Index(IdOpt),
31    /// Display a snapshot file
32    Snapshot(IdOpt),
33    /// Display a tree within a snapshot
34    Tree(TreeOpts),
35    /// Display the masterkey
36    Masterkey,
37}
38
39#[derive(Default, clap::Parser, Debug)]
40struct IdOpt {
41    /// Id to display
42    id: String,
43}
44
45#[derive(clap::Parser, Debug)]
46struct TreeOpts {
47    /// Snapshot/path of the tree to display
48    #[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}