mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +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,8 +667,15 @@ impl Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
|
{
|
||||||
|
ReflinkMode::Auto
|
||||||
|
}
|
||||||
|
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||||
|
{
|
||||||
ReflinkMode::Never
|
ReflinkMode::Never
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
backup: backup_mode,
|
backup: backup_mode,
|
||||||
backup_suffix,
|
backup_suffix,
|
||||||
|
@ -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 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.
|
/// copy-on-write scheme if --reflink is specified and the filesystem supports it.
|
||||||
fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()> {
|
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" {
|
|
||||||
/* workaround a limitation of fs::copy
|
|
||||||
* https://github.com/rust-lang/rust/issues/79390
|
|
||||||
*/
|
|
||||||
File::create(dest)?;
|
|
||||||
} else {
|
|
||||||
if options.parents {
|
if options.parents {
|
||||||
let parent = dest.parent().unwrap_or(dest);
|
let parent = dest.parent().unwrap_or(dest);
|
||||||
fs::create_dir_all(parent)?;
|
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.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))?;
|
fs::copy(source, dest).context(&*context_for(source, dest))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1259,6 +1277,11 @@ fn copy_link(source: &Path, dest: &Path) -> CopyResult<()> {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} 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()
|
dest.into()
|
||||||
};
|
};
|
||||||
symlink_file(&link, &dest, &*context_for(&link, &dest))
|
symlink_file(&link, &dest, &*context_for(&link, &dest))
|
||||||
|
|
|
@ -1325,3 +1325,16 @@ fn test_copy_dir_with_symlinks() {
|
||||||
ucmd.args(&["-r", "dir", "copy"]).succeeds();
|
ucmd.args(&["-r", "dir", "copy"]).succeeds();
|
||||||
assert_eq!(at.resolve_link("copy/file-link"), "file");
|
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