Skip to content

Commit

Permalink
parse-options: allow positivation of options starting, with no-
Browse files Browse the repository at this point in the history
Long options can be negated by adding no- right after the leading
two dashes. This is useful e.g. to override options set by aliases.

For options that are defined to start with no- already, this looks
a bit funny. Allow such options to also be negated by removing the
prefix.

The following thirteen options are affected:

	apply          --no-add
	bisect--helper --no-checkout
	checkout-index --no-create
	clone          --no-checkout --no-hardlinks
	commit         --no-verify   --no-post-rewrite
	format-patch   --no-binary
	hash-object    --no-filters
	read-tree      --no-sparse-checkout
	revert         --no-commit
	show-branch    --no-name
	update-ref     --no-deref

The following five are NOT affected because they are defined with
PARSE_OPT_NONEG or the non-negated version is defined as well:

	branch       --no-merged
	format-patch --no-stat             --no-numbered
	update-index --no-assume-unchanged --no-skip-worktree

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
René Scharfe authored and Junio C Hamano committed Feb 26, 2012
1 parent b9e63dd commit 0f1930c
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 12 deletions.
3 changes: 2 additions & 1 deletion Documentation/technical/api-parse-options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ The parse-options API allows:
* Short options may be bundled, e.g. `-a -b` can be specified as `-ab`.

* Boolean long options can be 'negated' (or 'unset') by prepending
`no-`, e.g. `\--no-abbrev` instead of `\--abbrev`.
`no-`, e.g. `\--no-abbrev` instead of `\--abbrev`. Conversely,
options that begin with `no-` can be 'negated' by removing it.

* Options and non-option arguments can clearly be separated using the `\--`
option, e.g. `-a -b \--option \-- \--this-is-a-file` indicates that
Expand Down
27 changes: 17 additions & 10 deletions parse-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,14 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
arg_end = arg + strlen(arg);

for (; options->type != OPTION_END; options++) {
const char *rest;
int flags = 0;
const char *rest, *long_name = options->long_name;
int flags = 0, opt_flags = 0;

if (!options->long_name)
if (!long_name)
continue;

rest = skip_prefix(arg, options->long_name);
again:
rest = skip_prefix(arg, long_name);
if (options->type == OPTION_ARGUMENT) {
if (!rest)
continue;
Expand All @@ -212,7 +213,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
}
if (!rest) {
/* abbreviated? */
if (!strncmp(options->long_name, arg, arg_end - arg)) {
if (!strncmp(long_name, arg, arg_end - arg)) {
is_abbreviated:
if (abbrev_option) {
/*
Expand All @@ -227,7 +228,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
if (!(flags & OPT_UNSET) && *arg_end)
p->opt = arg_end + 1;
abbrev_option = options;
abbrev_flags = flags;
abbrev_flags = flags ^ opt_flags;
continue;
}
/* negation allowed? */
Expand All @@ -239,12 +240,18 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
goto is_abbreviated;
}
/* negated? */
if (strncmp(arg, "no-", 3))
if (prefixcmp(arg, "no-")) {
if (!prefixcmp(long_name, "no-")) {
long_name += 3;
opt_flags |= OPT_UNSET;
goto again;
}
continue;
}
flags |= OPT_UNSET;
rest = skip_prefix(arg + 3, options->long_name);
rest = skip_prefix(arg + 3, long_name);
/* abbreviated and negated? */
if (!rest && !prefixcmp(options->long_name, arg + 3))
if (!rest && !prefixcmp(long_name, arg + 3))
goto is_abbreviated;
if (!rest)
continue;
Expand All @@ -254,7 +261,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
continue;
p->opt = rest + 1;
}
return get_value(p, options, flags);
return get_value(p, options, flags ^ opt_flags);
}

if (ambiguous_option)
Expand Down
2 changes: 1 addition & 1 deletion t/t0040-parse-options.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown --fear'
test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown --no-no-fear'

test_expect_failure 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'

cat > expect << EOF
boolean: 2
Expand Down

0 comments on commit 0f1930c

Please sign in to comment.