Merge branch 'rs/fgrep'
[gitweb.git] / builtin-grep.c
index d8b06ce810d334654ada4b7fa3b79c19a4787565..bebf15cd6f7d82b773f985ce238688b4759e3c37 100644 (file)
@@ -20,6 +20,8 @@
 #endif
 #endif
 
+static int builtin_grep;
+
 /*
  * git grep pathspecs are somewhat different from diff-tree pathspecs;
  * pathname wildcards are allowed.
@@ -295,6 +297,9 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                push_arg("-l");
        if (opt->unmatch_name_only)
                push_arg("-L");
+       if (opt->null_following_name)
+               /* in GNU grep git's "-z" translates to "-Z" */
+               push_arg("-Z");
        if (opt->count)
                push_arg("-c");
        if (opt->post_context || opt->pre_context) {
@@ -386,7 +391,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
         * we grep through the checked-out files. It tends to
         * be a lot more optimized
         */
-       if (!cached) {
+       if (!cached && !builtin_grep) {
                hit = external_grep(opt, paths, cached);
                if (hit >= 0)
                        return hit;
@@ -399,7 +404,12 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
                        continue;
                if (!pathspec_matches(paths, ce->name))
                        continue;
-               if (cached) {
+               /*
+                * If CE_VALID is on, we assume worktree file and its cache entry
+                * are identical, even if worktree file has been modified, so use
+                * cache version instead
+                */
+               if (cached || (ce->ce_flags & CE_VALID)) {
                        if (ce_stage(ce))
                                continue;
                        hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
@@ -498,7 +508,7 @@ static int grep_object(struct grep_opt *opt, const char **paths,
 }
 
 static const char builtin_grep_usage[] =
-"git-grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
+"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
 
 static const char emsg_invalid_context_len[] =
 "%s: invalid context length argument";
@@ -542,6 +552,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        cached = 1;
                        continue;
                }
+               if (!strcmp("--no-ext-grep", arg)) {
+                       builtin_grep = 1;
+                       continue;
+               }
                if (!strcmp("-a", arg) ||
                    !strcmp("--text", arg)) {
                        opt.binary = GREP_BINARY_TEXT;
@@ -599,6 +613,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        opt.unmatch_name_only = 1;
                        continue;
                }
+               if (!strcmp("-z", arg) ||
+                   !strcmp("--null", arg)) {
+                       opt.null_following_name = 1;
+                       continue;
+               }
                if (!strcmp("-c", arg) ||
                    !strcmp("--count", arg)) {
                        opt.count = 1;
@@ -774,7 +793,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        /* Make sure we do not get outside of paths */
                        for (i = 0; paths[i]; i++)
                                if (strncmp(prefix, paths[i], opt.prefix_length))
-                                       die("git-grep: cannot generate relative filenames containing '..'");
+                                       die("git grep: cannot generate relative filenames containing '..'");
                }
        }
        else if (prefix) {
@@ -783,8 +802,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                paths[1] = NULL;
        }
 
-       if (!list.nr)
+       if (!list.nr) {
+               if (!cached)
+                       setup_work_tree();
                return !grep_cache(&opt, paths, cached);
+       }
 
        if (cached)
                die("both --cached and trees are given.");