From 6cdc18742ed841435b2b24a1b861e81bf8b967f9 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 8 Jul 2023 14:50:18 +0200 Subject: [PATCH] feat: don't read non-contributing archives for export --- CHANGELOG.md | 5 +++++ src/backup/delta.rs | 11 +++++++++-- src/backup/manager/mod.rs | 11 +++++++++-- src/backup/state.rs | 8 ++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 918b0ea..62b6692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://git.rustybever.be/Chewing_Bever/alex/src/branch/dev) +### Changed + +* Export command no longer reads backups that do not contribute to the final + state + ## [0.3.1](https://git.rustybever.be/Chewing_Bever/alex/src/tag/0.3.1) ### Added diff --git a/src/backup/delta.rs b/src/backup/delta.rs index 1bc5477..21f626c 100644 --- a/src/backup/delta.rs +++ b/src/backup/delta.rs @@ -18,11 +18,18 @@ pub struct Delta { impl Delta { pub fn new() -> Self { Self { - added: Default::default(), - removed: Default::default(), + added: State::new(), + removed: State::new(), } } + /// Returns whether the delta is empty by checking whether both its added and removed state + /// return true for their `is_empty`. + #[allow(dead_code)] + pub fn is_empty(&self) -> bool { + self.added.is_empty() && self.removed.is_empty() + } + /// Calculate the union of this delta with another delta. /// /// The union of two deltas is a delta that produces the same state as if you were to apply diff --git a/src/backup/manager/mod.rs b/src/backup/manager/mod.rs index 6a43f9f..7cbd43c 100644 --- a/src/backup/manager/mod.rs +++ b/src/backup/manager/mod.rs @@ -226,9 +226,16 @@ where let enc = GzEncoder::new(tar_gz, Compression::default()); let mut ar = tar::Builder::new(enc); - for (contribution, backup) in - contributions.iter().rev().zip(chain.iter().take(index + 1)) + // We only need to consider backups that have a non-empty contribution. + // This allows us to skip reading backups that have been completely + // overwritten by their successors anyways. + for (contribution, backup) in contributions + .iter() + .rev() + .zip(chain.iter().take(index + 1)) + .filter(|(contribution, _)| !contribution.is_empty()) { + println!("{}", &backup); backup.append(&self.backup_dir, contribution, &mut ar)?; } diff --git a/src/backup/state.rs b/src/backup/state.rs index 4b09acf..de4b2c0 100644 --- a/src/backup/state.rs +++ b/src/backup/state.rs @@ -41,6 +41,14 @@ impl State { path.starts_with(dir) && files.contains(path.strip_prefix(dir).unwrap()) }) } + + /// Returns whether the state is empty. + /// + /// Note that this does not necessarily mean that the state does not contain any sets, but + /// rather that any sets that it does contain are also empty. + pub fn is_empty(&self) -> bool { + self.0.values().all(|s| s.is_empty()) + } } impl From for State