Compare commits

...

2 Commits

Author SHA1 Message Date
Jef Roosens a4a03ca4c5
feat: improve list view
ci/woodpecker/push/lint Pipeline was successful Details
ci/woodpecker/push/clippy Pipeline was successful Details
ci/woodpecker/push/build Pipeline was successful Details
2023-06-24 13:51:37 +02:00
Jef Roosens 5159bfdddd
feat: basic list command 2023-06-24 13:35:59 +02:00
6 changed files with 67 additions and 3 deletions

View File

@ -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

View File

@ -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)
}
}

View File

@ -127,4 +127,8 @@ where
.get(layer)
.map(|manager| manager.restore_backup(start_time))
}
pub fn managers(&self) -> &HashMap<String, Manager<T>> {
&self.managers
}
}

View File

@ -181,4 +181,9 @@ where
Err(other("Unknown backup."))
}
/// Get a reference to the underlying chains
pub fn chains(&self) -> &Vec<Vec<Backup<T>>> {
&self.chains
}
}

View File

@ -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<T: Clone> Backup<T> {
Ok(())
}
}
impl<T: Clone> fmt::Display for Backup<T> {
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
)
}
}

View File

@ -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<String>,
}
#[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,24 @@ 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();
println!(" {}", iter.next().unwrap());
for backup in iter {
println!(" {}", backup);
}
}
}
Ok(())
}
}