mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
mv: preserve the xattr
Should make tests/mv/acl pass
This commit is contained in:
parent
238fb776ad
commit
2ec4e9f784
5 changed files with 60 additions and 1 deletions
|
@ -42,6 +42,7 @@ fileio
|
||||||
filesystem
|
filesystem
|
||||||
filesystems
|
filesystems
|
||||||
flamegraph
|
flamegraph
|
||||||
|
fsxattr
|
||||||
fullblock
|
fullblock
|
||||||
getfacl
|
getfacl
|
||||||
gibi
|
gibi
|
||||||
|
@ -133,6 +134,7 @@ urand
|
||||||
whitespace
|
whitespace
|
||||||
wordlist
|
wordlist
|
||||||
wordlists
|
wordlists
|
||||||
|
xattrs
|
||||||
|
|
||||||
# * abbreviations
|
# * abbreviations
|
||||||
consts
|
consts
|
||||||
|
|
|
@ -21,6 +21,7 @@ indicatif = { workspace = true }
|
||||||
uucore = { workspace = true, features = [
|
uucore = { workspace = true, features = [
|
||||||
"backup-control",
|
"backup-control",
|
||||||
"fs",
|
"fs",
|
||||||
|
"fsxattr",
|
||||||
"update-control",
|
"update-control",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,10 @@ use uucore::fs::{
|
||||||
are_hardlinks_or_one_way_symlink_to_same_file, are_hardlinks_to_same_file,
|
are_hardlinks_or_one_way_symlink_to_same_file, are_hardlinks_to_same_file,
|
||||||
path_ends_with_terminator,
|
path_ends_with_terminator,
|
||||||
};
|
};
|
||||||
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
|
use uucore::fsxattr;
|
||||||
use uucore::update_control;
|
use uucore::update_control;
|
||||||
|
|
||||||
// These are exposed for projects (e.g. nushell) that want to create an `Options` value, which
|
// These are exposed for projects (e.g. nushell) that want to create an `Options` value, which
|
||||||
// requires these enums
|
// requires these enums
|
||||||
pub use uucore::{backup_control::BackupMode, update_control::UpdateMode};
|
pub use uucore::{backup_control::BackupMode, update_control::UpdateMode};
|
||||||
|
@ -631,6 +634,10 @@ fn rename_with_fallback(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
|
let xattrs =
|
||||||
|
fsxattr::retrieve_xattrs(from).unwrap_or_else(|_| std::collections::HashMap::new());
|
||||||
|
|
||||||
let result = if let Some(ref pb) = progress_bar {
|
let result = if let Some(ref pb) = progress_bar {
|
||||||
move_dir_with_progress(from, to, &options, |process_info: TransitProcess| {
|
move_dir_with_progress(from, to, &options, |process_info: TransitProcess| {
|
||||||
pb.set_position(process_info.copied_bytes);
|
pb.set_position(process_info.copied_bytes);
|
||||||
|
@ -641,6 +648,9 @@ fn rename_with_fallback(
|
||||||
move_dir(from, to, &options)
|
move_dir(from, to, &options)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
|
fsxattr::apply_xattrs(to, xattrs).unwrap();
|
||||||
|
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
return match err.kind {
|
return match err.kind {
|
||||||
fs_extra::error::ErrorKind::PermissionDenied => Err(io::Error::new(
|
fs_extra::error::ErrorKind::PermissionDenied => Err(io::Error::new(
|
||||||
|
@ -651,6 +661,11 @@ fn rename_with_fallback(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
|
fs::copy(from, to)
|
||||||
|
.and_then(|_| fsxattr::copy_xattrs(&from, &to))
|
||||||
|
.and_then(|_| fs::remove_file(from))?;
|
||||||
|
#[cfg(any(target_os = "macos", not(unix)))]
|
||||||
fs::copy(from, to).and_then(|_| fs::remove_file(from))?;
|
fs::copy(from, to).and_then(|_| fs::remove_file(from))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ encoding = ["data-encoding", "data-encoding-macro", "z85", "thiserror"]
|
||||||
entries = ["libc"]
|
entries = ["libc"]
|
||||||
fs = ["dunce", "libc", "winapi-util", "windows-sys"]
|
fs = ["dunce", "libc", "winapi-util", "windows-sys"]
|
||||||
fsext = ["libc", "time", "windows-sys"]
|
fsext = ["libc", "time", "windows-sys"]
|
||||||
fsxattr = [ "xattr" ]
|
fsxattr = ["xattr"]
|
||||||
lines = []
|
lines = []
|
||||||
format = ["itertools"]
|
format = ["itertools"]
|
||||||
mode = ["libc"]
|
mode = ["libc"]
|
||||||
|
|
|
@ -1569,6 +1569,47 @@ fn test_mv_dir_into_path_slash() {
|
||||||
assert!(at.dir_exists("f/b"));
|
assert!(at.dir_exists("f/b"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
|
#[test]
|
||||||
|
fn test_acl() {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use crate::common::util::compare_xattrs;
|
||||||
|
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
let path1 = "a";
|
||||||
|
let path2 = "b";
|
||||||
|
let file = "a/file";
|
||||||
|
let file_target = "b/file";
|
||||||
|
at.mkdir(path1);
|
||||||
|
at.mkdir(path2);
|
||||||
|
at.touch(file);
|
||||||
|
|
||||||
|
let path = at.plus_as_string(file);
|
||||||
|
// calling the command directly. xattr requires some dev packages to be installed
|
||||||
|
// and it adds a complex dependency just for a test
|
||||||
|
match Command::new("setfacl")
|
||||||
|
.args(["-m", "group::rwx", &path1])
|
||||||
|
.status()
|
||||||
|
.map(|status| status.code())
|
||||||
|
{
|
||||||
|
Ok(Some(0)) => {}
|
||||||
|
Ok(_) => {
|
||||||
|
println!("test skipped: setfacl failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("test skipped: setfacl failed with {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.ucmd().arg(&path).arg(path2).succeeds();
|
||||||
|
|
||||||
|
assert!(compare_xattrs(&file, &file_target));
|
||||||
|
}
|
||||||
|
|
||||||
// Todo:
|
// Todo:
|
||||||
|
|
||||||
// $ at.touch a b
|
// $ at.touch a b
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue