context: copy symlinks as symlinks and improve error messages

This commit is contained in:
2026-07-17 10:12:46 +02:00
parent 2b27b7b06e
commit c4b59a4376
11 changed files with 382 additions and 54 deletions
+33
View File
@@ -147,4 +147,37 @@ mod tests {
"subcontent"
);
}
/// Copying a tree containing a dangling symlink must reproduce the link
/// itself rather than failing to follow it (which previously surfaced as
/// a bare "No such file or directory (os error 2)").
#[test]
fn test_context_copy_preserves_dangling_symlink() {
use std::os::unix::fs::symlink;
let temp_dir = tempfile::tempdir().unwrap();
let ctx = Context::new(ContextConfig::Local);
let src_dir = temp_dir.path().join("src");
std::fs::create_dir_all(&src_dir).unwrap();
// A regular file alongside the symlink, to ensure normal copies still work.
std::fs::write(src_dir.join("real.txt"), "data").unwrap();
// A dangling symlink pointing to a non-existent target.
symlink("/nonexistent/target", src_dir.join("dangling")).unwrap();
let dest_dir = temp_dir.path().join("dest");
ctx.copy_path(&src_dir, &dest_dir).unwrap();
// The regular file was copied.
assert_eq!(
ctx.read_file(&dest_dir.join("real.txt")).unwrap(),
"data"
);
// The symlink was reproduced as a symlink (not followed).
let meta = std::fs::symlink_metadata(dest_dir.join("dangling")).unwrap();
assert!(meta.file_type().is_symlink());
assert_eq!(
std::fs::read_link(dest_dir.join("dangling")).unwrap(),
std::path::Path::new("/nonexistent/target")
);
}
}