rustic_rs/commands/
list.rs

1//! `list` subcommand
2
3use std::num::NonZero;
4
5use crate::{Application, RUSTIC_APP, repository::CliOpenRepo, status_err};
6
7use abscissa_core::{Command, Runnable, Shutdown};
8use anyhow::{Result, bail};
9
10use rustic_core::repofile::{IndexFile, IndexId, KeyId, PackId, SnapshotId};
11
12/// `list` subcommand
13#[derive(clap::Parser, Command, Debug)]
14pub(crate) struct ListCmd {
15    /// File types to list
16    #[clap(value_parser=["blobs", "indexpacks", "indexcontent", "index", "packs", "snapshots", "keys"])]
17    tpe: String,
18}
19
20impl Runnable for ListCmd {
21    fn run(&self) {
22        if let Err(err) = RUSTIC_APP
23            .config()
24            .repository
25            .run_open(|repo| self.inner_run(repo))
26        {
27            status_err!("{}", err);
28            RUSTIC_APP.shutdown(Shutdown::Crash);
29        };
30    }
31}
32
33impl ListCmd {
34    fn inner_run(&self, repo: CliOpenRepo) -> Result<()> {
35        match self.tpe.as_str() {
36            // special treatment for listing blobs: read the index and display it
37            "blobs" | "indexpacks" | "indexcontent" => {
38                for item in repo.stream_files::<IndexFile>()? {
39                    let (_, index) = item?;
40                    for pack in index.packs {
41                        match self.tpe.as_str() {
42                            "blobs" => {
43                                for blob in pack.blobs {
44                                    println!("{:?} {:?}", blob.tpe, blob.id);
45                                }
46                            }
47                            "indexcontent" => {
48                                for blob in pack.blobs {
49                                    println!(
50                                        "{:?} {:?} {:?} {} {}",
51                                        blob.tpe,
52                                        blob.id,
53                                        pack.id,
54                                        blob.length,
55                                        blob.uncompressed_length.map_or(0, NonZero::get)
56                                    );
57                                }
58                            }
59                            "indexpacks" => println!(
60                                "{:?} {:?} {} {}",
61                                pack.blob_type(),
62                                pack.id,
63                                pack.pack_size(),
64                                pack.time.map_or_else(String::new, |time| format!(
65                                    "{}",
66                                    time.format("%Y-%m-%d %H:%M:%S")
67                                ))
68                            ),
69                            t => {
70                                bail!("invalid type: {}", t);
71                            }
72                        }
73                    }
74                }
75            }
76            "index" => {
77                for id in repo.list::<IndexId>()? {
78                    println!("{id:?}");
79                }
80            }
81            "packs" => {
82                for id in repo.list::<PackId>()? {
83                    println!("{id:?}");
84                }
85            }
86            "snapshots" => {
87                for id in repo.list::<SnapshotId>()? {
88                    println!("{id:?}");
89                }
90            }
91            "keys" => {
92                for id in repo.list::<KeyId>()? {
93                    println!("{id:?}");
94                }
95            }
96            t => {
97                bail!("invalid type: {}", t);
98            }
99        };
100
101        Ok(())
102    }
103}