summaryrefslogtreecommitdiff
path: root/src/cmd/show_gen.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/show_gen.rs')
-rw-r--r--src/cmd/show_gen.rs123
1 files changed, 89 insertions, 34 deletions
diff --git a/src/cmd/show_gen.rs b/src/cmd/show_gen.rs
index d355389..95d3fd3 100644
--- a/src/cmd/show_gen.rs
+++ b/src/cmd/show_gen.rs
@@ -1,46 +1,101 @@
+//! The `show-generation` subcommand.
+
+use crate::chunk::ClientTrust;
use crate::client::BackupClient;
-use crate::client::ClientConfig;
+use crate::config::ClientConfig;
+use crate::db::DbInt;
use crate::error::ObnamError;
use crate::fsentry::FilesystemKind;
+use crate::generation::GenId;
+use clap::Parser;
use indicatif::HumanBytes;
+use serde::Serialize;
use tempfile::NamedTempFile;
+use tokio::runtime::Runtime;
+
+/// Show information about a generation.
+#[derive(Debug, Parser)]
+pub struct ShowGeneration {
+ /// Reference to the generation. Defaults to latest.
+ #[clap(default_value = "latest")]
+ gen_id: String,
+}
-pub fn show_generation(config: &ClientConfig, gen_ref: &str) -> anyhow::Result<()> {
- // Create a named temporary file. We don't meed the open file
- // handle, so we discard that.
- let dbname = {
+impl ShowGeneration {
+ /// Run the command.
+ pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> {
+ let rt = Runtime::new()?;
+ rt.block_on(self.run_async(config))
+ }
+
+ async fn run_async(&self, config: &ClientConfig) -> Result<(), ObnamError> {
let temp = NamedTempFile::new()?;
- let (_, dbname) = temp.keep()?;
- dbname
- };
-
- let client = BackupClient::new(&config.server_url)?;
-
- let genlist = client.list_generations()?;
- let gen_id: String = match genlist.resolve(gen_ref) {
- None => return Err(ObnamError::UnknownGeneration(gen_ref.to_string()).into()),
- Some(id) => id,
- };
-
- let gen = client.fetch_generation(&gen_id, &dbname)?;
- let files = gen.files()?;
-
- let total_bytes = files.iter().fold(0, |acc, file| {
- let e = file.entry();
- if e.kind() == FilesystemKind::Regular {
- acc + file.entry().len()
- } else {
- acc
+ let client = BackupClient::new(config)?;
+ let trust = client
+ .get_client_trust()
+ .await?
+ .or_else(|| Some(ClientTrust::new("FIXME", None, "".to_string(), vec![])))
+ .unwrap();
+
+ let genlist = client.list_generations(&trust);
+ let gen_id = genlist.resolve(&self.gen_id)?;
+ let gen = client.fetch_generation(&gen_id, temp.path()).await?;
+ let mut files = gen.files()?;
+ let mut files = files.iter()?;
+
+ let total_bytes = files.try_fold(0, |acc, file| {
+ file.map(|(_, e, _, _)| {
+ if e.kind() == FilesystemKind::Regular {
+ acc + e.len()
+ } else {
+ acc
+ }
+ })
+ });
+ let total_bytes = total_bytes?;
+
+ let output = Output::new(gen_id)
+ .db_bytes(temp.path().metadata()?.len())
+ .file_count(gen.file_count()?)
+ .file_bytes(total_bytes);
+ serde_json::to_writer_pretty(std::io::stdout(), &output)?;
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Default, Serialize)]
+struct Output {
+ generation_id: String,
+ file_count: DbInt,
+ file_bytes: String,
+ file_bytes_raw: u64,
+ db_bytes: String,
+ db_bytes_raw: u64,
+}
+
+impl Output {
+ fn new(gen_id: GenId) -> Self {
+ Self {
+ generation_id: format!("{}", gen_id),
+ ..Self::default()
}
- });
+ }
- println!("generation-id: {}", gen_id);
- println!("file-count: {}", gen.file_count()?);
- println!("file-bytes: {}", HumanBytes(total_bytes));
- println!("file-bytes-raw: {}", total_bytes);
+ fn file_count(mut self, n: DbInt) -> Self {
+ self.file_count = n;
+ self
+ }
- // Delete the temporary file.
- std::fs::remove_file(&dbname)?;
+ fn file_bytes(mut self, n: u64) -> Self {
+ self.file_bytes_raw = n;
+ self.file_bytes = HumanBytes(n).to_string();
+ self
+ }
- Ok(())
+ fn db_bytes(mut self, n: u64) -> Self {
+ self.db_bytes_raw = n;
+ self.db_bytes = HumanBytes(n).to_string();
+ self
+ }
}