use filetime::{set_file_mtime, FileTime};
use itertools::Itertools;
use conserve::monitor::test::TestMonitor;
use conserve::test_fixtures::{ScratchArchive, TreeFixture};
use conserve::*;
fn create_tree() -> (ScratchArchive, TreeFixture) {
let a = ScratchArchive::new();
let tf = TreeFixture::new();
tf.create_file_with_contents("thing", b"contents of thing");
let stats = backup(&a, tf.path(), &BackupOptions::default(), TestMonitor::arc()).unwrap();
assert_eq!(stats.new_files, 1);
(a, tf)
}
#[test]
fn diff_unchanged() {
let (a, tf) = create_tree();
let st = a.open_stored_tree(BandSelectionPolicy::Latest).unwrap();
let options = DiffOptions {
include_unchanged: true,
..DiffOptions::default()
};
let monitor = TestMonitor::arc();
let changes: Vec<EntryChange> = diff(&st, &tf.live_tree(), &options, monitor.clone())
.unwrap()
.collect();
dbg!(&changes);
assert_eq!(changes.len(), 2); assert_eq!(changes[0].apath, "/");
assert!(changes[0].change.is_unchanged());
assert!(!changes[0].change.is_changed());
assert_eq!(changes[1].apath, "/thing");
assert!(changes[1].change.is_unchanged());
assert!(!changes[1].change.is_changed());
let options = DiffOptions {
include_unchanged: false,
..DiffOptions::default()
};
let changes = diff(&st, &tf.live_tree(), &options, TestMonitor::arc())
.unwrap()
.collect_vec();
println!("changes with include_unchanged=false:\n{changes:#?}");
assert_eq!(changes.len(), 0);
}
#[test]
fn mtime_only_change_reported_as_changed() {
let (a, tf) = create_tree();
let st = a.open_stored_tree(BandSelectionPolicy::Latest).unwrap();
set_file_mtime(
tf.path().join("thing"),
FileTime::from_unix_time(1704135090, 0),
)
.unwrap();
let options = DiffOptions {
include_unchanged: false,
..DiffOptions::default()
};
let changes: Vec<EntryChange> = diff(&st, &tf.live_tree(), &options, TestMonitor::arc())
.unwrap()
.collect();
dbg!(&changes);
assert_eq!(changes.len(), 1);
assert_eq!(changes[0].apath, "/thing");
assert!(changes[0].change.is_changed());
assert!(!changes[0].change.is_unchanged());
}
#[cfg(target_os = "linux")]
#[test]
fn chgrp_reported_as_changed() {
use std::os::unix::fs::chown;
use conserve::test_fixtures::arbitrary_secondary_group;
let (a, tf) = create_tree();
chown(
tf.path().join("thing"),
None,
Some(arbitrary_secondary_group()),
)
.unwrap();
let st = a.open_stored_tree(BandSelectionPolicy::Latest).unwrap();
let options = DiffOptions {
include_unchanged: false,
..DiffOptions::default()
};
let changes: Vec<EntryChange> = diff(&st, &tf.live_tree(), &options, TestMonitor::arc())
.unwrap()
.collect();
dbg!(&changes);
assert_eq!(changes.len(), 1);
assert_eq!(changes[0].apath, "/thing");
assert!(changes[0].change.is_changed());
assert!(!changes[0].change.is_unchanged());
}
#[cfg(unix)]
#[test]
fn symlink_target_change_reported_as_changed() {
use std::fs::remove_file;
use std::path::Path;
let a = ScratchArchive::new();
let tf = TreeFixture::new();
tf.create_symlink("link", "target");
backup(&a, tf.path(), &BackupOptions::default(), TestMonitor::arc()).unwrap();
let link_path = tf.path().join("link");
remove_file(&link_path).unwrap();
std::os::unix::fs::symlink("new-target", &link_path).unwrap();
let st = a.open_stored_tree(BandSelectionPolicy::Latest).unwrap();
assert_eq!(
std::fs::read_link(&link_path).unwrap(),
Path::new("new-target")
);
let options = DiffOptions {
include_unchanged: false,
..DiffOptions::default()
};
let changes: Vec<EntryChange> = diff(&st, &tf.live_tree(), &options, TestMonitor::arc())
.unwrap()
.collect();
dbg!(&changes);
assert_eq!(changes.len(), 1);
assert_eq!(changes[0].apath, "/link");
assert!(changes[0].change.is_changed());
assert!(!changes[0].change.is_unchanged());
}