mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
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>
This commit is contained in:
parent
2d7f98bac7
commit
c8610a2e7e
|
@ -236,6 +236,8 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
|
||||||
!strcmp(ce->name, active_cache[nr]->name));
|
!strcmp(ce->name, active_cache[nr]->name));
|
||||||
nr--; /* compensate for loop control */
|
nr--; /* compensate for loop control */
|
||||||
}
|
}
|
||||||
|
if (hit && opt->status_only)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
free_grep_patterns(opt);
|
free_grep_patterns(opt);
|
||||||
return hit;
|
return hit;
|
||||||
|
@ -293,6 +295,8 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
|
||||||
hit |= grep_tree(opt, paths, &sub, tree_name, down);
|
hit |= grep_tree(opt, paths, &sub, tree_name, down);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
|
if (hit && opt->status_only)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
strbuf_release(&pathbuf);
|
strbuf_release(&pathbuf);
|
||||||
return hit;
|
return hit;
|
||||||
|
@ -329,8 +333,11 @@ static int grep_directory(struct grep_opt *opt, const char **paths)
|
||||||
setup_standard_excludes(&dir);
|
setup_standard_excludes(&dir);
|
||||||
|
|
||||||
fill_directory(&dir, paths);
|
fill_directory(&dir, paths);
|
||||||
for (i = 0; i < dir.nr; i++)
|
for (i = 0; i < dir.nr; i++) {
|
||||||
hit |= grep_file(opt, dir.entries[i]->name);
|
hit |= grep_file(opt, dir.entries[i]->name);
|
||||||
|
if (hit && opt->status_only)
|
||||||
|
break;
|
||||||
|
}
|
||||||
free_grep_patterns(opt);
|
free_grep_patterns(opt);
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
@ -505,6 +512,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||||
{ OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
|
{ OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
|
||||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
|
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
|
||||||
close_callback },
|
close_callback },
|
||||||
|
OPT_BOOLEAN('q', "quick", &opt.status_only,
|
||||||
|
"indicate hit with exit status without output"),
|
||||||
OPT_BOOLEAN(0, "all-match", &opt.all_match,
|
OPT_BOOLEAN(0, "all-match", &opt.all_match,
|
||||||
"show only matches from files that match all patterns"),
|
"show only matches from files that match all patterns"),
|
||||||
OPT_GROUP(""),
|
OPT_GROUP(""),
|
||||||
|
@ -628,8 +637,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||||
for (i = 0; i < list.nr; i++) {
|
for (i = 0; i < list.nr; i++) {
|
||||||
struct object *real_obj;
|
struct object *real_obj;
|
||||||
real_obj = deref_tag(list.objects[i].item, NULL, 0);
|
real_obj = deref_tag(list.objects[i].item, NULL, 0);
|
||||||
if (grep_object(&opt, paths, real_obj, list.objects[i].name))
|
if (grep_object(&opt, paths, real_obj, list.objects[i].name)) {
|
||||||
hit = 1;
|
hit = 1;
|
||||||
|
if (opt.status_only)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free_grep_patterns(&opt);
|
free_grep_patterns(&opt);
|
||||||
return !hit;
|
return !hit;
|
||||||
|
|
Loading…
Reference in a new issue