mirror of
https://github.com/uutils/coreutils
synced 2024-10-02 22:13:37 +00:00
gnu cp-parents
test case (#6446)
This commit is contained in:
parent
ef68e60c85
commit
e46ad30434
|
@ -431,7 +431,9 @@ pub(crate) fn copy_directory(
|
||||||
let dest = target.join(root.file_name().unwrap());
|
let dest = target.join(root.file_name().unwrap());
|
||||||
copy_attributes(root, dest.as_path(), &options.attributes)?;
|
copy_attributes(root, dest.as_path(), &options.attributes)?;
|
||||||
for (x, y) in aligned_ancestors(root, dest.as_path()) {
|
for (x, y) in aligned_ancestors(root, dest.as_path()) {
|
||||||
copy_attributes(x, y, &options.attributes)?;
|
if let Ok(src) = canonicalize(x, MissingHandling::Normal, ResolveMode::Physical) {
|
||||||
|
copy_attributes(&src, y, &options.attributes)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
copy_attributes(root, target, &options.attributes)?;
|
copy_attributes(root, target, &options.attributes)?;
|
||||||
|
|
|
@ -1332,7 +1332,11 @@ fn construct_dest_path(
|
||||||
Ok(match target_type {
|
Ok(match target_type {
|
||||||
TargetType::Directory => {
|
TargetType::Directory => {
|
||||||
let root = if options.parents {
|
let root = if options.parents {
|
||||||
|
if source_path.has_root() && cfg!(unix) {
|
||||||
|
Path::new("/")
|
||||||
|
} else {
|
||||||
Path::new("")
|
Path::new("")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
source_path.parent().unwrap_or(source_path)
|
source_path.parent().unwrap_or(source_path)
|
||||||
};
|
};
|
||||||
|
@ -1380,7 +1384,9 @@ fn copy_source(
|
||||||
);
|
);
|
||||||
if options.parents {
|
if options.parents {
|
||||||
for (x, y) in aligned_ancestors(source, dest.as_path()) {
|
for (x, y) in aligned_ancestors(source, dest.as_path()) {
|
||||||
copy_attributes(x, y, &options.attributes)?;
|
if let Ok(src) = canonicalize(x, MissingHandling::Normal, ResolveMode::Physical) {
|
||||||
|
copy_attributes(&src, y, &options.attributes)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
|
@ -1443,8 +1449,8 @@ pub(crate) fn copy_attributes(
|
||||||
|
|
||||||
let dest_uid = source_metadata.uid();
|
let dest_uid = source_metadata.uid();
|
||||||
let dest_gid = source_metadata.gid();
|
let dest_gid = source_metadata.gid();
|
||||||
|
// gnu compatibility: cp doesn't report an error if it fails to set the ownership.
|
||||||
wrap_chown(
|
let _ = wrap_chown(
|
||||||
dest,
|
dest,
|
||||||
&dest.symlink_metadata().context(context)?,
|
&dest.symlink_metadata().context(context)?,
|
||||||
Some(dest_uid),
|
Some(dest_uid),
|
||||||
|
@ -1452,11 +1458,9 @@ pub(crate) fn copy_attributes(
|
||||||
false,
|
false,
|
||||||
Verbosity {
|
Verbosity {
|
||||||
groups_only: false,
|
groups_only: false,
|
||||||
level: VerbosityLevel::Normal,
|
level: VerbosityLevel::Silent,
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
.map_err(Error::Error)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -2163,7 +2167,13 @@ fn copy_file(
|
||||||
fs::set_permissions(dest, dest_permissions).ok();
|
fs::set_permissions(dest, dest_permissions).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.dereference(source_in_command_line) {
|
||||||
|
if let Ok(src) = canonicalize(source, MissingHandling::Normal, ResolveMode::Physical) {
|
||||||
|
copy_attributes(&src, dest, &options.attributes)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
copy_attributes(source, dest, &options.attributes)?;
|
copy_attributes(source, dest, &options.attributes)?;
|
||||||
|
}
|
||||||
|
|
||||||
copied_files.insert(
|
copied_files.insert(
|
||||||
FileInformation::from_path(source, options.dereference(source_in_command_line))?,
|
FileInformation::from_path(source, options.dereference(source_in_command_line))?,
|
||||||
|
|
|
@ -5573,3 +5573,89 @@ fn test_preserve_attrs_overriding_2() {
|
||||||
assert_ne!(dest_file1_metadata.ino(), dest_file2_metadata.ino());
|
assert_ne!(dest_file1_metadata.ino(), dest_file2_metadata.ino());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test the behavior of preserving permissions when copying through a symlink
|
||||||
|
#[test]
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn test_cp_symlink_permissions() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
at.touch("a");
|
||||||
|
at.set_mode("a", 0o700);
|
||||||
|
at.symlink_file("a", "symlink");
|
||||||
|
at.mkdir("dest");
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.args(&["--preserve", "symlink", "dest"])
|
||||||
|
.succeeds();
|
||||||
|
let dest_dir_metadata = at.metadata("dest/symlink");
|
||||||
|
let src_dir_metadata = at.metadata("a");
|
||||||
|
assert_eq!(
|
||||||
|
src_dir_metadata.permissions().mode(),
|
||||||
|
dest_dir_metadata.permissions().mode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test the behavior of preserving permissions of parents when copying through a symlink
|
||||||
|
#[test]
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn test_cp_parents_symlink_permissions_file() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
at.mkdir("a");
|
||||||
|
at.touch("a/file");
|
||||||
|
at.set_mode("a", 0o700);
|
||||||
|
at.symlink_dir("a", "symlink");
|
||||||
|
at.mkdir("dest");
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.args(&["--parents", "-a", "symlink/file", "dest"])
|
||||||
|
.succeeds();
|
||||||
|
let dest_dir_metadata = at.metadata("dest/symlink");
|
||||||
|
let src_dir_metadata = at.metadata("a");
|
||||||
|
assert_eq!(
|
||||||
|
src_dir_metadata.permissions().mode(),
|
||||||
|
dest_dir_metadata.permissions().mode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test the behavior of preserving permissions of parents when copying through
|
||||||
|
/// a symlink when source is a dir.
|
||||||
|
#[test]
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn test_cp_parents_symlink_permissions_dir() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
at.mkdir_all("a/b");
|
||||||
|
at.set_mode("a", 0o755); // Set mode for the actual directory
|
||||||
|
at.symlink_dir("a", "symlink");
|
||||||
|
at.mkdir("dest");
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.args(&["--parents", "-a", "symlink/b", "dest"])
|
||||||
|
.succeeds();
|
||||||
|
let dest_dir_metadata = at.metadata("dest/symlink");
|
||||||
|
let src_dir_metadata = at.metadata("a");
|
||||||
|
assert_eq!(
|
||||||
|
src_dir_metadata.permissions().mode(),
|
||||||
|
dest_dir_metadata.permissions().mode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test the behavior of copying a file to a destination with parents using absolute paths.
|
||||||
|
#[cfg(unix)]
|
||||||
|
#[test]
|
||||||
|
fn test_cp_parents_absolute_path() {
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
at.mkdir_all("a/b");
|
||||||
|
at.touch("a/b/f");
|
||||||
|
at.mkdir("dest");
|
||||||
|
let src = format!("{}/a/b/f", at.root_dir_resolved());
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.args(&["--parents", src.as_str(), "dest"])
|
||||||
|
.succeeds();
|
||||||
|
let res = format!("dest{}/a/b/f", at.root_dir_resolved());
|
||||||
|
at.file_exists(res);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue