1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

cp: fix symlink-overwrite error-priority (#6586)

This commit is contained in:
Luv-Ray 2024-10-16 14:55:43 +08:00 committed by GitHub
parent d1becbca22
commit 85b0ef132b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 1 deletions

View file

@ -1271,7 +1271,12 @@ pub fn copy(sources: &[PathBuf], target: &Path, options: &Options) -> CopyResult
let dest = construct_dest_path(source, target, target_type, options) let dest = construct_dest_path(source, target, target_type, options)
.unwrap_or_else(|_| target.to_path_buf()); .unwrap_or_else(|_| target.to_path_buf());
if fs::metadata(&dest).is_ok() && !fs::symlink_metadata(&dest)?.file_type().is_symlink() if fs::metadata(&dest).is_ok()
&& !fs::symlink_metadata(&dest)?.file_type().is_symlink()
// if both `source` and `dest` are symlinks, it should be considered as an overwrite.
|| fs::metadata(source).is_ok()
&& fs::symlink_metadata(source)?.file_type().is_symlink()
|| matches!(options.copy_mode, CopyMode::SymLink)
{ {
// There is already a file and it isn't a symlink (managed in a different place) // There is already a file and it isn't a symlink (managed in a different place)
if copied_destinations.contains(&dest) if copied_destinations.contains(&dest)

View file

@ -5776,6 +5776,59 @@ fn test_cp_parents_absolute_path() {
at.file_exists(res); at.file_exists(res);
} }
#[test]
fn test_copy_symlink_overwrite() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("a");
at.mkdir("b");
at.mkdir("c");
at.write("t", "hello");
at.relative_symlink_file("../t", "a/1");
at.relative_symlink_file("../t", "b/1");
ucmd.arg("--no-dereference")
.arg("a/1")
.arg("b/1")
.arg("c")
.fails()
.stderr_only(if cfg!(not(target_os = "windows")) {
"cp: will not overwrite just-created 'c/1' with 'b/1'\n"
} else {
"cp: will not overwrite just-created 'c\\1' with 'b/1'\n"
});
}
#[test]
fn test_symlink_mode_overwrite() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("a");
at.mkdir("b");
at.write("a/t", "hello");
at.write("b/t", "hello");
if cfg!(not(target_os = "windows")) {
ucmd.arg("-s")
.arg("a/t")
.arg("b/t")
.arg(".")
.fails()
.stderr_only("cp: will not overwrite just-created './t' with 'b/t'\n");
assert_eq!(at.read("./t"), "hello");
} else {
ucmd.arg("-s")
.arg("a\\t")
.arg("b\\t")
.arg(".")
.fails()
.stderr_only("cp: will not overwrite just-created '.\\t' with 'b\\t'\n");
assert_eq!(at.read(".\\t"), "hello");
}
}
// make sure that cp backup dest symlink before removing it. // make sure that cp backup dest symlink before removing it.
#[test] #[test]
fn test_cp_with_options_backup_and_rem_when_dest_is_symlink() { fn test_cp_with_options_backup_and_rem_when_dest_is_symlink() {