diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 34a5bd6118..4fcd1b9264 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -2382,21 +2382,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { settings.line_ending = LineEnding::from_zero_flag(matches.get_flag(options::ZERO_TERMINATED)); settings.merge = matches.get_flag(options::MERGE); - settings.check = matches.contains_id(options::check::CHECK); - if settings.check && matches.get_flag(options::check::CHECK_SILENT) { + let check_modes: Vec<&str> = matches + .get_many::(options::check::CHECK) + .map(|modes| modes.map(String::as_str).collect()) + .unwrap_or_default(); + let check_silent = matches.get_flag(options::check::CHECK_SILENT) + || check_modes + .iter() + .any(|m| matches!(*m, options::check::SILENT | options::check::QUIET)); + let check_diagnose = check_modes.contains(&options::check::DIAGNOSE_FIRST); + if check_silent && check_diagnose { return Err(incompatible_options_error("cC")); } - if matches.get_flag(options::check::CHECK_SILENT) - || matches!( - matches - .get_one::(options::check::CHECK) - .map(String::as_str), - Some(options::check::SILENT | options::check::QUIET) - ) - { - settings.check_silent = true; - settings.check = true; - } + settings.check = check_silent || check_diagnose; + settings.check_silent = check_silent; if matches.contains_id(options::OUTPUT) && settings.check { let opts = if settings.check_silent { "Co" } else { "co" }; @@ -2605,6 +2604,8 @@ pub fn uu_app() -> Command { .long(options::check::CHECK) .require_equals(true) .num_args(0..) + .default_missing_value(options::check::DIAGNOSE_FIRST) + .action(ArgAction::Append) .value_parser(ShortcutValueParser::new([ options::check::SILENT, options::check::QUIET, diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index c309ad5b29..76e1fe0c3c 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -1579,6 +1579,40 @@ fn test_check_silent() { } } +#[test] +fn test_check_repeated_modes() { + for args in [ + ["--check=silent", "--check=diagnose-first"], + ["-c=silent", "-c=diagnose-first"], + ["--check=diagnose-first", "--check=quiet"], + ["-c", "--check=quiet"], + ["--check=silent", "-c"], + ] { + new_ucmd!() + .args(&args) + .arg("check_fail.txt") + .fails_with_code(2) + .stderr_only("sort: options '-cC' are incompatible\n"); + } + + for args in [ + ["--check=quiet", "-C"], + ["-C", "--check=silent"], + ["--check=quiet", "--check=silent"], + ] { + new_ucmd!() + .args(&args) + .arg("check_fail.txt") + .fails_with_code(1) + .no_output(); + } + + new_ucmd!() + .args(&["--check=diagnose-first", "-c", "check_fail.txt"]) + .fails_with_code(1) + .stderr_only("sort: check_fail.txt:6: disorder: 5\n"); +} + #[test] fn test_check_stops_early_without_panicking() { // `--check` returns as soon as it finds the first disorder. That used to drop the