Skip to content

Commit 79b441e

Browse files
committed
feat(interactive): show total diff when computing summary
1 parent 189b17c commit 79b441e

File tree

2 files changed

+117
-36
lines changed

2 files changed

+117
-36
lines changed

src/commands/tui/diff.rs

Lines changed: 95 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Diff Commands:
5151
5252
m : toggle ignoring metadata
5353
d : toggle show only different entries
54-
s : compute information for (sub-)dirs
54+
s : compute information for (sub-)dirs and show totals
5555
I : show information about snapshots
5656
5757
General Commands:
@@ -233,48 +233,61 @@ impl<'a, P: ProgressBars, S: IndexedFull> Diff<'a, P, S> {
233233
!self.ignore_identical || !self.node_changed(node).is_identical()
234234
}
235235

236-
fn ls_row(&self, node: &DiffNode, stat: &mut DiffStatistics) -> Vec<Text<'static>> {
236+
#[allow(clippy::type_complexity)]
237+
fn sizes(
238+
&self,
239+
node: &DiffNode,
240+
) -> (
241+
Option<u64>,
242+
Option<u64>,
243+
Option<u64>,
244+
Option<u64>,
245+
Option<u64>,
246+
) {
237247
let node_info = |node: &Node| {
238-
let size = node.subtree.map_or(node.meta.size, |id| {
248+
node.subtree.map_or(node.meta.size, |id| {
239249
self.summary_map
240250
.get(&id)
241251
.map_or(node.meta.size, |summary| summary.summary.size)
242-
});
243-
(
244-
bytes_size_to_string(size),
245-
node.meta.mtime.map_or_else(
246-
|| "?".to_string(),
247-
|t| format!("{}", t.format("%Y-%m-%d %H:%M:%S")),
248-
),
249-
)
252+
})
250253
};
251254

252255
let (left, right) = node.0.as_ref().left_and_right();
253256
let left_blobs = left.map(|node| BlobInfoRef::from_node_or_map(node, &self.summary_map));
254257
let right_blobs = right.map(|node| BlobInfoRef::from_node_or_map(node, &self.summary_map));
255-
let left_only = BlobInfoRef::text_diff(&left_blobs, &right_blobs, self.repo);
256-
let right_only = BlobInfoRef::text_diff(&right_blobs, &left_blobs, self.repo);
258+
let (left_only, right_only, both) =
259+
BlobInfoRef::size_diff(&left_blobs, &right_blobs, self.repo).unwrap_or_default();
257260

261+
let left_size = left.map(node_info);
262+
let right_size = right.map(node_info);
263+
264+
(left_size, left_only, right_size, right_only, both)
265+
}
266+
267+
fn ls_row(&self, node: &DiffNode, stat: &mut DiffStatistics) -> Vec<Text<'static>> {
268+
let node_mtime = |node: &Node| {
269+
node.meta.mtime.map_or_else(
270+
|| "?".to_string(),
271+
|t| format!("{}", t.format("%Y-%m-%d %H:%M:%S")),
272+
)
273+
};
274+
275+
let (left_size, left_only, right_size, right_only, _) = self.sizes(node);
258276
let changed = self.node_changed(node);
259277
stat.apply(changed);
260278
let name = node.name();
261279
let name = format!("{changed} {}", name.to_string_lossy());
262-
let (left_size, left_mtime) = match &node.0 {
263-
EitherOrBoth::Left(node) | EitherOrBoth::Both(node, _) => node_info(node),
264-
_ => (String::new(), String::new()),
265-
};
266-
let (right_size, right_mtime) = match &node.0 {
267-
EitherOrBoth::Right(node) | EitherOrBoth::Both(_, node) => node_info(node),
268-
_ => (String::new(), String::new()),
269-
};
280+
let (left, right) = node.0.as_ref().left_and_right();
281+
let left_mtime = left.map_or_else(String::new, node_mtime);
282+
let right_mtime = right.map_or_else(String::new, node_mtime);
270283
[
271284
name,
272285
left_mtime,
273-
left_size,
274-
left_only,
286+
left_size.map_or_else(String::new, bytes_size_to_string),
287+
left_only.map_or_else(String::new, bytes_size_to_string),
275288
right_mtime,
276-
right_size,
277-
right_only,
289+
right_size.map_or_else(String::new, bytes_size_to_string),
290+
right_only.map_or_else(String::new, bytes_size_to_string),
278291
]
279292
.into_iter()
280293
.map(Text::from)
@@ -381,7 +394,7 @@ impl<'a, P: ProgressBars, S: IndexedFull> Diff<'a, P, S> {
381394
Ok(())
382395
}
383396

