On Mon, Feb 13, 2017 at 04:11:59PM -0800, Jonathan Tan wrote: > When running a command of the form > > git grep --no-index pattern -- path > > in the absence of a Git repository, an error message will be printed: > > fatal: BUG: setup_git_env called without repository > > This is because "git grep" tries to interpret "--" as a rev. "git grep" > has always tried to first interpret "--" as a rev for at least a few > years, but this issue was upgraded from a pessimization to a bug in > commit 59332d1 ("Resurrect "git grep --no-index"", 2010-02-06), which > calls get_sha1 regardless of whether --no-index was specified. This bug > appeared to be benign until commit b1ef400 ("setup_git_env: avoid blind > fall-back to ".git"", 2016-10-20) when Git was taught to die in this > situation. (This "git grep" bug appears to be one of the bugs that > commit b1ef400 is meant to flush out.) > > Therefore, always interpret "--" as signaling the end of options, > instead of trying to interpret it as a rev first. Nicely explained. > There is probably a similar bug for commands of the form: > > git grep --no-index pattern foo > > If there is a repo and "foo" is a rev, the "--no-index or --untracked > cannot be used with revs." error would occur. If there is a repo and > "foo" is not a rev, this command would proceed as usual. If there is no > repo, the "setup_git_env called without repository" error would occur. > (This is my understanding from reading the code - I haven't tested it > out.) Yes, it's easy to see that "git grep --no-index foo bar" outside of a repo generates the same BUG. I suspect that "--no-index" should just disable looking up revs entirely, even if we are actually in a repository directory. > This patch does not fix this similar bug, but I decided to send it out > anyway because it still fixes a bug and unlocks the ability to > specify paths with "git grep --no-index". Yes, I think even if we fix the other bug, fixing this "--" thing is an improvement. > diff --git a/builtin/grep.c b/builtin/grep.c > index 2c727ef49..1b68d1638 100644 > --- a/builtin/grep.c > +++ b/builtin/grep.c > @@ -1154,6 +1154,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix) > const char *arg = argv[i]; > unsigned char sha1[20]; > struct object_context oc; > + if (!strcmp(arg, "--")) { > + i++; > + seen_dashdash = 1; > + break; > + } > /* Is it a rev? */ > if (!get_sha1_with_context(arg, 0, sha1, &oc)) { > struct object *object = parse_object_or_die(sha1, arg); So I think this is a definite improvement, but I see a few leftover oddities: - the end logic for this loop is now: if (arg is a rev) { ... handle rev ... continue; } break; It would probably be more obvious as: if (arg is not a rev) break; ... handle rev ... - the rev-handling code does: if (!seen_dashdash) verify_non_filename(prefix, arg); But I do not see how seen_dashdash could ever be untrue. We set it inside this loop, and break immediately when we see it. And indeed, running: echo content >master git grep content master -- does not work. The "--" should tell us that "master" is a rev, but we don't know yet that we have a dashdash. I think we need a separate loop to find the "--" first, and _then_ walk through the arguments, treating them as revs or paths as appropriate. This is how setup_revisions() does it. So this isn't a problem introduced by your patch, but it's intimately related. > diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh > index 19f0108f8..29202f0e7 100755 > --- a/t/t7810-grep.sh > +++ b/t/t7810-grep.sh > @@ -982,6 +982,18 @@ test_expect_success 'grep -e -- -- path' ' > test_cmp expected actual > ' > > +test_expect_success 'grep --no-index pattern -- path' ' > + rm -fr non && > + mkdir -p non/git && > + ( > + GIT_CEILING_DIRECTORIES="$(pwd)/non" && > + export GIT_CEILING_DIRECTORIES && > + cd non/git && > + echo hello >hello && > + git grep --no-index o -- . > + ) > +' Since de95302a4, you can do: nongit git grep --no-index -o -- . Though if this is destined for maint, it might need to be done separately this way and cleaned up later. It might also be a good idea to confirm that the pathspec is actually being respected in the --no-index case. Something like: echo hello >hello && echo goodbye >goodbye && echo hello:hello >expect && git grep --no-index o -- hello >actual && test_cmp expect actual -Peff