mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #2437 from miDeb/cp/reflink-auto
cp: default to --reflink=auto on linux and macos
This commit is contained in:
commit
a73e71ba74
2 changed files with 54 additions and 18 deletions
|
@ -667,7 +667,14 @@ impl Options {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ReflinkMode::Never
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
{
|
||||
ReflinkMode::Auto
|
||||
}
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
{
|
||||
ReflinkMode::Never
|
||||
}
|
||||
}
|
||||
},
|
||||
backup: backup_mode,
|
||||
|
@ -1218,28 +1225,39 @@ fn copy_file(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> {
|
|||
/// Copy the file from `source` to `dest` either using the normal `fs::copy` or a
|
||||
/// copy-on-write scheme if --reflink is specified and the filesystem supports it.
|
||||
fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> {
|
||||
if options.reflink_mode != ReflinkMode::Never {
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
return Err("--reflink is only supported on linux and macOS"
|
||||
.to_string()
|
||||
.into());
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
copy_on_write_macos(source, dest, options.reflink_mode)?;
|
||||
#[cfg(target_os = "linux")]
|
||||
copy_on_write_linux(source, dest, options.reflink_mode)?;
|
||||
} else if !options.dereference && fs::symlink_metadata(&source)?.file_type().is_symlink() {
|
||||
copy_link(source, dest)?;
|
||||
} else if source.to_string_lossy() == "/dev/null" {
|
||||
if options.parents {
|
||||
let parent = dest.parent().unwrap_or(dest);
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
let is_symlink = fs::symlink_metadata(&source)?.file_type().is_symlink();
|
||||
if source.to_string_lossy() == "/dev/null" {
|
||||
/* workaround a limitation of fs::copy
|
||||
* https://github.com/rust-lang/rust/issues/79390
|
||||
*/
|
||||
File::create(dest)?;
|
||||
} else {
|
||||
if options.parents {
|
||||
let parent = dest.parent().unwrap_or(dest);
|
||||
fs::create_dir_all(parent)?;
|
||||
} else if !options.dereference && is_symlink {
|
||||
copy_link(source, dest)?;
|
||||
} else if options.reflink_mode != ReflinkMode::Never {
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
return Err("--reflink is only supported on linux and macOS"
|
||||
.to_string()
|
||||
.into());
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
if is_symlink {
|
||||
assert!(options.dereference);
|
||||
let real_path = std::fs::read_link(source)?;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
copy_on_write_macos(&real_path, dest, options.reflink_mode)?;
|
||||
#[cfg(target_os = "linux")]
|
||||
copy_on_write_linux(&real_path, dest, options.reflink_mode)?;
|
||||
} else {
|
||||
#[cfg(target_os = "macos")]
|
||||
copy_on_write_macos(source, dest, options.reflink_mode)?;
|
||||
#[cfg(target_os = "linux")]
|
||||
copy_on_write_linux(source, dest, options.reflink_mode)?;
|
||||
}
|
||||
} else {
|
||||
fs::copy(source, dest).context(&*context_for(source, dest))?;
|
||||
}
|
||||
|
||||
|
@ -1259,6 +1277,11 @@ fn copy_link(source: &Path, dest: &Path) -> CopyResult<()> {
|
|||
),
|
||||
}
|
||||
} else {
|
||||
// we always need to remove the file to be able to create a symlink,
|
||||
// even if it is writeable.
|
||||
if dest.exists() {
|
||||
fs::remove_file(dest)?;
|
||||
}
|
||||
dest.into()
|
||||
};
|
||||
symlink_file(&link, &dest, &*context_for(&link, &dest))
|
||||
|
|
|
@ -1325,3 +1325,16 @@ fn test_copy_dir_with_symlinks() {
|
|||
ucmd.args(&["-r", "dir", "copy"]).succeeds();
|
||||
assert_eq!(at.resolve_link("copy/file-link"), "file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn test_copy_symlink_force() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.touch("file");
|
||||
at.symlink_file("file", "file-link");
|
||||
at.touch("copy");
|
||||
|
||||
ucmd.args(&["file-link", "copy", "-f", "--no-dereference"])
|
||||
.succeeds();
|
||||
assert_eq!(at.resolve_link("copy"), "file");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue