X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=builtin-grep.c;h=5fac5701e6ccebdbe83b00d2e2df19343d3aea0e;hb=7a97de4e19757b5576f32ce67d90cb792dbb893b;hp=36512d8a17abccb67654b5bcfcd74a441b3e4586;hpb=518920b764ee9150781e68217181b24d0712748e;p=git.git diff --git a/builtin-grep.c b/builtin-grep.c index 36512d8a..5fac5701 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -459,6 +459,8 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) push_arg("-n"); if (opt->regflags & REG_EXTENDED) push_arg("-E"); + if (opt->regflags & REG_ICASE) + push_arg("-i"); if (opt->word_regexp) push_arg("-w"); if (opt->name_only) @@ -503,22 +505,34 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached) push_arg(p->pattern); } - if (NO_H_OPTION_IN_GREP) + /* + * To make sure we get the header printed out when we want it, + * add /dev/null to the paths to grep. This is unnecessary + * (and wrong) with "-l" or "-L", which always print out the + * name anyway. + * + * GNU grep has "-H", but this is portable. + */ + if (!opt->name_only && !opt->unmatch_name_only) push_arg("/dev/null"); - else { - push_arg("-H"); - push_arg("--"); - } hit = 0; argc = nr; for (i = 0; i < active_nr; i++) { struct cache_entry *ce = active_cache[i]; + char *name; if (ce_stage(ce) || !S_ISREG(ntohl(ce->ce_mode))) continue; if (!pathspec_matches(paths, ce->name)) continue; - argv[argc++] = ce->name; + name = ce->name; + if (name[0] == '-') { + int len = ce_namelen(ce); + name = xmalloc(len + 3); + memcpy(name, "./", 2); + memcpy(name + 2, ce->name, len + 1); + } + argv[argc++] = name; if (argc < MAXARGS) continue; hit += exec_grep(argc, argv); @@ -540,19 +554,8 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached) * Use the external "grep" command for the case where * we grep through the checked-out files. It tends to * be a lot more optimized - * - * Some grep implementations do not understand -H nor -- - * but /dev/null can be used as a substitution in most - * cases. - * - * However -L and -c would slightly misbehave (-L would - * list /dev/null as a hit, and -c would report 0 hits - * from /dev/null); so do not use the external one on - * such platforms. */ - if (!cached && - (!NO_H_OPTION_IN_GREP || - (!opt->count && !opt->unmatch_name_only))) { + if (!cached) { hit = external_grep(opt, paths, cached); if (hit >= 0) return hit; @@ -577,11 +580,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths, struct tree_desc *tree, const char *tree_name, const char *base) { - unsigned mode; int len; int hit = 0; - const char *path; - const unsigned char *sha1; + struct name_entry entry; char *down; char *path_buf = xmalloc(PATH_MAX + strlen(tree_name) + 100); @@ -596,36 +597,32 @@ static int grep_tree(struct grep_opt *opt, const char **paths, } len = strlen(path_buf); - while (tree->size) { - int pathlen; - sha1 = tree_entry_extract(tree, &path, &mode); - pathlen = strlen(path); - strcpy(path_buf + len, path); + while (tree_entry(tree, &entry)) { + strcpy(path_buf + len, entry.path); - if (S_ISDIR(mode)) + if (S_ISDIR(entry.mode)) /* Match "abc/" against pathspec to * decide if we want to descend into "abc" * directory. */ - strcpy(path_buf + len + pathlen, "/"); + strcpy(path_buf + len + entry.pathlen, "/"); if (!pathspec_matches(paths, down)) ; - else if (S_ISREG(mode)) - hit |= grep_sha1(opt, sha1, path_buf); - else if (S_ISDIR(mode)) { + else if (S_ISREG(entry.mode)) + hit |= grep_sha1(opt, entry.sha1, path_buf); + else if (S_ISDIR(entry.mode)) { char type[20]; struct tree_desc sub; void *data; - data = read_sha1_file(sha1, type, &sub.size); + data = read_sha1_file(entry.sha1, type, &sub.size); if (!data) die("unable to read tree (%s)", - sha1_to_hex(sha1)); + sha1_to_hex(entry.sha1)); sub.buf = data; hit |= grep_tree(opt, paths, &sub, tree_name, down); free(data); } - update_tree_entry(tree); } return hit; }