diff --git a/src/uu/head/src/head.rs b/src/uu/head/src/head.rs index d67cc5b07..80f816d0f 100644 --- a/src/uu/head/src/head.rs +++ b/src/uu/head/src/head.rs @@ -76,7 +76,7 @@ fn app<'a>() -> App<'a, 'a> { .arg( Arg::with_name(options::QUIET_NAME) .short("q") - .long("--quiet") + .long("quiet") .visible_alias("silent") .help("never print headers giving file names") .overrides_with_all(&[options::VERBOSE_NAME, options::QUIET_NAME]), diff --git a/src/uu/head/src/parse.rs b/src/uu/head/src/parse.rs index 50cdfc439..6631dba0e 100644 --- a/src/uu/head/src/parse.rs +++ b/src/uu/head/src/parse.rs @@ -108,10 +108,7 @@ pub fn parse_num(src: &str) -> Result<(usize, bool), ParseSizeError> { return Err(ParseSizeError::ParseFailure(src.to_string())); } - match parse_size(&size_string) { - Ok(n) => Ok((n, all_but_last)), - Err(e) => Err(e), - } + parse_size(&size_string).map(|n| (n, all_but_last)) } #[cfg(test)] diff --git a/src/uu/split/src/split.rs b/src/uu/split/src/split.rs index 1fe35795e..ca9c68c74 100644 --- a/src/uu/split/src/split.rs +++ b/src/uu/split/src/split.rs @@ -19,7 +19,7 @@ use std::fs::File; use std::io::{stdin, BufRead, BufReader, BufWriter, Read, Write}; use std::path::Path; use std::{char, fs::remove_file}; -use uucore::parse_size::{parse_size, ParseSizeError}; +use uucore::parse_size::parse_size; static NAME: &str = "split"; static VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -281,16 +281,7 @@ impl ByteSplitter { let size_string = &settings.strategy_param; let size_num = match parse_size(&size_string) { Ok(n) => n, - Err(e) => match e { - ParseSizeError::ParseFailure(_) => { - crash!(1, "invalid number of bytes: {}", e.to_string()) - } - ParseSizeError::SizeTooBig(_) => crash!( - 1, - "invalid number of bytes: ‘{}’: Value too large for defined data type", - size_string - ), - }, + Err(e) => crash!(1, "invalid number of bytes: {}", e.to_string()), }; ByteSplitter { diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index acaad8c30..76c799621 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -33,7 +33,6 @@ use uucore::ringbuffer::RingBuffer; pub mod options { pub mod verbosity { pub static QUIET: &str = "quiet"; - pub static SILENT: &str = "silent"; pub static VERBOSE: &str = "verbose"; } pub static BYTES: &str = "bytes"; @@ -77,6 +76,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let app = App::new(executable!()) .version(crate_version!()) .about("output the last part of files") + // TODO: add usage .arg( Arg::with_name(options::BYTES) .short("c") @@ -111,13 +111,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Arg::with_name(options::verbosity::QUIET) .short("q") .long(options::verbosity::QUIET) + .visible_alias("silent") + .overrides_with_all(&[options::verbosity::QUIET, options::verbosity::VERBOSE]) .help("never output headers giving file names"), ) - .arg( - Arg::with_name(options::verbosity::SILENT) - .long(options::verbosity::SILENT) - .help("synonym of --quiet"), - ) .arg( Arg::with_name(options::SLEEP_INT) .short("s") @@ -129,6 +126,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { Arg::with_name(options::verbosity::VERBOSE) .short("v") .long(options::verbosity::VERBOSE) + .overrides_with_all(&[options::verbosity::QUIET, options::verbosity::VERBOSE]) .help("always output headers giving file names"), ) .arg( @@ -195,8 +193,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { } let verbose = matches.is_present(options::verbosity::VERBOSE); - let quiet = matches.is_present(options::verbosity::QUIET) - || matches.is_present(options::verbosity::SILENT); + let quiet = matches.is_present(options::verbosity::QUIET); let files: Vec = matches .values_of(options::ARG_FILES) @@ -423,8 +420,5 @@ fn parse_num(src: &str) -> Result<(usize, bool), ParseSizeError> { return Err(ParseSizeError::ParseFailure(src.to_string())); } - match parse_size(&size_string) { - Ok(n) => Ok((n, starting_with)), - Err(e) => Err(e), - } + parse_size(&size_string).map(|n| (n, starting_with)) } diff --git a/src/uucore/src/lib/parser/parse_size.rs b/src/uucore/src/lib/parser/parse_size.rs index 4a31d753a..c7825d4e3 100644 --- a/src/uucore/src/lib/parser/parse_size.rs +++ b/src/uucore/src/lib/parser/parse_size.rs @@ -75,10 +75,9 @@ pub fn parse_size(size: &str) -> Result { Ok(n) => n, Err(_) => return Err(ParseSizeError::size_too_big(size)), }; - match number.checked_mul(factor) { - Some(n) => Ok(n), - None => Err(ParseSizeError::size_too_big(size)), - } + number + .checked_mul(factor) + .ok_or(ParseSizeError::size_too_big(size)) } #[derive(Debug, PartialEq, Eq)] @@ -108,22 +107,58 @@ impl fmt::Display for ParseSizeError { impl ParseSizeError { fn parse_failure(s: &str) -> ParseSizeError { - // has to be handled in the respective uutils because strings differ, e.g. - // truncate: Invalid number: ‘fb’ - // tail: invalid number of bytes: ‘fb’ + // stderr on linux (GNU coreutils 8.32) + // has to be handled in the respective uutils because strings differ, e.g.: + // + // `NUM` + // head: invalid number of bytes: ‘1fb’ + // tail: invalid number of bytes: ‘1fb’ + // + // `SIZE` + // split: invalid number of bytes: ‘1fb’ + // truncate: Invalid number: ‘1fb’ + // + // `MODE` + // stdbuf: invalid mode ‘1fb’ + // + // `SIZE` + // sort: invalid suffix in --buffer-size argument '1fb' + // sort: invalid --buffer-size argument 'fb' + // + // `SIZE` + // du: invalid suffix in --buffer-size argument '1fb' + // du: invalid suffix in --threshold argument '1fb' + // du: invalid --buffer-size argument 'fb' + // du: invalid --threshold argument 'fb' + // + // `BYTES` + // od: invalid suffix in --read-bytes argument '1fb' + // od: invalid --read-bytes argument argument 'fb' + // --skip-bytes + // --width + // --strings + // etc. ParseSizeError::ParseFailure(format!("‘{}’", s)) } fn size_too_big(s: &str) -> ParseSizeError { - // has to be handled in the respective uutils because strings differ, e.g. - // truncate: Invalid number: ‘1Y’: Value too large to be stored in data type - // tail: invalid number of bytes: ‘1Y’: Value too large to be stored in data type + // stderr on linux (GNU coreutils 8.32) + // has to be handled in the respective uutils because strings differ, e.g.: + // + // head: invalid number of bytes: ‘1Y’: Value too large for defined data type + // tail: invalid number of bytes: ‘1Y’: Value too large for defined data type // split: invalid number of bytes: ‘1Y’: Value too large for defined data type + // truncate: Invalid number: ‘1Y’: Value too large for defined data type + // stdbuf: invalid mode ‘1Y’: Value too large for defined data type + // sort: -S argument '1Y' too large + // du: -B argument '1Y' too large + // od: -N argument '1Y' too large // etc. - ParseSizeError::SizeTooBig(format!( - "‘{}’: Value too large to be stored in data type", - s - )) + // + // stderr on macos (brew - GNU coreutils 8.32) also differs for the same version, e.g.: + // ghead: invalid number of bytes: ‘1Y’: Value too large to be stored in data type + // gtail: invalid number of bytes: ‘1Y’: Value too large to be stored in data type + ParseSizeError::SizeTooBig(format!("‘{}’: Value too large for defined data type", s)) } } diff --git a/tests/by-util/test_head.rs b/tests/by-util/test_head.rs index 99e6518fa..6a2cdf1cd 100755 --- a/tests/by-util/test_head.rs +++ b/tests/by-util/test_head.rs @@ -244,6 +244,7 @@ hello ", ); } + #[test] fn test_head_invalid_num() { new_ucmd!() @@ -258,16 +259,26 @@ fn test_head_invalid_num() { new_ucmd!() .args(&["-c", "1Y", "emptyfile.txt"]) .fails() - .stderr_is( - "head: invalid number of bytes: ‘1Y’: Value too large to be stored in data type", - ); + .stderr_is("head: invalid number of bytes: ‘1Y’: Value too large for defined data type"); #[cfg(not(target_pointer_width = "128"))] new_ucmd!() .args(&["-n", "1Y", "emptyfile.txt"]) .fails() - .stderr_is( - "head: invalid number of lines: ‘1Y’: Value too large to be stored in data type", - ); + .stderr_is("head: invalid number of lines: ‘1Y’: Value too large for defined data type"); + #[cfg(target_pointer_width = "32")] + { + let sizes = ["1000G", "10T"]; + for size in &sizes { + new_ucmd!() + .args(&["-c", size]) + .fails() + .code_is(1) + .stderr_only(format!( + "head: invalid number of bytes: ‘{}’: Value too large for defined data type", + size + )); + } + } } #[test] diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 43e4aaa0c..c296e2763 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -284,12 +284,11 @@ fn test_multiple_input_files_with_suppressed_headers() { #[test] fn test_multiple_input_quiet_flag_overrides_verbose_flag_for_suppressing_headers() { - // TODO: actually the later one should win, i.e. -qv should lead to headers being printed, -vq to them being suppressed new_ucmd!() .arg(FOOBAR_TXT) .arg(FOOBAR_2_TXT) - .arg("-q") .arg("-v") + .arg("-q") .run() .stdout_is_fixture("foobar_multiple_quiet.expected"); } @@ -367,16 +366,26 @@ fn test_tail_invalid_num() { new_ucmd!() .args(&["-c", "1Y", "emptyfile.txt"]) .fails() - .stderr_is( - "tail: invalid number of bytes: ‘1Y’: Value too large to be stored in data type", - ); + .stderr_is("tail: invalid number of bytes: ‘1Y’: Value too large for defined data type"); #[cfg(not(target_pointer_width = "128"))] new_ucmd!() .args(&["-n", "1Y", "emptyfile.txt"]) .fails() - .stderr_is( - "tail: invalid number of lines: ‘1Y’: Value too large to be stored in data type", - ); + .stderr_is("tail: invalid number of lines: ‘1Y’: Value too large for defined data type"); + #[cfg(target_pointer_width = "32")] + { + let sizes = ["1000G", "10T"]; + for size in &sizes { + new_ucmd!() + .args(&["-c", size]) + .fails() + .code_is(1) + .stderr_only(format!( + "tail: invalid number of bytes: ‘{}’: Value too large for defined data type", + size + )); + } + } } #[test]