From 25ef39472c46b231944d56e6cf53a1e220eeb6d2 Mon Sep 17 00:00:00 2001 From: Jan Scheer Date: Mon, 21 Jun 2021 14:33:09 +0200 Subject: [PATCH] groups: fix to pass GNU Testsuite `groups-process-all.sh` * add support for multiple users * sync help text with GNU's `groups` manpage --- src/uu/groups/Cargo.toml | 2 +- src/uu/groups/src/groups.rs | 84 +++++++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/uu/groups/Cargo.toml b/src/uu/groups/Cargo.toml index 4a5a537e5..e7ce52650 100644 --- a/src/uu/groups/Cargo.toml +++ b/src/uu/groups/Cargo.toml @@ -3,7 +3,7 @@ name = "uu_groups" version = "0.0.6" authors = ["uutils developers"] license = "MIT" -description = "groups ~ (uutils) display group memberships for USERNAME" +description = "groups ~ (uutils) print the groups a user is in" homepage = "https://github.com/uutils/coreutils" repository = "https://github.com/uutils/coreutils/tree/master/src/uu/groups" diff --git a/src/uu/groups/src/groups.rs b/src/uu/groups/src/groups.rs index 746b7ff97..22e7b8918 100644 --- a/src/uu/groups/src/groups.rs +++ b/src/uu/groups/src/groups.rs @@ -5,6 +5,13 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +// +// ============================================================================ +// Testsuite summary for GNU coreutils 8.32.162-4eda +// ============================================================================ +// PASS: tests/misc/groups-dash.sh +// PASS: tests/misc/groups-process-all.sh +// PASS: tests/misc/groups-version.sh // spell-checker:ignore (ToDO) passwd @@ -14,11 +21,15 @@ use uucore::entries::{get_groups_gnu, gid2grp, Locate, Passwd}; use clap::{crate_version, App, Arg}; -static ABOUT: &str = "display current group names"; -static OPT_USER: &str = "user"; +mod options { + pub const USERS: &str = "USERNAME"; +} +static ABOUT: &str = "Print group memberships for each USERNAME or, \ + if no USERNAME is specified, for\nthe current process \ + (which may differ if the groups data‐base has changed)."; fn get_usage() -> String { - format!("{0} [USERNAME]", executable!()) + format!("{0} [OPTION]... [USERNAME]...", executable!()) } pub fn uumain(args: impl uucore::Args) -> i32 { @@ -28,36 +39,57 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .version(crate_version!()) .about(ABOUT) .usage(&usage[..]) - .arg(Arg::with_name(OPT_USER)) + .arg( + Arg::with_name(options::USERS) + .multiple(true) + .takes_value(true) + .value_name(options::USERS), + ) .get_matches_from(args); - match matches.value_of(OPT_USER) { - None => { + let users: Vec = matches + .values_of(options::USERS) + .map(|v| v.map(ToString::to_string).collect()) + .unwrap_or_default(); + + let mut exit_code = 1; + + if users.is_empty() { + println!( + "{}", + get_groups_gnu(None) + .unwrap() + .iter() + .map(|&gid| gid2grp(gid).unwrap_or_else(|_| { + show_error!("cannot find name for group ID {}", gid); + exit_code = 1; + gid.to_string() + })) + .collect::>() + .join(" ") + ); + return exit_code; + } + + for user in users { + if let Ok(p) = Passwd::locate(user.as_str()) { println!( - "{}", - get_groups_gnu(None) - .unwrap() + "{} : {}", + user, + p.belongs_to() .iter() - .map(|&g| gid2grp(g).unwrap()) + .map(|&gid| gid2grp(gid).unwrap_or_else(|_| { + show_error!("cannot find name for group ID {}", gid); + exit_code = 1; + gid.to_string() + })) .collect::>() .join(" ") ); - 0 - } - Some(user) => { - if let Ok(p) = Passwd::locate(user) { - println!( - "{}", - p.belongs_to() - .iter() - .map(|&g| gid2grp(g).unwrap()) - .collect::>() - .join(" ") - ); - 0 - } else { - crash!(1, "'{}': no such user", user); - } + } else { + show_error!("'{}': no such user", user); + exit_code = 1; } } + exit_code }