feat(backup): add delta mutation methods; start union tests
parent
638e228ba4
commit
7e045760b3
|
@ -1,11 +1,15 @@
|
||||||
use std::{borrow::Borrow, fmt};
|
use std::{
|
||||||
|
borrow::Borrow,
|
||||||
|
fmt,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::State;
|
use super::State;
|
||||||
|
|
||||||
/// Represents the changes relative to the previous backup
|
/// Represents the changes relative to the previous backup
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
|
||||||
pub struct Delta {
|
pub struct Delta {
|
||||||
/// What files were added/modified in each part of the tarball.
|
/// What files were added/modified in each part of the tarball.
|
||||||
pub added: State,
|
pub added: State,
|
||||||
|
@ -19,7 +23,6 @@ pub struct Delta {
|
||||||
impl Delta {
|
impl Delta {
|
||||||
/// Returns whether the delta is empty by checking whether both its added and removed state
|
/// Returns whether the delta is empty by checking whether both its added and removed state
|
||||||
/// return true for their `is_empty`.
|
/// return true for their `is_empty`.
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.added.is_empty() && self.removed.is_empty()
|
self.added.is_empty() && self.removed.is_empty()
|
||||||
}
|
}
|
||||||
|
@ -143,6 +146,58 @@ impl Delta {
|
||||||
|
|
||||||
contributions
|
contributions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Append the given files to the directory's list of added files
|
||||||
|
pub fn append_added<I>(&mut self, dir: impl Into<PathBuf>, files: I)
|
||||||
|
where
|
||||||
|
I: IntoIterator,
|
||||||
|
I::Item: Into<PathBuf>,
|
||||||
|
{
|
||||||
|
let dir: PathBuf = dir.into();
|
||||||
|
let files = files.into_iter().map(Into::into);
|
||||||
|
|
||||||
|
if let Some(dir_files) = self.added.get_mut(&dir) {
|
||||||
|
dir_files.extend(files);
|
||||||
|
} else {
|
||||||
|
self.added.insert(dir, files.collect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around the `append_added` method for a builder-style construction of delta's
|
||||||
|
pub fn with_added<I>(mut self, dir: impl Into<PathBuf>, files: I) -> Self
|
||||||
|
where
|
||||||
|
I: IntoIterator,
|
||||||
|
I::Item: Into<PathBuf>,
|
||||||
|
{
|
||||||
|
self.append_added(dir, files);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Append the given files to the directory's list of removed files
|
||||||
|
pub fn append_removed<I>(&mut self, dir: impl Into<PathBuf>, files: I)
|
||||||
|
where
|
||||||
|
I: IntoIterator,
|
||||||
|
I::Item: Into<PathBuf>,
|
||||||
|
{
|
||||||
|
let dir: PathBuf = dir.into();
|
||||||
|
let files = files.into_iter().map(Into::into);
|
||||||
|
|
||||||
|
if let Some(dir_files) = self.removed.get_mut(&dir) {
|
||||||
|
dir_files.extend(files);
|
||||||
|
} else {
|
||||||
|
self.removed.insert(dir, files.collect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around the `append_removed` method for a builder-style construction of delta's
|
||||||
|
pub fn with_removed<I>(mut self, dir: impl Into<PathBuf>, files: I) -> Self
|
||||||
|
where
|
||||||
|
I: IntoIterator,
|
||||||
|
I::Item: Into<PathBuf>,
|
||||||
|
{
|
||||||
|
self.append_removed(dir, files);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Delta {
|
impl fmt::Display for Delta {
|
||||||
|
@ -153,3 +208,44 @@ impl fmt::Display for Delta {
|
||||||
write!(f, "+{}-{}", added_count, removed_count)
|
write!(f, "+{}-{}", added_count, removed_count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_union_disjunct_dirs() {
|
||||||
|
let a = Delta::default()
|
||||||
|
.with_added("dir_added_1", ["file1", "file2"])
|
||||||
|
.with_removed("dir_removed_1", ["file1", "file2"]);
|
||||||
|
let b = Delta::default()
|
||||||
|
.with_added("dir_added_3", ["file1", "file2"])
|
||||||
|
.with_removed("dir_removed_3", ["file1", "file2"]);
|
||||||
|
|
||||||
|
let expected = Delta::default()
|
||||||
|
.with_added("dir_added_1", ["file1", "file2"])
|
||||||
|
.with_added("dir_added_3", ["file1", "file2"])
|
||||||
|
.with_removed("dir_removed_1", ["file1", "file2"])
|
||||||
|
.with_removed("dir_removed_3", ["file1", "file2"]);
|
||||||
|
|
||||||
|
assert_eq!(expected, a.union(&b));
|
||||||
|
assert_eq!(expected, b.union(&a));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_union_disjunct_files() {
|
||||||
|
let a = Delta::default()
|
||||||
|
.with_added("dir_added_1", ["file1", "file2"])
|
||||||
|
.with_removed("dir_removed_1", ["file1", "file2"]);
|
||||||
|
let b = Delta::default()
|
||||||
|
.with_added("dir_added_1", ["file3", "file4"])
|
||||||
|
.with_removed("dir_removed_1", ["file3", "file4"]);
|
||||||
|
|
||||||
|
let expected = Delta::default()
|
||||||
|
.with_added("dir_added_1", ["file1", "file2", "file3", "file4"])
|
||||||
|
.with_removed("dir_removed_1", ["file1", "file2", "file3", "file4"]);
|
||||||
|
|
||||||
|
assert_eq!(expected, a.union(&b));
|
||||||
|
assert_eq!(expected, b.union(&a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue