From 29d710367089b78c3774b01ea971fd7ff18ac025 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Fri, 31 Dec 2021 13:53:36 -0500 Subject: [PATCH 01/16] sum: return UResult from uumain() function --- src/uu/sum/src/sum.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/uu/sum/src/sum.rs b/src/uu/sum/src/sum.rs index c58a1dcdc..bcc4738e8 100644 --- a/src/uu/sum/src/sum.rs +++ b/src/uu/sum/src/sum.rs @@ -12,9 +12,10 @@ extern crate uucore; use clap::{crate_version, App, Arg}; use std::fs::File; -use std::io::{stdin, Read, Result}; +use std::io::{stdin, Read}; use std::path::Path; use uucore::display::Quotable; +use uucore::error::{FromIo, UResult, USimpleError}; use uucore::InvalidEncodingHandling; static NAME: &str = "sum"; @@ -65,26 +66,25 @@ fn sysv_sum(mut reader: Box) -> (usize, u16) { (blocks_read, ret as u16) } -fn open(name: &str) -> Result> { +fn open(name: &str) -> UResult> { match name { "-" => Ok(Box::new(stdin()) as Box), _ => { let path = &Path::new(name); if path.is_dir() { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "Is a directory", + return Err(USimpleError::new( + 2, + format!("{}: Is a directory", name.maybe_quote()), )); }; // Silent the warning as we want to the error message - #[allow(clippy::question_mark)] if path.metadata().is_err() { - return Err(std::io::Error::new( - std::io::ErrorKind::NotFound, - "No such file or directory", + return Err(USimpleError::new( + 2, + format!("{}: No such file or directory", name.maybe_quote()), )); }; - let f = File::open(path)?; + let f = File::open(path).map_err_context(String::new)?; Ok(Box::new(f) as Box) } } @@ -96,7 +96,8 @@ mod options { pub static SYSTEM_V_COMPATIBLE: &str = "sysv"; } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let args = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); @@ -116,13 +117,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 { files.len() > 1 }; - let mut exit_code = 0; for file in &files { let reader = match open(file) { Ok(f) => f, Err(error) => { - show_error!("{}: {}", file.maybe_quote(), error); - exit_code = 2; + show!(error); continue; } }; @@ -138,8 +137,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { println!("{} {}", sum, blocks); } } - - exit_code + Ok(()) } pub fn uu_app() -> App<'static, 'static> { From 4e16717c22c93e315cbba0ce28d27a1c3ce5fd6a Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Fri, 31 Dec 2021 13:59:20 -0500 Subject: [PATCH 02/16] sync: return UResult from uumain() function --- src/uu/sync/src/sync.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/uu/sync/src/sync.rs b/src/uu/sync/src/sync.rs index d6a21f280..9e5116a8f 100644 --- a/src/uu/sync/src/sync.rs +++ b/src/uu/sync/src/sync.rs @@ -9,14 +9,10 @@ extern crate libc; -#[macro_use] -extern crate uucore; - use clap::{crate_version, App, Arg}; use std::path::Path; use uucore::display::Quotable; - -static EXIT_ERR: i32 = 1; +use uucore::error::{UResult, USimpleError}; static ABOUT: &str = "Synchronize cached writes to persistent storage"; pub mod options { @@ -164,7 +160,8 @@ fn usage() -> String { format!("{0} [OPTION]... FILE...", uucore::execution_phrase()) } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = usage(); let matches = uu_app().usage(&usage[..]).get_matches_from(args); @@ -176,11 +173,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { for f in &files { if !Path::new(&f).exists() { - crash!( - EXIT_ERR, - "cannot stat {}: No such file or directory", - f.quote() - ); + return Err(USimpleError::new( + 1, + format!("cannot stat {}: No such file or directory", f.quote()), + )); } } @@ -194,7 +190,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { } else { sync(); } - 0 + Ok(()) } pub fn uu_app() -> App<'static, 'static> { From 28958a3ed2edcd9322c63dc88487803841357331 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Fri, 31 Dec 2021 14:07:39 -0500 Subject: [PATCH 03/16] tee: return UResult from uumain() function --- src/uu/tee/src/tee.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/uu/tee/src/tee.rs b/src/uu/tee/src/tee.rs index e977699ea..9629e711d 100644 --- a/src/uu/tee/src/tee.rs +++ b/src/uu/tee/src/tee.rs @@ -14,6 +14,7 @@ use std::fs::OpenOptions; use std::io::{copy, sink, stdin, stdout, Error, ErrorKind, Read, Result, Write}; use std::path::PathBuf; use uucore::display::Quotable; +use uucore::error::UResult; #[cfg(unix)] use uucore::libc; @@ -37,7 +38,8 @@ fn usage() -> String { format!("{0} [OPTION]... [FILE]...", uucore::execution_phrase()) } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = usage(); let matches = uu_app().usage(&usage[..]).get_matches_from(args); @@ -52,8 +54,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 { }; match tee(options) { - Ok(_) => 0, - Err(_) => 1, + Ok(_) => Ok(()), + Err(_) => Err(1.into()), } } From 1ead016f3531abcc5a04f22db81fcf8ba23a961f Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Fri, 31 Dec 2021 14:28:27 -0500 Subject: [PATCH 04/16] fixup! sync: return UResult from uumain() function --- src/uu/sync/src/sync.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uu/sync/src/sync.rs b/src/uu/sync/src/sync.rs index 9e5116a8f..4e6bb7d27 100644 --- a/src/uu/sync/src/sync.rs +++ b/src/uu/sync/src/sync.rs @@ -68,6 +68,7 @@ mod platform { use std::mem; use std::os::windows::prelude::*; use std::path::Path; + use uucore::crash; use uucore::wide::{FromWide, ToWide}; unsafe fn flush_volume(name: &str) { From d03dcc023160ad6ade3c9bd5d0a6d874b13308e5 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Fri, 31 Dec 2021 14:26:20 -0500 Subject: [PATCH 05/16] test: return UResult from uumain() function --- src/uu/test/src/test.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/uu/test/src/test.rs b/src/uu/test/src/test.rs index 5ce798bfa..653161631 100644 --- a/src/uu/test/src/test.rs +++ b/src/uu/test/src/test.rs @@ -13,7 +13,8 @@ mod parser; use clap::{crate_version, App, AppSettings}; use parser::{parse, Operator, Symbol, UnaryOperator}; use std::ffi::{OsStr, OsString}; -use uucore::{display::Quotable, show_error}; +use uucore::display::Quotable; +use uucore::error::{UResult, USimpleError}; const USAGE: &str = "test EXPRESSION or: test @@ -91,7 +92,8 @@ pub fn uu_app() -> App<'static, 'static> { .setting(AppSettings::DisableVersion) } -pub fn uumain(mut args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(mut args: impl uucore::Args) -> UResult<()> { let program = args.next().unwrap_or_else(|| OsString::from("test")); let binary_name = uucore::util_name(); let mut args: Vec<_> = args.collect(); @@ -109,13 +111,12 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 { .setting(AppSettings::NeedsLongHelp) .setting(AppSettings::NeedsLongVersion) .get_matches_from(std::iter::once(program).chain(args.into_iter())); - return 0; + return Ok(()); } // If invoked via name '[', matching ']' must be in the last arg let last = args.pop(); if last.as_deref() != Some(OsStr::new("]")) { - show_error!("missing ']'"); - return 2; + return Err(USimpleError::new(2, "missing ']'")); } } @@ -124,15 +125,12 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 { match result { Ok(result) => { if result { - 0 + Ok(()) } else { - 1 + Err(1.into()) } } - Err(e) => { - show_error!("{}", e); - 2 - } + Err(e) => Err(USimpleError::new(2, e)), } } From c075f105a4037a6ba6ca99f92c5ce17dcbd58d21 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 1 Jan 2022 18:31:47 +0100 Subject: [PATCH 06/16] remove unnecessary and unused macros --- src/uu/du/src/du.rs | 4 +- src/uu/join/src/join.rs | 2 +- src/uu/shred/src/shred.rs | 2 +- src/uu/split/src/split.rs | 2 +- src/uucore/src/lib/lib.rs | 1 - src/uucore/src/lib/macros.rs | 66 +------------ src/uucore/src/lib/mods.rs | 1 - src/uucore/src/lib/mods/coreopts.rs | 141 ---------------------------- 8 files changed, 8 insertions(+), 211 deletions(-) delete mode 100644 src/uucore/src/lib/mods/coreopts.rs diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 9fd44b001..6db088ea1 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -292,13 +292,13 @@ fn du( let read = match fs::read_dir(&my_stat.path) { Ok(read) => read, Err(e) => { - safe_writeln!( + writeln!( stderr(), "{}: cannot read directory {}: {}", options.util_name, my_stat.path.quote(), e - ); + ).unwrap(); return Box::new(iter::once(my_stat)); } }; diff --git a/src/uu/join/src/join.rs b/src/uu/join/src/join.rs index 03fe7dcd5..e396d4294 100644 --- a/src/uu/join/src/join.rs +++ b/src/uu/join/src/join.rs @@ -413,7 +413,7 @@ impl<'a> State<'a> { // This is fatal if the check is enabled. if input.check_order == CheckOrder::Enabled { - exit!(1); + std::process::exit(1); } self.has_failed = true; diff --git a/src/uu/shred/src/shred.rs b/src/uu/shred/src/shred.rs index 591dacf25..f745c3bf6 100644 --- a/src/uu/shred/src/shred.rs +++ b/src/uu/shred/src/shred.rs @@ -410,7 +410,7 @@ fn get_size(size_str_opt: Option) -> Option { util_name(), size_str_opt.unwrap().maybe_quote() ); - exit!(1); + std::process::exit(1); } }; diff --git a/src/uu/split/src/split.rs b/src/uu/split/src/split.rs index dfc116cb3..423a31892 100644 --- a/src/uu/split/src/split.rs +++ b/src/uu/split/src/split.rs @@ -91,7 +91,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { if cfg!(windows) { // see https://github.com/rust-lang/rust/issues/29494 show_error!("{} is currently not supported in this platform", OPT_FILTER); - exit!(-1); + std::process::exit(-1); } else { settings.filter = Some(matches.value_of(OPT_FILTER).unwrap().to_owned()); } diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 3d2d867bd..2f8ccce13 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -18,7 +18,6 @@ mod parser; // string parsing modules // * cross-platform modules pub use crate::mods::backup_control; -pub use crate::mods::coreopts; pub use crate::mods::display; pub use crate::mods::error; pub use crate::mods::os; diff --git a/src/uucore/src/lib/macros.rs b/src/uucore/src/lib/macros.rs index 275b0afe7..5c1e24d03 100644 --- a/src/uucore/src/lib/macros.rs +++ b/src/uucore/src/lib/macros.rs @@ -26,9 +26,7 @@ //! - From custom messages: [`show_error!`], [`show_usage_error!`] //! - Print warnings: [`show_warning!`] //! - Terminate util execution -//! - Terminate regularly: [`exit!`], [`return_if_err!`] -//! - Crash program: [`crash!`], [`crash_if_err!`], [`safe_unwrap!`] -//! - Unwrapping result types: [`safe_unwrap!`] +//! - Crash program: [`crash!`], [`crash_if_err!`] // spell-checker:ignore sourcepath targetpath @@ -223,22 +221,10 @@ macro_rules! show_usage_error( }) ); -//==== - -/// Calls [`std::process::exit`] with the provided exit code. -/// -/// Why not call exit directly? -#[macro_export] -macro_rules! exit( - ($exit_code:expr) => ({ - ::std::process::exit($exit_code) - }) -); - /// Display an error and [`exit!`] /// /// Displays the provided error message using [`show_error!`], then invokes -/// [`exit!`] with the provided exit code. +/// [`std::process::exit`] with the provided exit code. /// /// # Examples /// @@ -255,7 +241,7 @@ macro_rules! exit( macro_rules! crash( ($exit_code:expr, $($args:tt)+) => ({ $crate::show_error!($($args)+); - $crate::exit!($exit_code) + std::process::exit($exit_code); }) ); @@ -289,52 +275,6 @@ macro_rules! crash_if_err( ) ); -/// Unwrap some Result, crashing instead of panicking. -/// -/// Drop this in favor of `crash_if_err!` -#[macro_export] -macro_rules! safe_unwrap( - ($exp:expr) => ( - match $exp { - Ok(m) => m, - Err(f) => $crate::crash!(1, "{}", f.to_string()) - } - ) -); - -//==== - -/// Unwraps the Result. Instead of panicking, it shows the error and then -/// returns from the function with the provided exit code. -/// Assumes the current function returns an i32 value. -/// -/// Replace with `crash_if_err`? -#[macro_export] -macro_rules! return_if_err( - ($exit_code:expr, $exp:expr) => ( - match $exp { - Ok(m) => m, - Err(f) => { - $crate::show_error!("{}", f); - return $exit_code; - } - } - ) -); - -//==== - -/// This is used exclusively by du... -#[macro_export] -macro_rules! safe_writeln( - ($fd:expr, $($args:tt)+) => ( - match writeln!($fd, $($args)+) { - Ok(_) => {} - Err(f) => panic!("{}", f) - } - ) -); - //-- message templates //-- message templates : (join utility sub-macros) diff --git a/src/uucore/src/lib/mods.rs b/src/uucore/src/lib/mods.rs index 8f6d14976..bbde696dc 100644 --- a/src/uucore/src/lib/mods.rs +++ b/src/uucore/src/lib/mods.rs @@ -1,7 +1,6 @@ // mods ~ cross-platforms modules (core/bundler file) pub mod backup_control; -pub mod coreopts; pub mod display; pub mod error; pub mod os; diff --git a/src/uucore/src/lib/mods/coreopts.rs b/src/uucore/src/lib/mods/coreopts.rs deleted file mode 100644 index b534ff902..000000000 --- a/src/uucore/src/lib/mods/coreopts.rs +++ /dev/null @@ -1,141 +0,0 @@ -pub struct HelpText<'a> { - pub name: &'a str, - pub version: &'a str, - pub syntax: &'a str, - pub summary: &'a str, - pub long_help: &'a str, - pub display_usage: bool, -} - -pub struct CoreOptions<'a> { - options: getopts::Options, - help_text: HelpText<'a>, -} - -impl<'a> CoreOptions<'a> { - pub fn new(help_text: HelpText<'a>) -> Self { - let mut ret = CoreOptions { - options: getopts::Options::new(), - help_text, - }; - ret.options - .optflag("", "help", "print usage information") - .optflag("", "version", "print name and version number"); - ret - } - pub fn optflagopt( - &mut self, - short_name: &str, - long_name: &str, - desc: &str, - hint: &str, - ) -> &mut CoreOptions<'a> { - self.options.optflagopt(short_name, long_name, desc, hint); - self - } - pub fn optflag( - &mut self, - short_name: &str, - long_name: &str, - desc: &str, - ) -> &mut CoreOptions<'a> { - self.options.optflag(short_name, long_name, desc); - self - } - pub fn optflagmulti( - &mut self, - short_name: &str, - long_name: &str, - desc: &str, - ) -> &mut CoreOptions<'a> { - self.options.optflagmulti(short_name, long_name, desc); - self - } - pub fn optopt( - &mut self, - short_name: &str, - long_name: &str, - desc: &str, - hint: &str, - ) -> &mut CoreOptions<'a> { - self.options.optopt(short_name, long_name, desc, hint); - self - } - pub fn optmulti( - &mut self, - short_name: &str, - long_name: &str, - desc: &str, - hint: &str, - ) -> &mut CoreOptions<'a> { - self.options.optmulti(short_name, long_name, desc, hint); - self - } - pub fn usage(&self, summary: &str) -> String { - self.options.usage(summary) - } - pub fn parse(&mut self, args: Vec) -> getopts::Matches { - let matches = match self.options.parse(&args[1..]) { - Ok(m) => Some(m), - Err(f) => { - eprint!("{}: error: ", self.help_text.name); - eprintln!("{}", f); - ::std::process::exit(1); - } - } - .unwrap(); - if matches.opt_present("help") { - let usage_str = if self.help_text.display_usage { - format!( - "\n {}\n\n Reference\n", - self.options.usage(self.help_text.summary) - ) - .replace("Options:", " Options:") - } else { - String::new() - }; - print!( - " - {0} {1} - - {0} {2} -{3}{4} -", - self.help_text.name, - self.help_text.version, - self.help_text.syntax, - usage_str, - self.help_text.long_help - ); - crate::exit!(0); - } else if matches.opt_present("version") { - println!("{} {}", self.help_text.name, self.help_text.version); - crate::exit!(0); - } - matches - } -} - -#[macro_export] -macro_rules! app { - ($syntax: expr, $summary: expr, $long_help: expr) => { - uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText { - name: uucore::util_name(), - version: env!("CARGO_PKG_VERSION"), - syntax: $syntax, - summary: $summary, - long_help: $long_help, - display_usage: true, - }) - }; - ($syntax: expr, $summary: expr, $long_help: expr, $display_usage: expr) => { - uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText { - name: uucore::util_name(), - version: env!("CARGO_PKG_VERSION"), - syntax: $syntax, - summary: $summary, - long_help: $long_help, - display_usage: $display_usage, - }) - }; -} From 62341112df5f70f8ca3a487f6e9a361a3b6b38d2 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 1 Jan 2022 18:49:35 +0100 Subject: [PATCH 07/16] remove cut-specific macros --- src/uu/cut/src/cut.rs | 27 ++-------- src/uucore/src/lib/macros.rs | 101 ----------------------------------- 2 files changed, 5 insertions(+), 123 deletions(-) diff --git a/src/uu/cut/src/cut.rs b/src/uu/cut/src/cut.rs index 0b465dcdd..8dfdf25f8 100644 --- a/src/uu/cut/src/cut.rs +++ b/src/uu/cut/src/cut.rs @@ -466,12 +466,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { delim = "="; } if delim.chars().count() > 1 { - Err(msg_opt_invalid_should_be!( - "empty or 1 character long", - "a value 2 characters or longer", - "--delimiter", - "-d" - )) + Err("invalid input: The '--delimiter' ('-d') option expects empty or 1 character long, but was provided a value 2 characters or longer".into()) } else { let delim = if delim.is_empty() { "\0".to_owned() @@ -503,13 +498,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }) } (ref b, ref c, ref f) if b.is_some() || c.is_some() || f.is_some() => Err( - msg_expects_no_more_than_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)"), + "invalid usage: expects no more than one of --fields (-f), --chars (-c) or --bytes (-b)".into() ), - _ => Err(msg_expects_one_of!( - "--fields (-f)", - "--chars (-c)", - "--bytes (-b)" - )), + _ => Err("invalid usage: expects one of --fields (-f), --chars (-c) or --bytes (-b)".into()), }; let mode_parse = match mode_parse { @@ -518,20 +509,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.is_present(options::DELIMITER) => { - Err(msg_opt_only_usable_if!( - "printing a sequence of fields", - "--delimiter", - "-d" - )) + Err("invalid input: The '--delimiter' ('-d') option only usable if printing a sequence of fields".into()) } Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.is_present(options::ONLY_DELIMITED) => { - Err(msg_opt_only_usable_if!( - "printing a sequence of fields", - "--only-delimited", - "-s" - )) + Err("invalid input: The '--only-delimited' ('-s') option only usable if printing a sequence of fields".into()) } _ => Ok(mode), }, diff --git a/src/uucore/src/lib/macros.rs b/src/uucore/src/lib/macros.rs index 5c1e24d03..a3d5b299e 100644 --- a/src/uucore/src/lib/macros.rs +++ b/src/uucore/src/lib/macros.rs @@ -274,104 +274,3 @@ macro_rules! crash_if_err( } ) ); - -//-- message templates - -//-- message templates : (join utility sub-macros) - -// used only by "cut" -#[macro_export] -macro_rules! snippet_list_join_oxford_comma { - ($conjunction:expr, $valOne:expr, $valTwo:expr) => ( - format!("{}, {} {}", $valOne, $conjunction, $valTwo) - ); - ($conjunction:expr, $valOne:expr, $valTwo:expr $(, $remaining_values:expr)*) => ( - format!("{}, {}", $valOne, $crate::snippet_list_join_oxford_comma!($conjunction, $valTwo $(, $remaining_values)*)) - ); -} - -// used only by "cut" -#[macro_export] -macro_rules! snippet_list_join { - ($conjunction:expr, $valOne:expr, $valTwo:expr) => ( - format!("{} {} {}", $valOne, $conjunction, $valTwo) - ); - ($conjunction:expr, $valOne:expr, $valTwo:expr $(, $remaining_values:expr)*) => ( - format!("{}, {}", $valOne, $crate::snippet_list_join_oxford_comma!($conjunction, $valTwo $(, $remaining_values)*)) - ); -} - -//-- message templates : invalid input - -#[macro_export] -macro_rules! msg_invalid_input { - ($reason: expr) => { - format!("invalid input: {}", $reason) - }; -} - -// -- message templates : invalid input : flag - -#[macro_export] -macro_rules! msg_invalid_opt_use { - ($about:expr, $flag:expr) => { - $crate::msg_invalid_input!(format!("The '{}' option {}", $flag, $about)) - }; - ($about:expr, $long_flag:expr, $short_flag:expr) => { - $crate::msg_invalid_input!(format!( - "The '{}' ('{}') option {}", - $long_flag, $short_flag, $about - )) - }; -} - -// Only used by "cut" -#[macro_export] -macro_rules! msg_opt_only_usable_if { - ($clause:expr, $flag:expr) => { - $crate::msg_invalid_opt_use!(format!("only usable if {}", $clause), $flag) - }; - ($clause:expr, $long_flag:expr, $short_flag:expr) => { - $crate::msg_invalid_opt_use!( - format!("only usable if {}", $clause), - $long_flag, - $short_flag - ) - }; -} - -// Used only by "cut" -#[macro_export] -macro_rules! msg_opt_invalid_should_be { - ($expects:expr, $received:expr, $flag:expr) => { - $crate::msg_invalid_opt_use!( - format!("expects {}, but was provided {}", $expects, $received), - $flag - ) - }; - ($expects:expr, $received:expr, $long_flag:expr, $short_flag:expr) => { - $crate::msg_invalid_opt_use!( - format!("expects {}, but was provided {}", $expects, $received), - $long_flag, - $short_flag - ) - }; -} - -// -- message templates : invalid input : input combinations - -// UNUSED! -#[macro_export] -macro_rules! msg_expects_one_of { - ($valOne:expr $(, $remaining_values:expr)*) => ( - $crate::msg_invalid_input!(format!("expects one of {}", $crate::snippet_list_join!("or", $valOne $(, $remaining_values)*))) - ); -} - -// Used only by "cut" -#[macro_export] -macro_rules! msg_expects_no_more_than_one_of { - ($valOne:expr $(, $remaining_values:expr)*) => ( - $crate::msg_invalid_input!(format!("expects no more than one of {}", $crate::snippet_list_join!("or", $valOne $(, $remaining_values)*))) ; - ); -} From 7fa720d3114435ed2558366dd3c9a1feadb74128 Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 1 Jan 2022 19:43:44 +0100 Subject: [PATCH 08/16] fix lint, fmt & udeps errors --- Cargo.lock | 1 - src/uu/du/src/du.rs | 7 +++---- src/uucore/Cargo.toml | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6c23c9bc..de9fe11cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3238,7 +3238,6 @@ dependencies = [ "data-encoding-macro", "dns-lookup", "dunce", - "getopts", "lazy_static", "libc", "nix 0.23.1", diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 6db088ea1..58d01701f 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -18,7 +18,7 @@ use std::env; use std::fs; #[cfg(not(windows))] use std::fs::Metadata; -use std::io::{stderr, ErrorKind, Result, Write}; +use std::io::{ErrorKind, Result}; use std::iter; #[cfg(not(windows))] use std::os::unix::fs::MetadataExt; @@ -292,13 +292,12 @@ fn du( let read = match fs::read_dir(&my_stat.path) { Ok(read) => read, Err(e) => { - writeln!( - stderr(), + eprintln!( "{}: cannot read directory {}: {}", options.util_name, my_stat.path.quote(), e - ).unwrap(); + ); return Box::new(iter::once(my_stat)); } }; diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index a97f82133..99e1061ec 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -19,7 +19,6 @@ path="src/lib/lib.rs" clap = "2.33.3" dns-lookup = { version="1.0.5", optional=true } dunce = "1.0.0" -getopts = "<= 0.2.21" wild = "2.0" # * optional thiserror = { version="1.0", optional=true } From af5919e466f41e28ae7090c499d3b996c025e12e Mon Sep 17 00:00:00 2001 From: Sebastian Holgersson Date: Sat, 1 Jan 2022 21:44:11 +0100 Subject: [PATCH 09/16] numfmt: implement missing --suffix option adds support for the --suffix option from issue #1280. --- src/uu/numfmt/src/format.rs | 26 ++++++++++++--- src/uu/numfmt/src/numfmt.rs | 12 +++++++ src/uu/numfmt/src/options.rs | 2 ++ tests/by-util/test_numfmt.rs | 64 ++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/uu/numfmt/src/format.rs b/src/uu/numfmt/src/format.rs index aa90f7936..42f7d45bf 100644 --- a/src/uu/numfmt/src/format.rs +++ b/src/uu/numfmt/src/format.rs @@ -220,16 +220,34 @@ fn format_string( options: &NumfmtOptions, implicit_padding: Option, ) -> Result { + // strip the (optional) suffix before applying any transformation + let source_without_suffix = if let Some(suffix) = &options.suffix { + source.strip_suffix(suffix).unwrap_or(source) + } else { + source + }; + let number = transform_to( - transform_from(source, &options.transform.from)?, + transform_from(source_without_suffix, &options.transform.from)?, &options.transform.to, options.round, )?; + // bring back the suffix before applying padding + let number_with_suffix = if let Some(suffix) = &options.suffix { + format!("{}{}", number, suffix) + } else { + number + }; + Ok(match implicit_padding.unwrap_or(options.padding) { - 0 => number, - p if p > 0 => format!("{:>padding$}", number, padding = p as usize), - p => format!("{: number_with_suffix, + p if p > 0 => format!("{:>padding$}", number_with_suffix, padding = p as usize), + p => format!( + "{: Result { _ => unreachable!("Should be restricted by clap"), }; + let suffix = args.value_of(options::SUFFIX).map(|s| s.to_owned()); + Ok(NumfmtOptions { transform, padding, @@ -149,6 +151,7 @@ fn parse_options(args: &ArgMatches) -> Result { fields, delimiter, round, + suffix, }) } @@ -242,5 +245,14 @@ pub fn uu_app() -> App<'static, 'static> { .default_value("from-zero") .possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]), ) + .arg( + Arg::with_name(options::SUFFIX) + .long(options::SUFFIX) + .help( + "print SUFFIX after each formatted number, and accept \ + inputs optionally ending with SUFFIX", + ) + .value_name("SUFFIX"), + ) .arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true)) } diff --git a/src/uu/numfmt/src/options.rs b/src/uu/numfmt/src/options.rs index 59bf9d8d3..bd76b18b8 100644 --- a/src/uu/numfmt/src/options.rs +++ b/src/uu/numfmt/src/options.rs @@ -11,6 +11,7 @@ pub const HEADER_DEFAULT: &str = "1"; pub const NUMBER: &str = "NUMBER"; pub const PADDING: &str = "padding"; pub const ROUND: &str = "round"; +pub const SUFFIX: &str = "suffix"; pub const TO: &str = "to"; pub const TO_DEFAULT: &str = "none"; @@ -26,6 +27,7 @@ pub struct NumfmtOptions { pub fields: Vec, pub delimiter: Option, pub round: RoundMethod, + pub suffix: Option, } #[derive(Clone, Copy)] diff --git a/tests/by-util/test_numfmt.rs b/tests/by-util/test_numfmt.rs index 336b0f7cd..9043eb541 100644 --- a/tests/by-util/test_numfmt.rs +++ b/tests/by-util/test_numfmt.rs @@ -505,3 +505,67 @@ fn test_round() { .stdout_only(exp.join("\n") + "\n"); } } + +#[test] +fn test_suffix_is_added_if_not_supplied() { + new_ucmd!() + .args(&["--suffix=TEST"]) + .pipe_in("1000") + .succeeds() + .stdout_only("1000TEST\n"); +} + +#[test] +fn test_suffix_is_preserved() { + new_ucmd!() + .args(&["--suffix=TEST"]) + .pipe_in("1000TEST") + .succeeds() + .stdout_only("1000TEST\n"); +} + +#[test] +fn test_suffix_is_only_applied_to_selected_field() { + new_ucmd!() + .args(&["--suffix=TEST", "--field=2"]) + .pipe_in("1000 2000 3000") + .succeeds() + .stdout_only("1000 2000TEST 3000\n"); +} + +#[test] +fn test_transform_with_suffix_on_input() { + new_ucmd!() + .args(&["--suffix=TEST", "--to=si"]) + .pipe_in("2000TEST") + .succeeds() + .stdout_only("2.0KTEST\n"); +} + +#[test] +fn test_transform_without_suffix_on_input() { + new_ucmd!() + .args(&["--suffix=TEST", "--to=si"]) + .pipe_in("2000") + .succeeds() + .stdout_only("2.0KTEST\n"); +} + +#[test] +fn test_transform_with_suffix_and_delimiter() { + new_ucmd!() + .args(&["--suffix=mysuffix", "--to=si", "-d=|"]) + .pipe_in("1000mysuffix|2000|3000") + .succeeds() + .stdout_only("1.0Kmysuffix|2000|3000\n"); +} + +#[test] +fn test_suffix_with_padding() { + new_ucmd!() + .args(&["--suffix=padme", "--padding=12"]) + .pipe_in("1000 2000 3000") + .succeeds() + .stdout_only(" 1000padme 2000 3000\n"); +} + From 84798a520ea9c92519b81ff971734bea7e6c12f2 Mon Sep 17 00:00:00 2001 From: Sebastian Holgersson Date: Sat, 1 Jan 2022 22:55:50 +0100 Subject: [PATCH 10/16] numfmt: fix spelling and formatting issues in tests --- tests/by-util/test_numfmt.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/by-util/test_numfmt.rs b/tests/by-util/test_numfmt.rs index 9043eb541..596aab6ba 100644 --- a/tests/by-util/test_numfmt.rs +++ b/tests/by-util/test_numfmt.rs @@ -536,36 +536,35 @@ fn test_suffix_is_only_applied_to_selected_field() { #[test] fn test_transform_with_suffix_on_input() { new_ucmd!() - .args(&["--suffix=TEST", "--to=si"]) - .pipe_in("2000TEST") + .args(&["--suffix=b", "--to=si"]) + .pipe_in("2000b") .succeeds() - .stdout_only("2.0KTEST\n"); + .stdout_only("2.0Kb\n"); } #[test] fn test_transform_without_suffix_on_input() { new_ucmd!() - .args(&["--suffix=TEST", "--to=si"]) + .args(&["--suffix=b", "--to=si"]) .pipe_in("2000") .succeeds() - .stdout_only("2.0KTEST\n"); + .stdout_only("2.0Kb\n"); } #[test] fn test_transform_with_suffix_and_delimiter() { new_ucmd!() - .args(&["--suffix=mysuffix", "--to=si", "-d=|"]) - .pipe_in("1000mysuffix|2000|3000") + .args(&["--suffix=b", "--to=si", "-d=|"]) + .pipe_in("1000b|2000|3000") .succeeds() - .stdout_only("1.0Kmysuffix|2000|3000\n"); + .stdout_only("1.0Kb|2000|3000\n"); } #[test] fn test_suffix_with_padding() { new_ucmd!() - .args(&["--suffix=padme", "--padding=12"]) + .args(&["--suffix=pad", "--padding=12"]) .pipe_in("1000 2000 3000") .succeeds() - .stdout_only(" 1000padme 2000 3000\n"); + .stdout_only(" 1000pad 2000 3000\n"); } - From cd79bc49bc094335238cb4aa0442e1cf3e80c175 Mon Sep 17 00:00:00 2001 From: Roy Ivy III Date: Sat, 1 Jan 2022 17:50:11 -0600 Subject: [PATCH 11/16] maint/CICD ~ ignore 'vendor' for CodeCov --- .github/workflows/CICD.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index e4d74a690..215232a87 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -844,13 +844,13 @@ jobs: ## Generate coverage data COVERAGE_REPORT_DIR="target/debug" COVERAGE_REPORT_FILE="${COVERAGE_REPORT_DIR}/lcov.info" - # GRCOV_IGNORE_OPTION='--ignore build.rs --ignore "/*" --ignore "[a-zA-Z]:/*"' ## `grcov` ignores these params when passed as an environment variable (why?) + # GRCOV_IGNORE_OPTION='--ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*"' ## `grcov` ignores these params when passed as an environment variable (why?) # GRCOV_EXCLUDE_OPTION='--excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()"' ## `grcov` ignores these params when passed as an environment variable (why?) mkdir -p "${COVERAGE_REPORT_DIR}" # display coverage files - grcov . --output-type files --ignore build.rs --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" | sort --unique + grcov . --output-type files --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" | sort --unique # generate coverage report - grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" + grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" echo ::set-output name=report::${COVERAGE_REPORT_FILE} - name: Upload coverage results (to Codecov.io) uses: codecov/codecov-action@v1 From a3895bba595149922bd7aaef9783f0f7bd9d9513 Mon Sep 17 00:00:00 2001 From: Sebastian Holgersson Date: Sun, 2 Jan 2022 02:16:59 +0100 Subject: [PATCH 12/16] numfmt: replace if let with simpler match --- src/uu/numfmt/src/format.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/uu/numfmt/src/format.rs b/src/uu/numfmt/src/format.rs index 42f7d45bf..f66e1ac0a 100644 --- a/src/uu/numfmt/src/format.rs +++ b/src/uu/numfmt/src/format.rs @@ -221,10 +221,9 @@ fn format_string( implicit_padding: Option, ) -> Result { // strip the (optional) suffix before applying any transformation - let source_without_suffix = if let Some(suffix) = &options.suffix { - source.strip_suffix(suffix).unwrap_or(source) - } else { - source + let source_without_suffix = match &options.suffix { + Some(suffix) => source.strip_suffix(suffix).unwrap_or(source), + None => source, }; let number = transform_to( @@ -234,10 +233,9 @@ fn format_string( )?; // bring back the suffix before applying padding - let number_with_suffix = if let Some(suffix) = &options.suffix { - format!("{}{}", number, suffix) - } else { - number + let number_with_suffix = match &options.suffix { + Some(suffix) => format!("{}{}", number, suffix), + None => number, }; Ok(match implicit_padding.unwrap_or(options.padding) { From ebd5e965e95ac544a146a728b43b494edecd2ebe Mon Sep 17 00:00:00 2001 From: Terts Diepraam Date: Sat, 1 Jan 2022 20:44:02 +0100 Subject: [PATCH 13/16] stdbuf: fix cargo --git build (#1276) --- src/uu/stdbuf/build.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/uu/stdbuf/build.rs b/src/uu/stdbuf/build.rs index b14d503cf..b03bce849 100644 --- a/src/uu/stdbuf/build.rs +++ b/src/uu/stdbuf/build.rs @@ -20,17 +20,23 @@ mod platform { } fn main() { - let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("Could not find manifest dir"); - let profile = env::var("PROFILE").expect("Could not determine profile"); - let out_dir = env::var("OUT_DIR").unwrap(); - let libstdbuf = format!( - "{}/../../../{}/{}/deps/liblibstdbuf{}", - manifest_dir, - env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| "target".to_string()), - profile, - platform::DYLIB_EXT - ); + let mut target_dir = Path::new(&out_dir); + + // Depending on how this is util is built, the directory structure. This seems to work for now. + // Here are three cases to test when changing this: + // - cargo run + // - cross run + // - cargo install --git + let mut name = target_dir.file_name().unwrap().to_string_lossy(); + while name != "target" && !name.starts_with("cargo-install") { + target_dir = target_dir.parent().unwrap(); + name = target_dir.file_name().unwrap().to_string_lossy(); + } + let mut libstdbuf = target_dir.to_path_buf(); + libstdbuf.push(env::var("PROFILE").unwrap()); + libstdbuf.push("deps"); + libstdbuf.push(format!("liblibstdbuf{}", platform::DYLIB_EXT)); fs::copy(libstdbuf, Path::new(&out_dir).join("libstdbuf.so")).unwrap(); } From b7e646e710d1409e050b905f14ce5b8b826702c7 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 2 Jan 2022 10:28:53 -0500 Subject: [PATCH 14/16] tty: return UResult from uumain() function --- src/uu/tty/src/tty.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/uu/tty/src/tty.rs b/src/uu/tty/src/tty.rs index 94e2e6b24..3a02803c0 100644 --- a/src/uu/tty/src/tty.rs +++ b/src/uu/tty/src/tty.rs @@ -12,6 +12,7 @@ use clap::{crate_version, App, Arg}; use std::ffi::CStr; use std::io::Write; +use uucore::error::{UResult, UUsageError}; use uucore::InvalidEncodingHandling; static ABOUT: &str = "Print the file name of the terminal connected to standard input."; @@ -24,21 +25,17 @@ fn usage() -> String { format!("{0} [OPTION]...", uucore::execution_phrase()) } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = usage(); let args = args .collect_str(InvalidEncodingHandling::ConvertLossy) .accept_any(); - let matches = uu_app().usage(&usage[..]).get_matches_from_safe(args); - - let matches = match matches { - Ok(m) => m, - Err(e) => { - eprint!("{}", e); - return 2; - } - }; + let matches = uu_app() + .usage(&usage[..]) + .get_matches_from_safe(args) + .map_err(|e| UUsageError::new(2, format!("{}", e)))?; let silent = matches.is_present(options::SILENT); @@ -68,9 +65,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 { } if atty::is(atty::Stream::Stdin) { - libc::EXIT_SUCCESS + Ok(()) } else { - libc::EXIT_FAILURE + Err(libc::EXIT_FAILURE.into()) } } From f89dc6585d859754ff25ec5c9f3bd61d0caab7d3 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 2 Jan 2022 10:33:41 -0500 Subject: [PATCH 15/16] unexpand: return UResult from uumain() function --- src/uu/unexpand/src/unexpand.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/uu/unexpand/src/unexpand.rs b/src/uu/unexpand/src/unexpand.rs index 95383b89d..1b227e4ce 100644 --- a/src/uu/unexpand/src/unexpand.rs +++ b/src/uu/unexpand/src/unexpand.rs @@ -17,6 +17,7 @@ use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Stdout, Write} use std::str::from_utf8; use unicode_width::UnicodeWidthChar; use uucore::display::Quotable; +use uucore::error::{FromIo, UResult}; use uucore::InvalidEncodingHandling; static NAME: &str = "unexpand"; @@ -90,16 +91,15 @@ impl Options { } } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let args = args .collect_str(InvalidEncodingHandling::Ignore) .accept_any(); let matches = uu_app().get_matches_from(args); - unexpand(Options::new(matches)); - - 0 + unexpand(Options::new(matches)).map_err_context(String::new) } pub fn uu_app() -> App<'static, 'static> { @@ -242,7 +242,7 @@ fn next_char_info(uflag: bool, buf: &[u8], byte: usize) -> (CharType, usize, usi (ctype, cwidth, nbytes) } -fn unexpand(options: Options) { +fn unexpand(options: Options) -> std::io::Result<()> { let mut output = BufWriter::new(stdout()); let ts = &options.tabstops[..]; let mut buf = Vec::new(); @@ -273,7 +273,7 @@ fn unexpand(options: Options) { init, true, ); - crash_if_err!(1, output.write_all(&buf[byte..])); + output.write_all(&buf[byte..])?; scol = col; break; } @@ -293,7 +293,7 @@ fn unexpand(options: Options) { }; if !tabs_buffered { - crash_if_err!(1, output.write_all(&buf[byte..byte + nbytes])); + output.write_all(&buf[byte..byte + nbytes])?; scol = col; // now printed up to this column } } @@ -318,7 +318,7 @@ fn unexpand(options: Options) { } else { 0 }; - crash_if_err!(1, output.write_all(&buf[byte..byte + nbytes])); + output.write_all(&buf[byte..byte + nbytes])?; scol = col; // we've now printed up to this column } } @@ -337,9 +337,9 @@ fn unexpand(options: Options) { init, true, ); - crash_if_err!(1, output.flush()); + output.flush()?; buf.truncate(0); // clear out the buffer } } - crash_if_err!(1, output.flush()) + output.flush() } From b30a20d89507645395f9d37168b79942f5bf7709 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sun, 2 Jan 2022 20:07:12 -0500 Subject: [PATCH 16/16] chcon: return UResult from uumain() function --- src/uu/chcon/src/chcon.rs | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/uu/chcon/src/chcon.rs b/src/uu/chcon/src/chcon.rs index e47312045..32fa23ef8 100644 --- a/src/uu/chcon/src/chcon.rs +++ b/src/uu/chcon/src/chcon.rs @@ -2,7 +2,8 @@ #![allow(clippy::upper_case_acronyms)] -use uucore::{display::Quotable, show_error, show_usage_error, show_warning}; +use uucore::error::{UResult, USimpleError, UUsageError}; +use uucore::{display::Quotable, show_error, show_warning}; use clap::{App, Arg}; use selinux::{OpaqueSecurityContext, SecurityContext}; @@ -60,7 +61,8 @@ fn get_usage() -> String { ) } -pub fn uumain(args: impl uucore::Args) -> i32 { +#[uucore_procs::gen_uumain] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { let usage = get_usage(); let config = uu_app().usage(usage.as_ref()); @@ -72,14 +74,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 { match r.kind { clap::ErrorKind::HelpDisplayed | clap::ErrorKind::VersionDisplayed => { println!("{}", r); - return libc::EXIT_SUCCESS; + return Ok(()); } _ => {} } } - show_usage_error!("{}.\n", r); - return libc::EXIT_FAILURE; + return Err(UUsageError::new(libc::EXIT_FAILURE, format!("{}.\n", r))); } }; @@ -98,8 +99,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { match result { Err(r) => { - show_error!("{}.", report_full_error(&r)); - return libc::EXIT_FAILURE; + return Err(USimpleError::new( + libc::EXIT_FAILURE, + format!("{}.", report_full_error(&r)), + )); } Ok(file_context) => SELinuxSecurityContext::File(file_context), @@ -111,14 +114,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Ok(context) => context, Err(_r) => { - show_error!("Invalid security context {}.", context.quote()); - return libc::EXIT_FAILURE; + return Err(USimpleError::new( + libc::EXIT_FAILURE, + format!("Invalid security context {}.", context.quote()), + )); } }; if SecurityContext::from_c_str(&c_context, false).check() == Some(false) { - show_error!("Invalid security context {}.", context.quote()); - return libc::EXIT_FAILURE; + return Err(USimpleError::new( + libc::EXIT_FAILURE, + format!("Invalid security context {}.", context.quote()), + )); } SELinuxSecurityContext::String(Some(c_context)) @@ -132,8 +139,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Ok(r) => Some(r), Err(r) => { - show_error!("{}.", report_full_error(&r)); - return libc::EXIT_FAILURE; + return Err(USimpleError::new( + libc::EXIT_FAILURE, + format!("{}.", report_full_error(&r)), + )); } } } else { @@ -142,13 +151,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let results = process_files(&options, &context, root_dev_ino); if results.is_empty() { - return libc::EXIT_SUCCESS; + return Ok(()); } for result in &results { show_error!("{}.", report_full_error(result)); } - libc::EXIT_FAILURE + Err(libc::EXIT_FAILURE.into()) } pub fn uu_app() -> App<'static, 'static> {