Add safe file-root apply

This commit is contained in:
Eric Wendland 2026-05-20 13:30:57 +02:00
commit 5c91635ea2
8 changed files with 394 additions and 14 deletions

View file

@ -394,6 +394,91 @@ fn cas_file_root_add_list_scan_detects_changes() {
}
}
#[test]
fn cas_file_root_apply_writes_missing_files_and_records_conflicts() {
let home = tempfile::tempdir().expect("tempdir");
let paths = geth_config::GethPaths::from_home(home.path());
let node = geth_node::init_node(&paths).expect("init node");
let source_path = home.path().join("source-root");
std::fs::create_dir_all(source_path.join("dir")).expect("create source root");
std::fs::write(source_path.join("a.txt"), b"remote").expect("write remote a");
std::fs::write(source_path.join("dir").join("b.txt"), b"remote b").expect("write remote b");
geth_node::handle_request(
&node,
geth_control::ControlRequest::CasRootAdd {
name: "remote-node-peer-shared".to_owned(),
path: source_path,
},
)
.expect("add source root");
let tree = match geth_node::handle_request(
&node,
geth_control::ControlRequest::CasRootScan {
name: "remote-node-peer-shared".to_owned(),
},
)
.expect("scan source root")
{
geth_control::ControlResponse::CasRootScanned { scan } => scan.tree.hash,
other => panic!("unexpected response: {other:?}"),
};
let target_path = home.path().join("target-root");
std::fs::create_dir_all(&target_path).expect("create target root");
std::fs::write(target_path.join("a.txt"), b"local edit").expect("write local a");
let response = geth_node::handle_request(
&node,
geth_control::ControlRequest::CasRootApply {
source: "remote-node-peer-shared".to_owned(),
target: target_path.clone(),
dry_run: false,
},
)
.expect("apply source root");
match response {
geth_control::ControlResponse::CasRootApplied {
files_written,
dirs_created,
conflicts,
note,
..
} => {
assert_eq!(files_written, 1);
assert_eq!(dirs_created, 1);
assert_eq!(conflicts.len(), 1);
assert_eq!(conflicts[0].path, "a.txt");
assert_eq!(conflicts[0].remote_tree, Some(tree));
assert!(note.contains("never deletes"));
}
other => panic!("unexpected response: {other:?}"),
}
assert_eq!(
std::fs::read(target_path.join("dir").join("b.txt")).expect("read applied b"),
b"remote b"
);
assert_eq!(
std::fs::read(target_path.join("a.txt")).expect("read local a"),
b"local edit"
);
let response = geth_node::handle_request(
&node,
geth_control::ControlRequest::CasConflictList {
root: Some("remote-node-peer-shared".to_owned()),
},
)
.expect("list apply conflicts");
match response {
geth_control::ControlResponse::CasConflictList { conflicts } => {
assert_eq!(conflicts.len(), 1);
assert_eq!(conflicts[0].path, "a.txt");
}
other => panic!("unexpected response: {other:?}"),
}
}
#[test]
fn cas_file_conflict_record_list_and_resolve() {
let home = tempfile::tempdir().expect("tempdir");