Handle remote-deleted + local-unchanged as local delete

Fix compute_sync_actions to properly treat the case where a file has
been deleted on the remote but remains unchanged locally: previously the
code always emitted an Upload (re-uploading the local copy). Now it
checks the base checksum and emits DeleteLocal when the local copy
matches the base (unchanged), and emits Upload only when the local copy
differs (modified).

Updated tests: adjusted test_remote_deleted_local_unchanged to assert
DeleteLocal, and added test_remote_deleted_local_modified to verify the
upload behavior when the local file is modified while remote was
deleted.
This commit is contained in:
Tristan Michael 2026-04-05 15:26:55 -07:00
parent 4c57851e15
commit 25358a9eec

View file

@ -167,9 +167,15 @@ pub fn compute_sync_actions(
}
// Local present, remote gone, base known: remote was deleted
(Some(_), None, Some(_)) => {
// modified locally + deleted remote -> upload (local wins)
(Some(l), None, Some(b)) => {
let local_changed = l.checksum != b.checksum;
if local_changed {
// modified locally + deleted remotely -> upload (local wins)
actions.push(SyncAction::Upload { path: path.to_string() });
} else {
// unchanged locally + deleted remotely -> delete local
actions.push(SyncAction::DeleteLocal { path: path.to_string() });
}
}
// Remote present, local gone, base known: local was deleted
@ -872,7 +878,20 @@ mod tests {
let actions = compute_sync_actions(&local, &remote, &state);
assert_eq!(actions.len(), 1);
// Local present, remote gone, base known -> upload (local wins)
// Local unchanged, remote deleted -> delete local
assert_eq!(actions[0], SyncAction::DeleteLocal { path: "file.md".to_string() });
}
#[test]
fn test_remote_deleted_local_modified() {
let local = vec![make_local("file.md", "new_checksum")];
let remote = vec![];
let mut state = SyncState::default();
state.files.insert("file.md".to_string(), make_base("abc123"));
let actions = compute_sync_actions(&local, &remote, &state);
assert_eq!(actions.len(), 1);
// Local modified, remote deleted -> upload (local wins)
assert_eq!(actions[0], SyncAction::Upload { path: "file.md".to_string() });
}