parse-options: fully disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN
baa4adc66a (parse-options: disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN, 2019-01-27) turned off support for abbreviated options when the flag PARSE_OPT_KEEP_UNKNOWN is given, as any shortened option could also be an abbreviation for one of the unknown options. The code for handling abbreviated options is guarded by an if, but it can also be reached via goto. baa4adc66a only blocked the first way. Add the condition to the other ones as well. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Jan 20, 2024 at 15:39 UTC
5825268db1058516d05be03d6a8d8d55eea5a943
2 files changed
+11
-3
parse-options.c
+5
-3
@@ -358,6 +358,7 @@ static enum parse_opt_result parse_long_opt(
358
const char *arg_end = strchrnul(arg, '=');
359
const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
360
enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG;
361
+ int allow_abbrev = !(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT);
362
363
for (; options->type != OPTION_END; options++) {
364
const char *rest, *long_name = options->long_name;
@@ -373,7 +374,7 @@ again:
374
rest = NULL;
375
if (!rest) {
376
/* abbreviated? */
376
- if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT) &&
377
+ if (allow_abbrev &&
378
!strncmp(long_name, arg, arg_end - arg)) {
379
is_abbreviated:
380
if (abbrev_option &&
@@ -397,7 +398,7 @@ is_abbreviated:
398
if (options->flags & PARSE_OPT_NONEG)
399
continue;
400
/* negated and abbreviated very much? */
400
- if (starts_with("no-", arg)) {
401
+ if (allow_abbrev && starts_with("no-", arg)) {
402
flags |= OPT_UNSET;
403
goto is_abbreviated;
404
}
@@ -412,7 +413,8 @@ is_abbreviated:
413
flags |= OPT_UNSET;
414
if (!skip_prefix(arg + 3, long_name, &rest)) {
415
/* abbreviated and negated? */
415
- if (starts_with(long_name, arg + 3))
416
+ if (allow_abbrev &&
417
+ starts_with(long_name, arg + 3))
418
goto is_abbreviated;
419
else
420
continue;
t/t4013-diff-various.sh
+6
@@ -666,4 +666,10 @@ test_expect_success 'diff --default-prefix overrides diff.mnemonicprefix' '
666
check_prefix actual a/file0 b/file0
667
'
668
669
+test_expect_success 'diff --no-renames cannot be abbreviated' '
670
+ test_expect_code 129 git diff --no-rename >actual 2>error &&
671
+ test_must_be_empty actual &&
672
+ grep "invalid option: --no-rename" error
673
+'
674
+
675
test_done