Skip to main content

rustic_rs/commands/
list.rs

1//! `list` subcommand
2
3use std::num::NonZero;
4
5use crate::{Application, RUSTIC_APP, repository::OpenRepo, 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: OpenRepo) -> Result<()> {
35        let config = RUSTIC_APP.config();
36        match self.tpe.as_str() {
37            // special treatment for listing blobs: read the index and display it
38            "blobs" | "indexpacks" | "indexcontent" => {
39                for item in repo.stream_files::<IndexFile>()? {
40                    let (_, index) = item?;
41                    for pack in index.packs {
42                        match self.tpe.as_str() {
43                            "blobs" => {
44                                for blob in pack.blobs {
45                                    println!("{:?} {:?}", blob.tpe, blob.id);
46                                }
47                            }
48                            "indexcontent" => {
49                                for blob in pack.blobs {
50                                    println!(
51                                        "{:?} {:?} {:?} {} {}",
52                                        blob.tpe,
53                                        blob.id,
54                                        pack.id,
55                                        blob.location.length,
56                                        blob.location.uncompressed_length.map_or(0, NonZero::get)
57                                    );
58                                }
59                            }
60                            "indexpacks" => println!(
61                                "{:?} {:?} {} {}",
62                                pack.blob_type(),
63                                pack.id,
64                                pack.pack_size(),
65                                pack.time.map_or_else(String::new, |time| config
66                                    .global
67                                    .format_timestamp(time))
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}