Merge branch 'rs/parse-options-with-keep-unknown-abbrev-fix'
"git diff --no-rename A B" did not disable rename detection but did not trigger an error from the command line parser. * rs/parse-options-with-keep-unknown-abbrev-fix: parse-options: simplify positivation handling parse-options: fully disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN
This commit is contained in:
@ -357,6 +357,7 @@ static enum parse_opt_result parse_long_opt(
|
|||||||
const char *arg_end = strchrnul(arg, '=');
|
const char *arg_end = strchrnul(arg, '=');
|
||||||
const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
|
const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
|
||||||
enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG;
|
enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG;
|
||||||
|
int allow_abbrev = !(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT);
|
||||||
|
|
||||||
for (; options->type != OPTION_END; options++) {
|
for (; options->type != OPTION_END; options++) {
|
||||||
const char *rest, *long_name = options->long_name;
|
const char *rest, *long_name = options->long_name;
|
||||||
@ -367,12 +368,16 @@ static enum parse_opt_result parse_long_opt(
|
|||||||
if (!long_name)
|
if (!long_name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
again:
|
if (!starts_with(arg, "no-") &&
|
||||||
|
!(options->flags & PARSE_OPT_NONEG) &&
|
||||||
|
skip_prefix(long_name, "no-", &long_name))
|
||||||
|
opt_flags |= OPT_UNSET;
|
||||||
|
|
||||||
if (!skip_prefix(arg, long_name, &rest))
|
if (!skip_prefix(arg, long_name, &rest))
|
||||||
rest = NULL;
|
rest = NULL;
|
||||||
if (!rest) {
|
if (!rest) {
|
||||||
/* abbreviated? */
|
/* abbreviated? */
|
||||||
if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT) &&
|
if (allow_abbrev &&
|
||||||
!strncmp(long_name, arg, arg_end - arg)) {
|
!strncmp(long_name, arg, arg_end - arg)) {
|
||||||
is_abbreviated:
|
is_abbreviated:
|
||||||
if (abbrev_option &&
|
if (abbrev_option &&
|
||||||
@ -396,22 +401,18 @@ is_abbreviated:
|
|||||||
if (options->flags & PARSE_OPT_NONEG)
|
if (options->flags & PARSE_OPT_NONEG)
|
||||||
continue;
|
continue;
|
||||||
/* negated and abbreviated very much? */
|
/* negated and abbreviated very much? */
|
||||||
if (starts_with("no-", arg)) {
|
if (allow_abbrev && starts_with("no-", arg)) {
|
||||||
flags |= OPT_UNSET;
|
flags |= OPT_UNSET;
|
||||||
goto is_abbreviated;
|
goto is_abbreviated;
|
||||||
}
|
}
|
||||||
/* negated? */
|
/* negated? */
|
||||||
if (!starts_with(arg, "no-")) {
|
if (!starts_with(arg, "no-"))
|
||||||
if (skip_prefix(long_name, "no-", &long_name)) {
|
|
||||||
opt_flags |= OPT_UNSET;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
flags |= OPT_UNSET;
|
flags |= OPT_UNSET;
|
||||||
if (!skip_prefix(arg + 3, long_name, &rest)) {
|
if (!skip_prefix(arg + 3, long_name, &rest)) {
|
||||||
/* abbreviated and negated? */
|
/* abbreviated and negated? */
|
||||||
if (starts_with(long_name, arg + 3))
|
if (allow_abbrev &&
|
||||||
|
starts_with(long_name, arg + 3))
|
||||||
goto is_abbreviated;
|
goto is_abbreviated;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
@ -663,4 +663,10 @@ test_expect_success 'diff --default-prefix overrides diff.mnemonicprefix' '
|
|||||||
check_prefix actual a/file0 b/file0
|
check_prefix actual a/file0 b/file0
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'diff --no-renames cannot be abbreviated' '
|
||||||
|
test_expect_code 129 git diff --no-rename >actual 2>error &&
|
||||||
|
test_must_be_empty actual &&
|
||||||
|
grep "invalid option: --no-rename" error
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user