From 5159bfdddd5fda8e8416972a12d7c9a7f1776c7d Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 24 Jun 2023 13:35:59 +0200 Subject: [PATCH 1/2] feat: basic list command --- src/backup/manager/meta.rs | 4 ++++ src/backup/manager/mod.rs | 5 +++++ src/cli/backup.rs | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/backup/manager/meta.rs b/src/backup/manager/meta.rs index ff91310..de82576 100644 --- a/src/backup/manager/meta.rs +++ b/src/backup/manager/meta.rs @@ -127,4 +127,8 @@ where .get(layer) .map(|manager| manager.restore_backup(start_time)) } + + pub fn managers(&self) -> &HashMap> { + &self.managers + } } diff --git a/src/backup/manager/mod.rs b/src/backup/manager/mod.rs index 2b742f7..47488d9 100644 --- a/src/backup/manager/mod.rs +++ b/src/backup/manager/mod.rs @@ -181,4 +181,9 @@ where Err(other("Unknown backup.")) } + + /// Get a reference to the underlying chains + pub fn chains(&self) -> &Vec>> { + &self.chains + } } diff --git a/src/cli/backup.rs b/src/cli/backup.rs index 32d45c4..44c7bca 100644 --- a/src/cli/backup.rs +++ b/src/cli/backup.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; #[derive(Subcommand)] pub enum BackupCommands { /// List all tracked backups - List, + List(BackupListArgs), /// Manually create a new backup Create(BackupCreateArgs), /// Restore a backup @@ -28,6 +28,12 @@ pub struct BackupCreateArgs { layer: String, } +#[derive(Args)] +pub struct BackupListArgs { + /// What layer to list + layer: Option, +} + #[derive(Args)] pub struct BackupRestoreArgs { /// Path to the backup inside the backup directory @@ -41,7 +47,7 @@ impl BackupArgs { pub fn run(&self, cli: &Cli) -> io::Result<()> { match &self.command { BackupCommands::Create(args) => args.run(cli), - BackupCommands::List => Ok(()), + BackupCommands::List(args) => args.run(cli), BackupCommands::Restore(args) => args.run(cli), } } @@ -120,3 +126,25 @@ impl BackupRestoreArgs { } } } + +impl BackupListArgs { + pub fn run(&self, cli: &Cli) -> io::Result<()> { + let meta = cli.meta()?; + + for (name, manager) in meta.managers().iter() { + println!("{}", name); + + for chain in manager.chains().iter().filter(|c| !c.is_empty()) { + let mut iter = chain.iter(); + let first = iter.next().unwrap(); + println!(" {}", first.start_time.format(Backup::FILENAME_FORMAT)); + + for backup in iter { + println!(" {}", backup.start_time.format(Backup::FILENAME_FORMAT)); + } + } + } + + Ok(()) + } +} From a4a03ca4c502e5e3b763d69521ed7c2c498a0168 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 24 Jun 2023 13:47:55 +0200 Subject: [PATCH 2/2] feat: improve list view --- CHANGELOG.md | 2 +- src/backup/delta.rs | 10 ++++++++++ src/backup/mod.rs | 18 ++++++++++++++++++ src/cli/backup.rs | 5 ++--- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a3fc13..a973aea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -* `backup` CLI command * Incremental backups * Chain length describes how many incremental backups to create from the same full backup @@ -18,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Backup layers * Store multiple chains of backups in parallel, configuring each with different parameters (son-father-grandfather principle) +* CLI commands for creating, restoring & listing backups ### Changed diff --git a/src/backup/delta.rs b/src/backup/delta.rs index 34971f0..6e37e96 100644 --- a/src/backup/delta.rs +++ b/src/backup/delta.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; +use std::fmt; use std::path::PathBuf; /// Represents the changes relative to the previous backup @@ -74,3 +75,12 @@ impl Delta { } } } + +impl fmt::Display for Delta { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let added_count: usize = self.added.values().map(|s| s.len()).sum(); + let removed_count: usize = self.removed.values().map(|s| s.len()).sum(); + + write!(f, "+{}-{}", added_count, removed_count) + } +} diff --git a/src/backup/mod.rs b/src/backup/mod.rs index 3bc99df..602df19 100644 --- a/src/backup/mod.rs +++ b/src/backup/mod.rs @@ -14,6 +14,7 @@ use flate2::Compression; use path::PathExt; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; +use std::fmt; use std::fs::File; use std::io; use std::path::{Path, PathBuf}; @@ -205,3 +206,20 @@ impl Backup { Ok(()) } } + +impl fmt::Display for Backup { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let letter = match self.type_ { + BackupType::Full => 'F', + BackupType::Incremental => 'I', + }; + + write!( + f, + "{} ({}, {})", + self.start_time.format(Backup::FILENAME_FORMAT), + letter, + self.delta + ) + } +} diff --git a/src/cli/backup.rs b/src/cli/backup.rs index 44c7bca..4f64882 100644 --- a/src/cli/backup.rs +++ b/src/cli/backup.rs @@ -136,11 +136,10 @@ impl BackupListArgs { for chain in manager.chains().iter().filter(|c| !c.is_empty()) { let mut iter = chain.iter(); - let first = iter.next().unwrap(); - println!(" {}", first.start_time.format(Backup::FILENAME_FORMAT)); + println!(" {}", iter.next().unwrap()); for backup in iter { - println!(" {}", backup.start_time.format(Backup::FILENAME_FORMAT)); + println!(" {}", backup); } } }