summaryrefslogtreecommitdiff
path: root/builtin-grep.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin-grep.c')
-rw-r--r--builtin-grep.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/builtin-grep.c b/builtin-grep.c
index 631129ddfd..3f12ba3826 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -20,6 +20,8 @@
#endif
#endif
+static int builtin_grep;
+
/*
* git grep pathspecs are somewhat different from diff-tree pathspecs;
* pathname wildcards are allowed.
@@ -289,12 +291,17 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
push_arg("-E");
if (opt->regflags & REG_ICASE)
push_arg("-i");
+ if (opt->binary == GREP_BINARY_NOMATCH)
+ push_arg("-I");
if (opt->word_regexp)
push_arg("-w");
if (opt->name_only)
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 +393,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 +406,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);
@@ -542,6 +554,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 +615,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 +795,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 +804,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.");