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 super::State;
 | 
			
		||||
 | 
			
		||||
/// 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 {
 | 
			
		||||
    /// What files were added/modified in each part of the tarball.
 | 
			
		||||
    pub added: State,
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +23,6 @@ pub struct Delta {
 | 
			
		|||
impl Delta {
 | 
			
		||||
    /// 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()
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +146,58 @@ impl Delta {
 | 
			
		|||
 | 
			
		||||
        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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -153,3 +208,44 @@ impl fmt::Display for Delta {
 | 
			
		|||
        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