Skip to content

Commit 4a12f89

Browse files
committed
Merge branch 'jk/eoo'
The command line parser learned "--end-of-options" notation; the standard convention for scripters to have hardcoded set of options first on the command line, and force the command to treat end-user input as non-options, has been to use "--" as the delimiter, but that would not work for commands that use "--" as a delimiter between revs and pathspec. * jk/eoo: gitcli: document --end-of-options parse-options: allow --end-of-options as a synonym for "--" revision: allow --end-of-options to end option parsing
2 parents b4a1eec + 67feca3 commit 4a12f89

File tree

6 files changed

+37
-2
lines changed

6 files changed

+37
-2
lines changed

Documentation/gitcli.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ arguments. Here are the rules:
3737
file called HEAD in your work tree, `git diff HEAD` is ambiguous, and
3838
you have to say either `git diff HEAD --` or `git diff -- HEAD` to
3939
disambiguate.
40+
41+
* Because `--` disambiguates revisions and paths in some commands, it
42+
cannot be used for those commands to separate options and revisions.
43+
You can use `--end-of-options` for this (it also works for commands
44+
that do not distinguish between revisions in paths, in which case it
45+
is simply an alias for `--`).
4046
+
4147
When writing a script that is expected to handle random user-input, it is
4248
a good practice to make it explicit which arguments are which by placing

parse-options.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
780780
continue;
781781
}
782782

783-
if (!arg[2]) { /* "--" */
783+
if (!arg[2] /* "--" */ ||
784+
!strcmp(arg + 2, "end-of-options")) {
784785
if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
785786
ctx->argc--;
786787
ctx->argv++;

revision.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
25232523
int i, flags, left, seen_dashdash, got_rev_arg = 0, revarg_opt;
25242524
struct argv_array prune_data = ARGV_ARRAY_INIT;
25252525
const char *submodule = NULL;
2526+
int seen_end_of_options = 0;
25262527

25272528
if (opt)
25282529
submodule = opt->submodule;
@@ -2552,7 +2553,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
25522553
revarg_opt |= REVARG_CANNOT_BE_FILENAME;
25532554
for (left = i = 1; i < argc; i++) {
25542555
const char *arg = argv[i];
2555-
if (*arg == '-') {
2556+
if (!seen_end_of_options && *arg == '-') {
25562557
int opts;
25572558

25582559
opts = handle_revision_pseudo_opt(submodule,
@@ -2574,6 +2575,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
25742575
continue;
25752576
}
25762577

2578+
if (!strcmp(arg, "--end-of-options")) {
2579+
seen_end_of_options = 1;
2580+
continue;
2581+
}
2582+
25772583
opts = handle_revision_opt(revs, argc - i, argv + i,
25782584
&left, argv, opt);
25792585
if (opts > 0) {

t/t0040-parse-options.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,11 @@ test_expect_success 'GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS works' '
399399
test-tool parse-options --ye
400400
'
401401

402+
test_expect_success '--end-of-options treats remainder as args' '
403+
test-tool parse-options \
404+
--expect="verbose: -1" \
405+
--expect="arg 00: --verbose" \
406+
--end-of-options --verbose
407+
'
408+
402409
test_done

t/t4202-log.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,4 +1707,11 @@ test_expect_success '--exclude-promisor-objects does not BUG-crash' '
17071707
test_must_fail git log --exclude-promisor-objects source-a
17081708
'
17091709

1710+
test_expect_success 'log --end-of-options' '
1711+
git update-ref refs/heads/--source HEAD &&
1712+
git log --end-of-options --source >actual &&
1713+
git log >expect &&
1714+
test_cmp expect actual
1715+
'
1716+
17101717
test_done

t/t6000-rev-list-misc.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,12 @@ test_expect_success '--header shows a NUL after each commit' '
140140
test_cmp expect actual
141141
'
142142

143+
test_expect_success 'rev-list --end-of-options' '
144+
git update-ref refs/heads/--output=yikes HEAD &&
145+
git rev-list --end-of-options --output=yikes >actual &&
146+
test_path_is_missing yikes &&
147+
git rev-list HEAD >expect &&
148+
test_cmp expect actual
149+
'
150+
143151
test_done

0 commit comments

Comments
 (0)