Some more fixes for reconcile with remote
This commit is contained in:
+86
-8
@@ -15,7 +15,7 @@ use tracing::info;
|
||||
|
||||
/// Server-side entry for one file. Built once on startup from a directory
|
||||
/// scan and refreshed by the watcher on inotify events.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct FileEntry {
|
||||
pub abs_path: PathBuf,
|
||||
pub rel_path: String,
|
||||
@@ -37,16 +37,17 @@ impl ServerState {
|
||||
|
||||
/// Replace the entire map with a fresh scan of `source`. Used on startup
|
||||
/// and on watcher-driven reconciliations.
|
||||
pub fn replace_all(&self, source: &Path) -> io::Result<()> {
|
||||
pub fn replace_all(&self, source: &Path) -> io::Result<bool> {
|
||||
let entries = scan_directory(source)?;
|
||||
let count = entries.len();
|
||||
let new_map: HashMap<u64, FileEntry> = entries.into_iter().collect();
|
||||
let mut map = self.inner.lock().unwrap();
|
||||
map.clear();
|
||||
for (id, entry) in entries {
|
||||
map.insert(id, entry);
|
||||
if *map == new_map {
|
||||
return Ok(false);
|
||||
}
|
||||
info!(count, "server state: scan complete");
|
||||
return Ok(());
|
||||
let count = new_map.len();
|
||||
*map = new_map;
|
||||
info!(count, "server state: scan complete (changed)");
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
/// Snapshot the current state into a manifest. Order is by inode ascending
|
||||
@@ -179,4 +180,81 @@ mod tests {
|
||||
state.replace_all(source).unwrap();
|
||||
assert_eq!(state.manifest().len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_all_returns_true_on_first_scan() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let source = tmp.path();
|
||||
fs::write(source.join("a.txt"), b"x").unwrap();
|
||||
|
||||
let state = ServerState::new();
|
||||
assert!(state.replace_all(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_all_returns_false_when_unchanged() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let source = tmp.path();
|
||||
fs::write(source.join("a.txt"), b"hello").unwrap();
|
||||
fs::write(source.join("b.txt"), b"world").unwrap();
|
||||
|
||||
let state = ServerState::new();
|
||||
state.replace_all(source).unwrap();
|
||||
assert!(!state.replace_all(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_all_returns_true_after_file_added() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let source = tmp.path();
|
||||
fs::write(source.join("a.txt"), b"x").unwrap();
|
||||
|
||||
let state = ServerState::new();
|
||||
state.replace_all(source).unwrap();
|
||||
|
||||
fs::write(source.join("b.txt"), b"y").unwrap();
|
||||
assert!(state.replace_all(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_all_returns_true_after_file_removed() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let source = tmp.path();
|
||||
fs::write(source.join("a.txt"), b"x").unwrap();
|
||||
fs::write(source.join("b.txt"), b"y").unwrap();
|
||||
|
||||
let state = ServerState::new();
|
||||
state.replace_all(source).unwrap();
|
||||
|
||||
fs::remove_file(source.join("a.txt")).unwrap();
|
||||
assert!(state.replace_all(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_all_returns_true_after_file_renamed() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let source = tmp.path();
|
||||
fs::write(source.join("old.txt"), b"x").unwrap();
|
||||
|
||||
let state = ServerState::new();
|
||||
state.replace_all(source).unwrap();
|
||||
assert!(!state.replace_all(source).unwrap());
|
||||
|
||||
fs::rename(source.join("old.txt"), source.join("new.txt")).unwrap();
|
||||
assert!(state.replace_all(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_all_returns_true_after_content_modified() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let source = tmp.path();
|
||||
fs::write(source.join("a.txt"), b"original").unwrap();
|
||||
|
||||
let state = ServerState::new();
|
||||
state.replace_all(source).unwrap();
|
||||
assert!(!state.replace_all(source).unwrap());
|
||||
|
||||
fs::write(source.join("a.txt"), b"modified content").unwrap();
|
||||
assert!(state.replace_all(source).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user