mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
cp: improve the support of --attributes-only (#6051)
* cp: improve the support of --attributes-only * remove useless comments Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com> --------- Co-authored-by: Daniel Hofstetter <daniel.hofstetter@42dh.com>
This commit is contained in:
parent
80702d5391
commit
89b326fe1e
2 changed files with 81 additions and 2 deletions
|
@ -780,7 +780,11 @@ impl CopyMode {
|
||||||
{
|
{
|
||||||
Self::Update
|
Self::Update
|
||||||
} else if matches.get_flag(options::ATTRIBUTES_ONLY) {
|
} else if matches.get_flag(options::ATTRIBUTES_ONLY) {
|
||||||
Self::AttrOnly
|
if matches.get_flag(options::REMOVE_DESTINATION) {
|
||||||
|
Self::Copy
|
||||||
|
} else {
|
||||||
|
Self::AttrOnly
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Self::Copy
|
Self::Copy
|
||||||
}
|
}
|
||||||
|
@ -1709,7 +1713,13 @@ fn copy_file(
|
||||||
fs::remove_file(dest)?;
|
fs::remove_file(dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if file_or_link_exists(dest) {
|
if file_or_link_exists(dest)
|
||||||
|
&& (!options.attributes_only
|
||||||
|
|| matches!(
|
||||||
|
options.overwrite,
|
||||||
|
OverwriteMode::Clobber(ClobberMode::RemoveDestination)
|
||||||
|
))
|
||||||
|
{
|
||||||
if are_hardlinks_to_same_file(source, dest)
|
if are_hardlinks_to_same_file(source, dest)
|
||||||
&& !options.force()
|
&& !options.force()
|
||||||
&& options.backup == BackupMode::NoBackup
|
&& options.backup == BackupMode::NoBackup
|
||||||
|
@ -1721,6 +1731,20 @@ fn copy_file(
|
||||||
handle_existing_dest(source, dest, options, source_in_command_line)?;
|
handle_existing_dest(source, dest, options, source_in_command_line)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.attributes_only
|
||||||
|
&& source.is_symlink()
|
||||||
|
&& !matches!(
|
||||||
|
options.overwrite,
|
||||||
|
OverwriteMode::Clobber(ClobberMode::RemoveDestination)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return Err(format!(
|
||||||
|
"cannot change attribute {}: Source file is a non regular file",
|
||||||
|
dest.quote()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
if options.preserve_hard_links() {
|
if options.preserve_hard_links() {
|
||||||
// if we encounter a matching device/inode pair in the source tree
|
// if we encounter a matching device/inode pair in the source tree
|
||||||
// we can arrange to create a hard link between the corresponding names
|
// we can arrange to create a hard link between the corresponding names
|
||||||
|
|
|
@ -3800,3 +3800,58 @@ fn test_acl_preserve() {
|
||||||
|
|
||||||
assert!(compare_xattrs(&file, &file_target));
|
assert!(compare_xattrs(&file, &file_target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cp_force_remove_destination_attributes_only_with_symlink() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
at.write("file1", "1");
|
||||||
|
at.write("file2", "2");
|
||||||
|
at.symlink_file("file1", "sym1");
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.args(&[
|
||||||
|
"-a",
|
||||||
|
"--remove-destination",
|
||||||
|
"--attributes-only",
|
||||||
|
"sym1",
|
||||||
|
"file2",
|
||||||
|
])
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
at.symlink_exists("file2"),
|
||||||
|
"file2 is not a symbolic link as expected"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
at.read("file1"),
|
||||||
|
at.read("file2"),
|
||||||
|
"Contents of file1 and file2 do not match"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cp_no_dereference_attributes_only_with_symlink() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
at.write("file1", "1");
|
||||||
|
at.write("file2", "2");
|
||||||
|
at.write("file2.exp", "2");
|
||||||
|
at.symlink_file("file1", "sym1");
|
||||||
|
|
||||||
|
let result = scene
|
||||||
|
.ucmd()
|
||||||
|
.args(&["--no-dereference", "--attributes-only", "sym1", "file2"])
|
||||||
|
.fails();
|
||||||
|
|
||||||
|
assert_eq!(result.code(), 1, "cp command did not fail");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
at.read("file2"),
|
||||||
|
at.read("file2.exp"),
|
||||||
|
"file2 content does not match expected"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue