diff --git a/src/uu/chgrp/src/chgrp.rs b/src/uu/chgrp/src/chgrp.rs index fba2cef16..fe5aee872 100644 --- a/src/uu/chgrp/src/chgrp.rs +++ b/src/uu/chgrp/src/chgrp.rs @@ -73,7 +73,7 @@ pub fn uu_app() -> Command { Arg::new(options::HELP) .long(options::HELP) .help("Print help information.") - .action(ArgAction::Help) + .action(ArgAction::Help), ) .arg( Arg::new(options::verbosity::CHANGES) @@ -101,20 +101,6 @@ pub fn uu_app() -> Command { .help("output a diagnostic for every file processed") .action(ArgAction::SetTrue), ) - .arg( - Arg::new(options::dereference::DEREFERENCE) - .long(options::dereference::DEREFERENCE) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::dereference::NO_DEREFERENCE) - .short('h') - .long(options::dereference::NO_DEREFERENCE) - .help( - "affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)", - ) - .action(ArgAction::SetTrue), - ) .arg( Arg::new(options::preserve_root::PRESERVE) .long(options::preserve_root::PRESERVE) @@ -141,23 +127,6 @@ pub fn uu_app() -> Command { .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 common arguments with chgrp, chown & chmod + .args(uucore::perms::common_args()) } diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index d13257437..c05288e21 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -23,6 +23,7 @@ const USAGE: &str = help_usage!("chmod.md"); const LONG_USAGE: &str = help_section!("after help", "chmod.md"); mod options { + pub const HELP: &str = "help"; pub const CHANGES: &str = "changes"; pub const QUIET: &str = "quiet"; // visible_alias("silent") pub const VERBOSE: &str = "verbose"; @@ -158,6 +159,13 @@ pub fn uu_app() -> Command { .args_override_self(true) .infer_long_args(true) .no_binary_name(true) + .disable_help_flag(true) + .arg( + Arg::new(options::HELP) + .long(options::HELP) + .help("Print help information.") + .action(ArgAction::Help), + ) .arg( Arg::new(options::CHANGES) .long(options::CHANGES) @@ -206,9 +214,10 @@ 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) @@ -216,6 +225,8 @@ pub fn uu_app() -> Command { .action(ArgAction::Append) .value_hint(clap::ValueHint::AnyPath), ) + // Add common arguments with chgrp, chown & chmod + .args(uucore::perms::common_args()) } struct Chmoder { diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 0e9b8b242..20bc87c34 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -96,25 +96,6 @@ pub fn uu_app() -> Command { .help("like verbose but report only when a change is made") .action(ArgAction::SetTrue), ) - .arg( - Arg::new(options::dereference::DEREFERENCE) - .long(options::dereference::DEREFERENCE) - .help( - "affect the referent of each symbolic link (this is the default), \ - rather than the symbolic link itself", - ) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new(options::dereference::NO_DEREFERENCE) - .short('h') - .long(options::dereference::NO_DEREFERENCE) - .help( - "affect symbolic links instead of any referenced file \ - (useful only on systems that can change the ownership of a symlink)", - ) - .action(ArgAction::SetTrue), - ) .arg( Arg::new(options::FROM) .long(options::FROM) @@ -165,27 +146,6 @@ 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) @@ -193,6 +153,8 @@ pub fn uu_app() -> Command { .help("output a diagnostic for every file processed") .action(ArgAction::SetTrue), ) + // Add common arguments with chgrp, chown & chmod + .args(uucore::perms::common_args()) } /// 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..73b84be72 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; @@ -33,6 +34,7 @@ pub enum VerbosityLevel { Verbose, Normal, } + #[derive(PartialEq, Eq, Clone, Debug)] pub struct Verbosity { pub groups_only: bool, @@ -634,6 +636,41 @@ pub fn chown_base( executor.exec() } +pub fn common_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), + Arg::new(options::dereference::DEREFERENCE) + .long(options::dereference::DEREFERENCE) + .help( + "affect the referent of each symbolic link (this is the default), \ + rather than the symbolic link itself", + ) + .action(clap::ArgAction::SetTrue), + Arg::new(options::dereference::NO_DEREFERENCE) + .short('h') + .long(options::dereference::NO_DEREFERENCE) + .help( + "affect symbolic links instead of any referenced file \ + (useful only on systems that can change the ownership of a symlink)", + ) + .action(clap::ArgAction::SetTrue), + ] +} + #[cfg(test)] mod tests { // Note this useful idiom: importing names from outer (for mod tests) scope.