Skip to content

Commit 66b8800

Browse files
committed
Merge branch 'rs/no-no-no-parseopt'
* rs/no-no-no-parseopt: parse-options: remove PARSE_OPT_NEGHELP parse-options: allow positivation of options starting, with no- test-parse-options: convert to OPT_BOOL() Conflicts: builtin/grep.c
2 parents 260eb7e + cbb08c2 commit 66b8800

File tree

8 files changed

+108
-32
lines changed

8 files changed

+108
-32
lines changed

Documentation/RelNotes/1.7.10.txt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Updates since v1.7.9
66

77
UI, Workflows & Features
88

9+
* Teams for localizing the messages from the Porcelain layer of
10+
commands are starting to form, thanks to Jiang Xin who volunteered
11+
to be the localization coordinator. An initial set of translated
12+
messages for simplified chinese is available.
13+
914
* Improved handling of views, labels and branches in git-p4 (in contrib).
1015

1116
* "git-p4" (in contrib) suffered from unnecessary merge conflicts when
@@ -98,6 +103,18 @@ Unless otherwise noted, all the fixes since v1.7.9 in the maintenance
98103
releases are contained in this release (see release notes to them for
99104
details).
100105

106+
* "git branch --with $that" assumed incorrectly that the user will never
107+
ask the question with nonsense value in $that.
108+
(merge 6c41e97 cn/maint-branch-with-bad later to maint).
109+
110+
* An invalid regular expression pattern given by an end user made
111+
"gitweb" to return garbled response.
112+
(merge 36612e4 jn/maint-gitweb-invalid-regexp later to maint).
113+
114+
* "git rev-list --verify-objects -q" omitted the extra verification
115+
it needs to do over "git rev-list --objects -q" by mistake.
116+
(merge 9899372 nd/maint-verify-objects later to maint).
117+
101118
* The bulk check-in codepath streamed contents that needs
102119
smudge/clean filters without running them, instead of punting and
103120
delegating to the codepath to run filters after slurping everything
@@ -126,7 +143,7 @@ details).
126143

127144
---
128145
exec >/var/tmp/1
129-
O=v1.7.9.2-322-g472fdee
146+
O=v1.7.9.2-347-gbfabdfe
130147
echo O=$(git describe)
131148
git log --first-parent --oneline ^maint $O..
132149
echo

Documentation/technical/api-parse-options.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ The parse-options API allows:
3939
* Short options may be bundled, e.g. `-a -b` can be specified as `-ab`.
4040

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

4445
* Options and non-option arguments can clearly be separated using the `\--`
4546
option, e.g. `-a -b \--option \-- \--this-is-a-file` indicates that

builtin/fast-export.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,9 +647,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
647647
"Output full tree for each commit"),
648648
OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
649649
"Use the done feature to terminate the stream"),
650-
{ OPTION_NEGBIT, 0, "data", &no_data, NULL,
651-
"Skip output of blob data",
652-
PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 },
650+
OPT_BOOL(0, "no-data", &no_data, "Skip output of blob data"),
653651
OPT_END()
654652
};
655653

