grep: do not unnecessarily query repo for "--"
authorJonathan Tan <jonathantanmy@google.com>
Tue, 14 Feb 2017 06:03:03 +0000 (01:03 -0500)
committerJunio C Hamano <gitster@pobox.com>
Tue, 14 Feb 2017 19:26:37 +0000 (11:26 -0800)
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.

Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/grep.c
t/t7810-grep.sh
index 5a282c4d06b174febf0180622b702a66c4df9e1b..081e1b57a163c4d2607be6892c1c979fec3fe649 100644 (file)
@@ -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);
@@ -1162,10 +1167,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
                        continue;
                }
-               if (!strcmp(arg, "--")) {
-                       i++;
-                       seen_dashdash = 1;
-               }
                break;
        }
 
index 19f0108f8a2c67c518a92d996be7a335dbb69af2..2c1f7373e6bce9497a45894133757f58a3e084af 100755 (executable)
@@ -982,6 +982,21 @@ 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 &&
+               echo goodbye >goodbye &&
+               echo hello:hello >expect &&
+               git grep --no-index o -- hello >actual &&
+               test_cmp expect actual
+       )
+'
+
 cat >expected <<EOF
 hello.c:int main(int argc, const char **argv)
 hello.c:       printf("Hello world.\n");