mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
chgrp: support the --from=:X syntax
This commit is contained in:
parent
8e9a4b5f9a
commit
d76c561516
2 changed files with 69 additions and 10 deletions
|
@ -19,6 +19,24 @@ use std::os::unix::fs::MetadataExt;
|
|||
const ABOUT: &str = help_about!("chgrp.md");
|
||||
const USAGE: &str = help_usage!("chgrp.md");
|
||||
|
||||
fn parse_gid_from_str(group: &str) -> Result<u32, String> {
|
||||
if let Some(gid_str) = group.strip_prefix(':') {
|
||||
// Handle :gid format
|
||||
gid_str
|
||||
.parse::<u32>()
|
||||
.map_err(|_| format!("invalid group id: '{}'", gid_str))
|
||||
} else {
|
||||
// Try as group name first
|
||||
match entries::grp2gid(group) {
|
||||
Ok(g) => Ok(g),
|
||||
// If group name lookup fails, try parsing as raw number
|
||||
Err(_) => group
|
||||
.parse::<u32>()
|
||||
.map_err(|_| format!("invalid group: '{}'", group)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<GidUidOwnerFilter> {
|
||||
let mut raw_group: String = String::new();
|
||||
let dest_gid = if let Some(file) = matches.get_one::<String>(options::REFERENCE) {
|
||||
|
@ -38,26 +56,21 @@ fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<GidUidOwnerFilter> {
|
|||
if group.is_empty() {
|
||||
None
|
||||
} else {
|
||||
match entries::grp2gid(group) {
|
||||
match parse_gid_from_str(group) {
|
||||
Ok(g) => Some(g),
|
||||
_ => {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
format!("invalid group: {}", group.quote()),
|
||||
))
|
||||
}
|
||||
Err(e) => return Err(USimpleError::new(1, e)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handle --from option
|
||||
let filter = if let Some(from_group) = matches.get_one::<String>(options::FROM) {
|
||||
match entries::grp2gid(from_group) {
|
||||
match parse_gid_from_str(from_group) {
|
||||
Ok(g) => IfFrom::Group(g),
|
||||
_ => {
|
||||
Err(_) => {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
format!("invalid group: {}", from_group.quote()),
|
||||
format!("invalid user: '{}'", from_group),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -547,3 +547,49 @@ fn test_from_with_reference() {
|
|||
let ref_gid = at.plus("ref_file").metadata().unwrap().gid();
|
||||
assert_eq!(new_gid, ref_gid);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn test_numeric_group_formats() {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let groups = nix::unistd::getgroups().unwrap();
|
||||
if groups.len() < 2 {
|
||||
return;
|
||||
}
|
||||
let (first_group, second_group) = (groups[0], groups[1]);
|
||||
|
||||
at.touch("test_file");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(first_group.to_string())
|
||||
.arg("test_file")
|
||||
.succeeds();
|
||||
|
||||
// Test :gid format in --from
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("--from=:{}", first_group.as_raw()))
|
||||
.arg(second_group.to_string())
|
||||
.arg("test_file")
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
let new_gid = at.plus("test_file").metadata().unwrap().gid();
|
||||
assert_eq!(new_gid, second_group.as_raw());
|
||||
|
||||
// Test :gid format in target group
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("--from={}", second_group.as_raw()))
|
||||
.arg(format!(":{}", first_group.as_raw()))
|
||||
.arg("test_file")
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
let final_gid = at.plus("test_file").metadata().unwrap().gid();
|
||||
assert_eq!(final_gid, first_group.as_raw());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue