Skip to content

Commit 0d8a309

Browse files
rscharfegitster
authored andcommitted
parse-options: detect ambiguous self-negation
Git currently does not detect the ambiguity of an option that starts with "no" like --notes and its negated form if given just --n or --no. All Git commands with such options have other negatable options, and we detect the ambiguity with them, so that's currently only a potential problem for scripts that use git rev-parse --parseopt. Let's fix it nevertheless, as there's no need for that confusion. To detect the ambiguity we have to loosen the check in register_abbrev(), as an option is considered an alias of itself. Add non-matching negation flags as a criterion to recognize an option being ambiguous with its negated form. And we need to keep going after finding a non-negated option as an abbreviated candidate and perform the negation checks in the same loop. Signed-off-by: René Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cb46c3f commit 0d8a309

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-2
lines changed

parse-options.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ static void register_abbrev(struct parse_opt_ctx_t *p,
363363
if (p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT)
364364
return;
365365
if (abbrev->option &&
366-
!is_alias(p, abbrev->option, option)) {
366+
!(abbrev->flags == flags && is_alias(p, abbrev->option, option))) {
367367
/*
368368
* If this is abbreviated, it is
369369
* ambiguous. So when there is no
@@ -406,7 +406,6 @@ static enum parse_opt_result parse_long_opt(
406406
if (!strncmp(long_name, arg, arg_end - arg)) {
407407
register_abbrev(p, options, flags ^ opt_flags,
408408
&abbrev, &ambiguous);
409-
continue;
410409
}
411410
/* negation allowed? */
412411
if (options->flags & PARSE_OPT_NONEG)

t/t1502-rev-parse-parseopt.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,15 @@ check_invalid_long_option optionspec-neg --no-positive-only
322322
check_invalid_long_option optionspec-neg --negative
323323
check_invalid_long_option optionspec-neg --no-no-negative
324324

325+
test_expect_success 'ambiguous: --no matches both --noble and --no-noble' '
326+
cat >spec <<-\EOF &&
327+
some-command [options]
328+
--
329+
noble The feudal switch.
330+
EOF
331+
test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
332+
git rev-parse --parseopt -- <spec 2>err --no &&
333+
grep "error: ambiguous option: no (could be --noble or --no-noble)" err
334+
'
335+
325336
test_done

0 commit comments

Comments
 (0)