@matheusbsbs / matheus-bagliano / commits / c8610a2e7e
Fork 0

grep: expose "status-only" feature via -q

Teach "git grep" a new "-q" option to report the presense of a match via its exit status without showing any output, similar to how "grep -q" works. Internally "grep" engine already knew this "status-only" mode of operation because it needed to grep inside log message to filter commits when called from the "git log" machinery, and this patch only exposes it to the command line tool. A somewhat unfair benchmark in the Linux kernel directory shows a dramatic improvement: (with patch) $ time ../git.git/git grep -q linux HEAD ; echo $? real 0m0.030s user 0m0.004s sys 0m0.004s 0 (without patch) $ time git grep linux HEAD >/dev/null; echo $? real 0m4.432s user 0m4.272s sys 0m0.076s 0 This is "somewhat unfair" because I knew a file with such a string comes very early in the tree traversal (namely, ".gitignore"). Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jan 25, 2010 at 15:37 UTC c8610a2e7eca60a060f719f0aeb20f146e339de4
1 file changed +14 -2
builtin-grep.c
+14 -2
@@ -236,6 +236,8 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
236 !strcmp(ce->name, active_cache[nr]->name));
237 nr--; /* compensate for loop control */
238 }
239 + if (hit && opt->status_only)
240 + break;
241 }
242 free_grep_patterns(opt);
243 return hit;
@@ -293,6 +295,8 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
295 hit |= grep_tree(opt, paths, &sub, tree_name, down);
296 free(data);
297 }
298 + if (hit && opt->status_only)
299 + break;
300 }
301 strbuf_release(&pathbuf);
302 return hit;
@@ -329,8 +333,11 @@ static int grep_directory(struct grep_opt *opt, const char **paths)
333 setup_standard_excludes(&dir);
334
335 fill_directory(&dir, paths);
332 - for (i = 0; i < dir.nr; i++)
336 + for (i = 0; i < dir.nr; i++) {
337 hit |= grep_file(opt, dir.entries[i]->name);
338 + if (hit && opt->status_only)
339 + break;
340 + }
341 free_grep_patterns(opt);
342 return hit;
343 }
@@ -505,6 +512,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
512 { OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
513 PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
514 close_callback },
515 + OPT_BOOLEAN('q', "quick", &opt.status_only,
516 + "indicate hit with exit status without output"),
517 OPT_BOOLEAN(0, "all-match", &opt.all_match,
518 "show only matches from files that match all patterns"),
519 OPT_GROUP(""),
@@ -628,8 +637,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
637 for (i = 0; i < list.nr; i++) {
638 struct object *real_obj;
639 real_obj = deref_tag(list.objects[i].item, NULL, 0);
631 - if (grep_object(&opt, paths, real_obj, list.objects[i].name))
640 + if (grep_object(&opt, paths, real_obj, list.objects[i].name)) {
641 hit = 1;
642 + if (opt.status_only)
643 + break;
644 + }
645 }
646 free_grep_patterns(&opt);
647 return !hit;