mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
mv: support moving folder containing symlinks to different filesystem (#8605)
Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
This commit is contained in:
co-authored by
Sylvestre Ledru
parent
88051cba99
commit
cc389e5927
+20
-9
@@ -1099,7 +1099,13 @@ fn copy_dir_contents_recursive(
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
fs::copy(&from_path, &to_path)?;
|
||||
if from_path.is_symlink() {
|
||||
// Copy a symlink file (no-follow).
|
||||
rename_symlink_fallback(&from_path, &to_path)?;
|
||||
} else {
|
||||
// Copy a regular file.
|
||||
fs::copy(&from_path, &to_path)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Print verbose message for file
|
||||
@@ -1142,14 +1148,19 @@ fn copy_file_with_hardlinks_helper(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Regular file copy
|
||||
#[cfg(all(unix, not(any(target_os = "macos", target_os = "redox"))))]
|
||||
{
|
||||
fs::copy(from, to).and_then(|_| fsxattr::copy_xattrs(&from, &to))?;
|
||||
}
|
||||
#[cfg(any(target_os = "macos", target_os = "redox"))]
|
||||
{
|
||||
fs::copy(from, to)?;
|
||||
if from.is_symlink() {
|
||||
// Copy a symlink file (no-follow).
|
||||
rename_symlink_fallback(from, to)?;
|
||||
} else {
|
||||
// Copy a regular file.
|
||||
#[cfg(all(unix, not(any(target_os = "macos", target_os = "redox"))))]
|
||||
{
|
||||
fs::copy(from, to).and_then(|_| fsxattr::copy_xattrs(&from, &to))?;
|
||||
}
|
||||
#[cfg(any(target_os = "macos", target_os = "redox"))]
|
||||
{
|
||||
fs::copy(from, to)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -623,6 +623,58 @@ fn test_mv_symlink_into_target() {
|
||||
ucmd.arg("dir-link").arg("dir").succeeds();
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "android")))]
|
||||
#[ignore = "requires sudo"]
|
||||
#[test]
|
||||
fn test_mv_broken_symlink_to_another_fs() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
scene.fixtures.mkdir("foo");
|
||||
|
||||
let output = scene
|
||||
.cmd("sudo")
|
||||
.env("PATH", env!("PATH"))
|
||||
.args(&["-E", "--non-interactive", "ls"])
|
||||
.run();
|
||||
println!("test output: {output:?}");
|
||||
|
||||
let mount = scene
|
||||
.cmd("sudo")
|
||||
.env("PATH", env!("PATH"))
|
||||
.args(&[
|
||||
"-E",
|
||||
"--non-interactive",
|
||||
"mount",
|
||||
"none",
|
||||
"-t",
|
||||
"tmpfs",
|
||||
"foo",
|
||||
])
|
||||
.run();
|
||||
|
||||
if !mount.succeeded() {
|
||||
print!("Test skipped; requires root user");
|
||||
return;
|
||||
}
|
||||
|
||||
scene.fixtures.mkdir("bar");
|
||||
scene.fixtures.symlink_file("nonexistent", "bar/baz");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("bar")
|
||||
.arg("foo")
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.no_stdout();
|
||||
|
||||
scene
|
||||
.cmd("sudo")
|
||||
.env("PATH", env!("PATH"))
|
||||
.args(&["-E", "--non-interactive", "umount", "foo"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, not(target_os = "android")))]
|
||||
fn test_mv_hardlink_to_symlink() {
|
||||
|
||||
Reference in New Issue
Block a user