From 836351dd7a8920534b1ac64ee0c2ff46a391ba18 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 28 Dec 2024 23:41:14 +0100 Subject: [PATCH] ch*: refactor duplicate declarations --- src/uu/chgrp/src/chgrp.rs | 30 ++++++++------------------ src/uu/chmod/src/chmod.rs | 18 +++++++++++----- src/uu/chown/src/chown.rs | 32 ++++++++-------------------- src/uucore/src/lib/features/perms.rs | 21 ++++++++++++++++++ 4 files changed, 52 insertions(+), 49 deletions(-) diff --git a/src/uu/chgrp/src/chgrp.rs b/src/uu/chgrp/src/chgrp.rs index fba2cef16..7f68f7b13 100644 --- a/src/uu/chgrp/src/chgrp.rs +++ b/src/uu/chgrp/src/chgrp.rs @@ -63,7 +63,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } pub fn uu_app() -> Command { - Command::new(uucore::util_name()) + let mut cmd = Command::new(uucore::util_name()) .version(crate_version!()) .about(ABOUT) .override_usage(format_usage(USAGE)) @@ -140,24 +140,12 @@ pub fn uu_app() -> Command { .long(options::RECURSIVE) .help("operate on files and directories recursively") .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::traverse::TRAVERSE) - .short(options::traverse::TRAVERSE.chars().next().unwrap()) - .help("if a command line argument is a symbolic link to a directory, traverse it") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::traverse::NO_TRAVERSE) - .short(options::traverse::NO_TRAVERSE.chars().next().unwrap()) - .help("do not traverse any symbolic links (default)") - .overrides_with_all([options::traverse::TRAVERSE, options::traverse::EVERY]) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::traverse::EVERY) - .short(options::traverse::EVERY.chars().next().unwrap()) - .help("traverse every symbolic link to a directory encountered") - .action(ArgAction::SetTrue), - ) + ); + + // Add traverse-related arguments + for arg in uucore::perms::traverse_args() { + cmd = cmd.arg(arg); + } + + cmd } diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index d13257437..07c04a98d 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -151,7 +151,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } pub fn uu_app() -> Command { - Command::new(uucore::util_name()) + let mut cmd = Command::new(uucore::util_name()) .version(crate_version!()) .about(ABOUT) .override_usage(format_usage(USAGE)) @@ -206,16 +206,24 @@ pub fn uu_app() -> Command { .help("use RFILE's mode instead of MODE values"), ) .arg( - Arg::new(options::MODE).required_unless_present(options::REFERENCE), // It would be nice if clap could parse with delimiter, e.g. "g-x,u+x", - // however .multiple_occurrences(true) cannot be used here because FILE already needs that. - // Only one positional argument with .multiple_occurrences(true) set is allowed per command + Arg::new(options::MODE).required_unless_present(options::REFERENCE), + // It would be nice if clap could parse with delimiter, e.g. "g-x,u+x", + // however .multiple_occurrences(true) cannot be used here because FILE already needs that. + // Only one positional argument with .multiple_occurrences(true) set is allowed per command ) .arg( Arg::new(options::FILE) .required_unless_present(options::MODE) .action(ArgAction::Append) .value_hint(clap::ValueHint::AnyPath), - ) + ); + + // Add traverse-related arguments + for arg in uucore::perms::traverse_args() { + cmd = cmd.arg(arg); + } + + cmd } struct Chmoder { diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 0e9b8b242..61fe24eab 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -77,7 +77,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } pub fn uu_app() -> Command { - Command::new(uucore::util_name()) + let mut cmd = Command::new(uucore::util_name()) .version(crate_version!()) .about(ABOUT) .override_usage(format_usage(USAGE)) @@ -165,34 +165,20 @@ pub fn uu_app() -> Command { .long(options::verbosity::SILENT) .action(ArgAction::SetTrue), ) - .arg( - Arg::new(options::traverse::TRAVERSE) - .short(options::traverse::TRAVERSE.chars().next().unwrap()) - .help("if a command line argument is a symbolic link to a directory, traverse it") - .overrides_with_all([options::traverse::EVERY, options::traverse::NO_TRAVERSE]) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::traverse::EVERY) - .short(options::traverse::EVERY.chars().next().unwrap()) - .help("traverse every symbolic link to a directory encountered") - .overrides_with_all([options::traverse::TRAVERSE, options::traverse::NO_TRAVERSE]) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::traverse::NO_TRAVERSE) - .short(options::traverse::NO_TRAVERSE.chars().next().unwrap()) - .help("do not traverse any symbolic links (default)") - .overrides_with_all([options::traverse::TRAVERSE, options::traverse::EVERY]) - .action(ArgAction::SetTrue), - ) .arg( Arg::new(options::verbosity::VERBOSE) .long(options::verbosity::VERBOSE) .short('v') .help("output a diagnostic for every file processed") .action(ArgAction::SetTrue), - ) + ); + + // Add traverse-related arguments + for arg in uucore::perms::traverse_args() { + cmd = cmd.arg(arg); + } + + cmd } /// Parses the user string to extract the UID. diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs index 3623e9e61..9ee64e212 100644 --- a/src/uucore/src/lib/features/perms.rs +++ b/src/uucore/src/lib/features/perms.rs @@ -13,6 +13,7 @@ pub use crate::features::entries; use crate::show_error; use clap::{Arg, ArgMatches, Command}; use libc::{gid_t, uid_t}; +use options::traverse; use walkdir::WalkDir; use std::io::Error as IOError; @@ -634,6 +635,26 @@ pub fn chown_base( executor.exec() } +pub fn traverse_args() -> Vec { + vec![ + Arg::new(traverse::TRAVERSE) + .short(traverse::TRAVERSE.chars().next().unwrap()) + .help("if a command line argument is a symbolic link to a directory, traverse it") + .overrides_with_all([traverse::EVERY, traverse::NO_TRAVERSE]) + .action(clap::ArgAction::SetTrue), + Arg::new(traverse::EVERY) + .short(traverse::EVERY.chars().next().unwrap()) + .help("traverse every symbolic link to a directory encountered") + .overrides_with_all([traverse::TRAVERSE, traverse::NO_TRAVERSE]) + .action(clap::ArgAction::SetTrue), + Arg::new(traverse::NO_TRAVERSE) + .short(traverse::NO_TRAVERSE.chars().next().unwrap()) + .help("do not traverse any symbolic links (default)") + .overrides_with_all([traverse::TRAVERSE, traverse::EVERY]) + .action(clap::ArgAction::SetTrue), + ] +} + #[cfg(test)] mod tests { // Note this useful idiom: importing names from outer (for mod tests) scope.