X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-grep.c;h=89489ddcf8edb85160036b0336ab4ce80c3cb6bc;hb=01eadafccbeae485503f5373dc60cc5a04877c3b;hp=d3cc75e3a47bed0d44d1981a6f609f24558a9e1b;hpb=3e186ef13572196a6b2a18573bc9066dcf1060c9;p=git.git diff --git a/builtin-grep.c b/builtin-grep.c index d3cc75e3a..89489ddcf 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -20,6 +20,30 @@ #endif #endif +static int builtin_grep; + +static int grep_config(const char *var, const char *value, void *cb) +{ + struct grep_opt *opt = cb; + + if (!strcmp(var, "grep.color") || !strcmp(var, "color.grep")) { + opt->color = git_config_colorbool(var, value, -1); + return 0; + } + if (!strcmp(var, "grep.color.external") || + !strcmp(var, "color.grep.external")) { + return git_config_string(&(opt->color_external), var, value); + } + if (!strcmp(var, "grep.color.match") || + !strcmp(var, "color.grep.match")) { + if (!value) + return config_error_nonbool(var); + color_parse(value, var, opt->color_match); + return 0; + } + return git_color_default_config(var, value, cb); +} + /* * git grep pathspecs are somewhat different from diff-tree pathspecs; * pathname wildcards are allowed. @@ -267,6 +291,21 @@ static int flush_grep(struct grep_opt *opt, return status; } +static void grep_add_color(struct strbuf *sb, const char *escape_seq) +{ + size_t orig_len = sb->len; + + while (*escape_seq) { + if (*escape_seq == 'm') + strbuf_addch(sb, ';'); + else if (*escape_seq != '\033' && *escape_seq != '[') + strbuf_addch(sb, *escape_seq); + escape_seq++; + } + if (sb->len > orig_len && sb->buf[sb->len - 1] == ';') + strbuf_setlen(sb, sb->len - 1); +} + static int external_grep(struct grep_opt *opt, const char **paths, int cached) { int i, nr, argc, hit, len, status; @@ -297,6 +336,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) { @@ -334,6 +376,23 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) push_arg("-e"); push_arg(p->pattern); } + if (opt->color) { + struct strbuf sb = STRBUF_INIT; + + grep_add_color(&sb, opt->color_match); + setenv("GREP_COLOR", sb.buf, 1); + + strbuf_reset(&sb); + strbuf_addstr(&sb, "mt="); + grep_add_color(&sb, opt->color_match); + strbuf_addstr(&sb, ":sl=:cx=:fn=:ln=:bn=:se="); + setenv("GREP_COLORS", sb.buf, 1); + + strbuf_release(&sb); + + if (opt->color_external && strlen(opt->color_external) > 0) + push_arg(opt->color_external); + } hit = 0; argc = nr; @@ -388,7 +447,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; @@ -401,7 +460,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); @@ -526,6 +590,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix) opt.pattern_tail = &opt.pattern_list; opt.regflags = REG_NEWLINE; + strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD); + opt.color = -1; + git_config(grep_config, &opt); + if (opt.color == -1) + opt.color = git_use_color_default; + /* * If there is no -- then the paths must exist in the working * tree. If there is no explicit pattern specified with -e or @@ -544,6 +614,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; @@ -601,6 +675,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; @@ -713,6 +792,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix) opt.relative = 0; continue; } + if (!strcmp("--color", arg)) { + opt.color = 1; + continue; + } + if (!strcmp("--no-color", arg)) { + opt.color = 0; + continue; + } if (!strcmp("--", arg)) { /* later processing wants to have this at argv[1] */ argv--; @@ -738,6 +825,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) } } + if (opt.color && !opt.color_external) + builtin_grep = 1; if (!opt.pattern_list) die("no pattern given."); if ((opt.regflags != REG_NEWLINE) && opt.fixed)