builtin/grep.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -684,9 +684,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
684684
struct option options[] = {
685685
OPT_BOOLEAN(0, "cached", &cached,
686686
"search in index instead of in the work tree"),
687-
{ OPTION_BOOLEAN, 0, "index", &use_index, NULL,
688-
"finds in contents not managed by git",
689-
PARSE_OPT_NOARG | PARSE_OPT_NEGHELP },
687+
OPT_NEGBIT(0, "no-index", &use_index,
688+
"finds in contents not managed by git", 1),
690689
OPT_BOOLEAN(0, "untracked", &untracked,
691690
"search in both tracked and untracked files"),
692691
OPT_SET_INT(0, "exclude-standard", &opt_exclude,

parse-options.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,14 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
193193
arg_end = arg + strlen(arg);
194194

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

199-
if (!options->long_name)
199+
if (!long_name)
200200
continue;
201201

202-
rest = skip_prefix(arg, options->long_name);
202+
again:
203+
rest = skip_prefix(arg, long_name);
203204
if (options->type == OPTION_ARGUMENT) {
204205
if (!rest)
205206
continue;
@@ -212,7 +213,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
212213
}
213214
if (!rest) {
214215
/* abbreviated? */
215-
if (!strncmp(options->long_name, arg, arg_end - arg)) {
216+
if (!strncmp(long_name, arg, arg_end - arg)) {
216217
is_abbreviated:
217218
if (abbrev_option) {
218219
/*
@@ -227,7 +228,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
227228
if (!(flags & OPT_UNSET) && *arg_end)
228229
p->opt = arg_end + 1;
229230
abbrev_option = options;
230-
abbrev_flags = flags;
231+
abbrev_flags = flags ^ opt_flags;
231232
continue;
232233
}
233234
/* negation allowed? */
@@ -239,12 +240,18 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
239240
goto is_abbreviated;
240241
}
241242
/* negated? */
242-
if (strncmp(arg, "no-", 3))
243+
if (prefixcmp(arg, "no-")) {
244+
if (!prefixcmp(long_name, "no-")) {
245+
long_name += 3;
246+
opt_flags |= OPT_UNSET;
247+
goto again;
248+
}
243249
continue;
250+
}
244251
flags |= OPT_UNSET;
245-
rest = skip_prefix(arg + 3, options->long_name);
252+
rest = skip_prefix(arg + 3, long_name);
246253
/* abbreviated and negated? */
247-
if (!rest && !prefixcmp(options->long_name, arg + 3))
254+
if (!rest && !prefixcmp(long_name, arg + 3))
248255
goto is_abbreviated;
249256
if (!rest)
250257
continue;
@@ -254,7 +261,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
254261
continue;
255262
p->opt = rest + 1;
256263
}
257-
return get_value(p, options, flags);
264+
return get_value(p, options, flags ^ opt_flags);
258265
}
259266

260267
if (ambiguous_option)
@@ -526,7 +533,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
526533
continue;
527534

528535
pos = fprintf(outfile, " ");
529-
if (opts->short_name && !(opts->flags & PARSE_OPT_NEGHELP)) {
536+
if (opts->short_name) {
530537
if (opts->flags & PARSE_OPT_NODASH)
531538
pos += fprintf(outfile, "%c", opts->short_name);
532539
else
@@ -535,9 +542,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
535542
if (opts->long_name && opts->short_name)
536543
pos += fprintf(outfile, ", ");
537544
if (opts->long_name)
538-
pos += fprintf(outfile, "--%s%s",
539-
(opts->flags & PARSE_OPT_NEGHELP) ? "no-" : "",
540-
opts->long_name);
545+
pos += fprintf(outfile, "--%s", opts->long_name);
541546
if (opts->type == OPTION_NUMBER)
542547
pos += fprintf(outfile, "-NUM");
543548

parse-options.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ enum parse_opt_option_flags {
4040
PARSE_OPT_LASTARG_DEFAULT = 16,
4141
PARSE_OPT_NODASH = 32,
4242
PARSE_OPT_LITERAL_ARGHELP = 64,
43-
PARSE_OPT_NEGHELP = 128,
4443
PARSE_OPT_SHELL_EVAL = 256
4544
};
4645

@@ -90,9 +89,6 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,
9089
* PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
9190
* (i.e. '<argh>') in the help message.
9291
* Useful for options with multiple parameters.
93-
* PARSE_OPT_NEGHELP: says that the long option should always be shown with
94-
* the --no prefix in the usage message. Sometimes
95-
* useful for users of OPTION_NEGBIT.
9692
*
9793
* `callback`::
9894
* pointer to the callback to use for OPTION_CALLBACK or

t/t0040-parse-options.sh

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ test_description='our own option parser'
1010
cat > expect << EOF
1111
usage: test-parse-options <options>
1212
13-
-b, --boolean get a boolean
13+
--yes get a boolean
14+
-D, --no-doubt begins with 'no-'
15+
-B, --no-fear be brave
16+
-b, --boolean increment by one
1417
-4, --or4 bitwise-or boolean with ...0100
1518
--neg-or4 same as --no-or4
1619
@@ -53,6 +56,59 @@ test_expect_success 'test help' '
5356

5457
mv expect expect.err
5558

59+
cat >expect.template <<EOF
60+
boolean: 0
61+
integer: 0
62+
timestamp: 0
63+
string: (not set)
64+
abbrev: 7
65+
verbose: 0
66+
quiet: no
67+
dry run: no
68+
file: (not set)
69+
EOF
70+
71+
check() {
72+
what="$1" &&
73+
shift &&
74+
expect="$1" &&
75+
shift &&
76+
sed "s/^$what .*/$what $expect/" <expect.template >expect &&
77+
test-parse-options $* >output 2>output.err &&
78+
test ! -s output.err &&
79+
test_cmp expect output
80+
}
81+
82+
check_unknown() {
83+
case "$1" in
84+
--*)
85+
echo error: unknown option \`${1#--}\' >expect ;;
86+
-*)
87+
echo error: unknown switch \`${1#-}\' >expect ;;
88+
esac &&
89+
cat expect.err >>expect &&
90+
test_must_fail test-parse-options $* >output 2>output.err &&
91+
test ! -s output &&
92+
test_cmp expect output.err
93+
}
94+
95+
test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes'
96+
test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt'
97+
test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D'
98+
test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear'
99+
test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B'
100+
101+
test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
102+
test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
103+
104+
test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
105+
test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
106+
107+
test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown --fear'
108+
test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown --no-no-fear'
109+
110+
test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
111+
56112
cat > expect << EOF
57113
boolean: 2
58114
integer: 1729
@@ -296,7 +352,7 @@ test_expect_success 'OPT_NEGBIT() works' '
296352
test_cmp expect output
297353
'
298354

299-
test_expect_success 'OPT_BOOLEAN() with PARSE_OPT_NODASH works' '
355+
test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
300356
test-parse-options + + + + + + > output 2> output.err &&
301357
test ! -s output.err &&
302358
test_cmp expect output

test-parse-options.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ int main(int argc, const char **argv)
3737
NULL
3838
};
3939
struct option options[] = {
40-
OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"),
40+
OPT_BOOL(0, "yes", &boolean, "get a boolean"),
41+
OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"),
42+
{ OPTION_SET_INT, 'B', "no-fear", &boolean, NULL,
43+
"be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
44+
OPT_COUNTUP('b', "boolean", &boolean, "increment by one"),
4145
OPT_BIT('4', "or4", &boolean,
4246
"bitwise-or boolean with ...0100", 4),
4347
OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4),
@@ -62,11 +66,11 @@ int main(int argc, const char **argv)
6266
OPT_ARGUMENT("quux", "means --quux"),
6367
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
6468
number_callback),
65-
{ OPTION_BOOLEAN, '+', NULL, &boolean, NULL, "same as -b",
69+
{ OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b",
6670
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH },
67-
{ OPTION_BOOLEAN, 0, "ambiguous", &ambiguous, NULL,
71+
{ OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL,
6872
"positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
69-
{ OPTION_BOOLEAN, 0, "no-ambiguous", &ambiguous, NULL,
73+
{ OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL,
7074
"negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
7175
OPT_GROUP("Standard options"),
7276
OPT__ABBREV(&abbrev),

0 commit comments

Comments
 (0)