diff --git a/builtin/grep.c b/builtin/grep.c index 69ac2d8797..2cd9ec9019 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -18,6 +18,7 @@ #include "quote.h" #include "dir.h" #include "pathspec.h" +#include "attr.h" static char const * const grep_usage[] = { N_("git grep [options] [-e] [...] [[--] ...]"), @@ -163,6 +164,22 @@ static void work_done(struct work_item *w) grep_unlock(); } +static int skip_binary(struct grep_opt *opt, const char *filename) +{ + if ((opt->binary & GREP_BINARY_NOMATCH)) { + static struct git_attr *attr_text; + struct git_attr_check check; + + if (!attr_text) + attr_text = git_attr("text"); + memset(&check, 0, sizeof(check)); + check.attr = attr_text; + return !git_check_attr(filename, 1, &check) && + ATTR_FALSE(check.value); + } + return 0; +} + static void *run(void *arg) { int hit = 0; @@ -173,6 +190,9 @@ static void *run(void *arg) if (!w) break; + if (skip_binary(opt, (const char *)w->source.identifier)) + continue; + opt->output_priv = w; hit |= grep_source(opt, &w->source); grep_source_clear_data(&w->source); @@ -381,6 +401,9 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int continue; if (!ce_path_match(ce, pathspec, NULL)) continue; + if (skip_binary(opt, ce->name)) + continue; + /* * If CE_VALID is on, we assume worktree file and its cache entry * are identical, even if worktree file has been modified, so use @@ -805,6 +828,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix) string_list_append(&path_list, show_in_pager); use_threads = 0; } + if ((opt.binary & GREP_BINARY_NOMATCH)) + use_threads = 0; if (!opt.pattern_list) die(_("no pattern given.")); @@ -874,6 +899,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix) if (len > 4 && is_dir_sep(pager[len - 5])) pager += len - 4; + if (opt.ignore_case && !strcmp("less", pager)) + string_list_append(&path_list, "-i"); + if (!strcmp("less", pager) || !strcmp("vi", pager)) { struct strbuf buf = STRBUF_INIT; strbuf_addf(&buf, "+/%s%s",