diff --git a/src/lib.rs b/src/lib.rs index d4ce110..daf7023 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,6 +140,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .map_or(Default::default(), |v| v.collect()); let extended_regexp = matches.get_flag("extended_regexp"); let fixed_strings = matches.get_flag("fixed_strings"); + let basic_regexp = matches.get_flag("basic_regexp"); let perl_regexp = matches.get_flag("perl_regexp"); let regexp = matches.get_many::("regexp").unwrap_or_default(); let file_pattern = matches @@ -197,6 +198,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { #[cfg(windows)] let binary = matches.get_flag("binary"); + let matcher_mode_count = [extended_regexp, fixed_strings, basic_regexp, perl_regexp] + .into_iter() + .filter(|matched| *matched) + .count(); + if matcher_mode_count > 1 { + return Err(USimpleError::new( + 2, + "conflicting matchers specified".to_string(), + )); + } + // With -e/-f given, ALL positionals are files. let has_explicit_patterns = regexp.len() != 0 || file_pattern.len() != 0; let (positional_pattern, file_args) = if has_explicit_patterns { @@ -461,32 +473,28 @@ pub fn uu_app() -> Command { .short('E') .long("extended-regexp") .help("PATTERNS are extended regular expressions") - .action(ArgAction::SetTrue) - .overrides_with_all(["basic_regexp", "fixed_strings", "perl_regexp"]), + .action(ArgAction::SetTrue), ) .arg( Arg::new("fixed_strings") .short('F') .long("fixed-strings") .help("PATTERNS are strings") - .action(ArgAction::SetTrue) - .overrides_with_all(["basic_regexp", "extended_regexp", "perl_regexp"]), + .action(ArgAction::SetTrue), ) .arg( Arg::new("basic_regexp") .short('G') .long("basic-regexp") .help("PATTERNS are basic regular expressions") - .action(ArgAction::SetTrue) - .overrides_with_all(["extended_regexp", "fixed_strings", "perl_regexp"]), + .action(ArgAction::SetTrue), ) .arg( Arg::new("perl_regexp") .short('P') .long("perl-regexp") .help("PATTERNS are Perl regular expressions") - .action(ArgAction::SetTrue) - .overrides_with_all(["basic_regexp", "extended_regexp", "fixed_strings"]), + .action(ArgAction::SetTrue), ) .arg( Arg::new("regexp") diff --git a/tests/test_grep.rs b/tests/test_grep.rs index 2c16db4..59aca3b 100644 --- a/tests/test_grep.rs +++ b/tests/test_grep.rs @@ -165,6 +165,41 @@ fn fixed_string_is_literal() { .stdout_only("hi\nHI\n"); } +#[test] +fn conflicting_matcher_flags_are_rejected() { + let cases: &[&[&str]] = &[ + &["-e", ".", "-F", "-G"], + &["-e", ".", "-F", "-E"], + &["-e", ".", "-E", "-G"], + &["-e", ".", "-G", "-E"], + &["-e", ".", "-P", "-F"], + &["-e", ".", "-P", "-E"], + &["-e", ".", "-P", "-G"], + &["-e", ".", "-G", "-F", "-E"], + &["-e", ".", "--fixed-strings", "--basic-regexp"], + ]; + + for args in cases { + let (_s, mut c) = ucmd(); + c.args(args) + .fails_with_code(2) + .stderr_contains("conflicting matchers specified") + .no_stdout(); + } + + let (_s, mut c) = ucmd(); + c.args(&["-e", ".", "-F", "-F"]) + .pipe_in("abc\n") + .fails_with_code(1) + .no_stdout(); + + let (_s, mut c) = ucmd(); + c.args(&["-e", ".", "-E", "-E"]) + .pipe_in("abc\n") + .succeeds() + .stdout_only("abc\n"); +} + #[test] fn pcre_features() { let (_s, mut c) = ucmd(); @@ -197,14 +232,12 @@ fn perl_regexp_rejects_multiple_patterns() { // Two separate -e flags. let (_s, mut c) = ucmd(); c.args(&["-P", "-e", "foo", "-e", "bar"]) - .pipe_in("foo\nbar\n") .fails_with_code(2) .stderr_contains("the -P option only supports a single pattern"); // A newline inside the pattern string is split into multiple patterns. let (_s, mut c) = ucmd(); c.args(&["-P", "-e", "foo\nbar"]) - .pipe_in("foo\nbar\n") .fails_with_code(2) .stderr_contains("the -P option only supports a single pattern");