384-
pub fn compute_summary(&mut self) -> Result<()> {
397+
pub fn compute_summary(&mut self) -> Result<PopUpTable> {
385398
let pb = self.repo.progress_bars();
386399
let p = pb.progress_counter("computing (sub)-dir information");
387400

@@ -399,7 +412,58 @@ impl<'a, P: ProgressBars, S: IndexedFull> Diff<'a, P, S> {
399412

400413
p.finish();
401414
self.update_table();
402-
Ok(())
415+
416+
// Compute total sizes diff
417+
let (left_size, left_only, right_size, right_only, both) = self.sizes(&self.node);
418+
let left_repo_size = if let (Some(only), Some(both)) = (left_only, both) {
419+
Some(only + both)
420+
} else {
421+
None
422+
};
423+
let right_repo_size = if let (Some(only), Some(both)) = (right_only, both) {
424+
Some(only + both)
425+
} else {
426+
None
427+
};
428+
let mut rows = Vec::new();
429+
let title_left = if self.node.0.has_left() {
430+
format!("{}:{}", self.snapshot_left.id, self.path_left.display())
431+
} else {
432+
format!("({})", self.snapshot_left.id)
433+
};
434+
let title_right = if self.node.0.has_right() {
435+
format!("{}:{}", self.snapshot_right.id, self.path_right.display())
436+
} else {
437+
format!("({})", self.snapshot_right.id)
438+
};
439+
rows.push(vec![
440+
Text::from(""),
441+
Text::from(title_right),
442+
Text::from(title_left),
443+
]);
444+
rows.push(vec![
445+
Text::from("total Size"),
446+
Text::from(left_size.map_or_else(String::new, bytes_size_to_string)),
447+
Text::from(right_size.map_or_else(String::new, bytes_size_to_string)),
448+
]);
449+
rows.push(vec![
450+
Text::from("total RepoSize"),
451+
Text::from(left_repo_size.map_or_else(String::new, bytes_size_to_string)),
452+
Text::from(right_repo_size.map_or_else(String::new, bytes_size_to_string)),
453+
]);
454+
rows.push(vec![
455+
Text::from("exclusive RepoSize"),
456+
Text::from(left_only.map_or_else(String::new, bytes_size_to_string)),
457+
Text::from(right_only.map_or_else(String::new, bytes_size_to_string)),
458+
]);
459+
let both = both.map_or_else(String::new, bytes_size_to_string);
460+
rows.push(vec![
461+
Text::from("shared RepoSize"),
462+
Text::from(both.clone()),
463+
Text::from(both),
464+
]);
465+
466+
Ok(popup_table("diff total", rows))
403467
}
404468

405469
pub fn snapshot_details(&self) -> PopUpTable {
@@ -448,7 +512,10 @@ impl<'a, P: ProgressBars, S: IndexedFull> ProcessEvent for Diff<'a, P, S> {
448512
}
449513
Char('m') => self.toggle_ignore_metadata(),
450514
Char('d') => self.toggle_ignore_identical()?,
451-
Char('s') => self.compute_summary()?,
515+
Char('s') => {
516+
self.current_screen =
517+
CurrentScreen::SnapshotDetails(self.compute_summary()?);
518+
}
452519
Char('I') => {
453520
self.current_screen =
454521
CurrentScreen::SnapshotDetails(self.snapshot_details());

src/commands/tui/summary.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustic_core::{
66
repofile::{Metadata, Node, Tree},
77
};
88

9-
use crate::{commands::ls::Summary, helpers::bytes_size_to_string};
9+
use crate::commands::ls::Summary;
1010

1111
#[derive(Default)]
1212
pub struct SummaryMap(BTreeMap<TreeId, TreeSummary>);
@@ -121,23 +121,37 @@ impl<'a> BlobInfoRef<'a> {
121121
Self(node.content.iter().flatten().collect())
122122
}
123123

124-
pub fn text_diff<P, S: IndexedFull>(
124+
pub fn size_diff<P, S: IndexedFull>(
125125
blobs1: &Option<Self>,
126126
blobs2: &Option<Self>,
127127
repo: &'a Repository<P, S>,
128-
) -> String {
128+
) -> Result<(Option<u64>, Option<u64>, Option<u64>)> {
129129
if let (Some(blobs1), Some(blobs2)) = (blobs1, blobs2) {
130-
blobs1
130+
let left_only = blobs1
131131
.0
132132
.difference(&blobs2.0)
133133
.map(|id| repo.get_index_entry(*id))
134134
.try_fold(0u64, |sum, b| -> Result<_> {
135135
Ok(sum + u64::from(b?.length))
136-
})
137-
.ok()
138-
.map_or_else(|| "?".to_string(), bytes_size_to_string)
136+
})?;
137+
138+
let right_only = blobs2
139+
.0
140+
.difference(&blobs1.0)
141+
.map(|id| repo.get_index_entry(*id))
142+
.try_fold(0u64, |sum, b| -> Result<_> {
143+
Ok(sum + u64::from(b?.length))
144+
})?;
145+
let both = blobs2
146+
.0
147+
.intersection(&blobs1.0)
148+
.map(|id| repo.get_index_entry(*id))
149+
.try_fold(0u64, |sum, b| -> Result<_> {
150+
Ok(sum + u64::from(b?.length))
151+
})?;
152+
Ok((Some(left_only), Some(right_only), Some(both)))
139153
} else {
140-
String::new()
154+
Ok(Default::default())
141155
}
142156
}
143157
}

0 commit comments

Comments
 (0)