Skip to content

uniq: match GNU's errors for -f/-s/-w and --group/--all-repeated - #14304

Open
arbelonson-source wants to merge 1 commit into
uutils:mainfrom
arbelonson-source:fix/uniq-invalid-argument-messages
Open

uniq: match GNU's errors for -f/-s/-w and --group/--all-repeated#14304
arbelonson-source wants to merge 1 commit into
uutils:mainfrom
arbelonson-source:fix/uniq-invalid-argument-messages

Conversation

@arbelonson-source

Copy link
Copy Markdown
Contributor

Three separate gaps, all in how uniq reports a bad option value.

-f/-s/-w: wrong words, wrong quoting

$ uniq -f abc f          # ours, before
uniq: Invalid argument for skip-fields: abc
$ uniq -f abc f          # GNU 9.11
uniq: abc: invalid number of fields to skip

GNU names what the number counts, not the option, and never quotes the value. -s says "bytes to skip", -w says "bytes to compare" — each of the three call sites now uses the phrase GNU uses for that one.

A value starting with - was also rejected outright — clap read it as an unrecognized flag rather than this option's value:

$ uniq -f -1 f            # ours, before
error: unexpected argument '-1' found
$ uniq -f -1 f            # GNU
uniq: -1: invalid number of fields to skip

allow_hyphen_values fixes that — the same gap fixed for sort --parallel in #14303 just now.

--group/--all-repeated: one clap possible-values list shared by two different options

$ uniq --group=bogus f          # ours, before
error: invalid value 'bogus' for '--group[=<group-method>]'
  [possible values: separate, prepend, append, both]
$ uniq --group=bogus f          # GNU
uniq: invalid argument 'bogus' for '--group'
Valid arguments are:
  - 'prepend'
  - 'append'
  - 'separate'
  - 'both'

Beyond the wording, get_delimiter read both options' values through the same match arm, so a bad --all-repeated value would have reported --group's list (or vice versa) if either had reached the point clap's own validation was bypassable — the two options don't even take the same choices (--all-repeated has none where --group has both, not the reverse). Fixed by validating each against its own list, in its own GNU-documented order, keeping the unambiguous-abbreviation matching ShortcutValueParser already gave (--group=s still resolves to separate).

A hack this retires

map_clap_errors had two branches that existed only to special-case the literal string "badoption" — the exact value GNU's own test suite happens to use — with that value hardcoded directly into the message text rather than read from the error. That could never have been correct for any value a user actually typed instead of "badoption". Removing the two ShortcutValueParsers removes the clap error kind those branches existed to intercept, so they're now dead code; deleted along with the two now-unused Fluent keys they referenced. The two tests that exercised them (from GNU's own test-case numbering, "119" and "145") are updated to the real, general message rather than the one hardcoded example.

Testing

  • 35-case differential sweep against GNU 9.11 covering -f/-s/-w with non-numeric, negative, empty and valid values (both space- and =-separated), and --group/--all-repeated with bad, valid, and abbreviated choices: all match (2 apparent mismatches were the test's own binary-path artifact in the --help hint, not a real difference).
  • 6 new tests, 3 confirmed to fail without the fix (the numeric-message, hyphen-value, and choice-list cases); the fourth (abbreviations) already passed before, since that part of ShortcutValueParser's behavior wasn't broken — kept as a non-regression check.
  • cargo test --features uniq --test tests -- test_uniq: 40 passed, 0 failed (34 pre-existing — 2 of which needed their hardcoded-"badoption" expectations corrected to the real message — plus 6 new).
  • moz-fluent-lint on src/uu/uniq/locales: no errors.
  • cargo fmt --check and cargo clippy -p uu_uniq --all-targets -- -D warnings: clean.

Disclosure

Prepared with AI assistance (Claude Opus 5, via Claude Code), per the AI policy in CONTRIBUTING.md. GNU's behaviour was established by running the installed GNU binary as a black box; I did not read GNU coreutils source. All testing was run locally.

Three separate gaps, all in how uniq reports a bad option value:

`-f`/`-s`/`-w` named the option and quoted the value, GNU does neither --
it names what the number counts instead:

    $ uniq -f abc f          # ours, before
    uniq: Invalid argument for skip-fields: abc
    $ uniq -f abc f          # GNU
    uniq: abc: invalid number of fields to skip

`-s` and `-w` say "bytes to skip"/"bytes to compare" instead; each of the
three call sites now says what GNU says for that one.

A value starting with `-` was rejected by clap as an unrecognized flag
instead of being read as the option's own value -- `uniq -f -1` -- needing
`allow_hyphen_values`, the same gap fixed for `sort --parallel` earlier.

`--group` and `--all-repeated` used a clap `ShortcutValueParser`, so a bad
choice got clap's wording, and worse, both used the SAME possible-values
list in the one place `get_delimiter` read them, even though the two
options take different choices with a different canonical order:

    $ uniq --group=bogus f          # ours, before
    error: invalid value 'bogus' for '--group[=<group-method>]'
      [possible values: separate, prepend, append, both]
    $ uniq --group=bogus f          # GNU
    uniq: invalid argument 'bogus' for '--group'
    Valid arguments are:
      - 'prepend'
      - 'append'
      - 'separate'
      - 'both'

Fixed by validating each option's value against its own choice list,
keeping the unambiguous-abbreviation matching `ShortcutValueParser` gave
(`--group=s` still means `separate`).

This also retires a hack in `map_clap_errors`: two branches existed only
to special-case the literal string "badoption" -- the exact value GNU's
own test suite happens to use -- with the *value* hardcoded into the
message text rather than read from the error. That could never have
been correct for a value the user actually typed; both `ShortcutValueParser`
choices being replaced removes the clap error they were built to catch,
and the two tests that exercised them are updated to the real, general
message instead.
@oech3

oech3 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

see #14308 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants