mirror of
https://github.com/rustic-rs/rustic.git
synced 2025-10-26 11:18:51 +00:00
Merge pull request #170 from rustic-rs/duplicate-snapshots
snapshots: summarize snapshots with identical trees
This commit is contained in:
commit
deb651e75b
@ -3,6 +3,7 @@ use std::time::Duration;
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use humantime::format_duration;
|
||||
use itertools::Itertools;
|
||||
use prettytable::{format, row, Table};
|
||||
|
||||
use super::bytes;
|
||||
@ -24,6 +25,10 @@ pub(super) struct Opts {
|
||||
#[clap(long)]
|
||||
long: bool,
|
||||
|
||||
/// Show all snapshots instead of summarizing identical follow-up snapshots
|
||||
#[clap(long)]
|
||||
all: bool,
|
||||
|
||||
/// Snapshots to show
|
||||
#[clap(value_name = "ID")]
|
||||
ids: Vec<String>,
|
||||
@ -63,24 +68,31 @@ pub(super) async fn execute(be: &impl DecryptReadBackend, opts: Opts) -> Result<
|
||||
display_snap(snap);
|
||||
}
|
||||
} else {
|
||||
let snap_to_table = |(sn, count): (SnapshotFile, usize)| {
|
||||
let tags = sn.tags.formatln();
|
||||
let paths = sn.paths.formatln();
|
||||
let time = sn.time.format("%Y-%m-%d %H:%M:%S");
|
||||
let (files, dirs, size) = match &sn.summary {
|
||||
Some(s) => (
|
||||
s.total_files_processed.to_string(),
|
||||
s.total_dirs_processed.to_string(),
|
||||
bytes(s.total_bytes_processed),
|
||||
),
|
||||
None => ("?".to_string(), "?".to_string(), "?".to_string()),
|
||||
};
|
||||
let id = match count {
|
||||
0 => format!("{}", sn.id),
|
||||
count => format!("{} (+{})", sn.id, count),
|
||||
};
|
||||
row![id, time, sn.hostname, tags, paths, r->files, r->dirs, r->size]
|
||||
};
|
||||
|
||||
let mut table: Table = snapshots
|
||||
.into_iter()
|
||||
.map(|sn| {
|
||||
let tags = sn.tags.formatln();
|
||||
let paths = sn.paths.formatln();
|
||||
let time = sn.time.format("%Y-%m-%d %H:%M:%S");
|
||||
let (files, dirs, size) = sn
|
||||
.summary
|
||||
.map(|s| {
|
||||
(
|
||||
s.total_files_processed.to_string(),
|
||||
s.total_dirs_processed.to_string(),
|
||||
bytes(s.total_bytes_processed),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| ("?".to_string(), "?".to_string(), "?".to_string()));
|
||||
row![sn.id, time, sn.hostname, tags, paths, r->files, r->dirs, r->size]
|
||||
})
|
||||
.group_by(|sn| if opts.all { sn.id } else { sn.tree })
|
||||
.into_iter()
|
||||
.map(|(_, mut g)| (g.next().unwrap(), g.count()))
|
||||
.map(snap_to_table)
|
||||
.collect();
|
||||
table.set_titles(
|
||||
row![b->"ID", b->"Time", b->"Host", b->"Tags", b->"Paths", br->"Files",br->"Dirs", br->"Size"],
|
||||
|
||||
@ -15,7 +15,7 @@ use crate::backend::{DecryptReadBackend, FileType, RepoFile};
|
||||
|
||||
/// This is an extended version of the summaryOutput structure of restic in
|
||||
/// restic/internal/ui/backup$/json.go
|
||||
#[derive(Debug, Serialize, Deserialize, Derivative)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Derivative)]
|
||||
#[derivative(Default)]
|
||||
pub struct SnapshotSummary {
|
||||
pub files_new: u64,
|
||||
@ -61,7 +61,7 @@ impl DeleteOption {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Derivative)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Derivative)]
|
||||
#[derivative(Default)]
|
||||
pub struct SnapshotFile {
|
||||
#[derivative(Default(value = "Local::now()"))]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user