[-z | --null]
[-c | --count] [--all-match] [-q | --quiet]
[--max-depth <depth>]
- [--color | --no-color]
+ [--color[=<when>] | --no-color]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-f <file>] [-e] <pattern>
- [--and|--or|--not|(|)|-e <pattern>...] [<tree>...]
- [--] [<path>...]
+ [--and|--or|--not|(|)|-e <pattern>...]
- [--cached | --no-index | <tree>...]
++ [ [--exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
+ [--] [<pathspec>...]
DESCRIPTION
-----------
OPTIONS
-------
--cached::
- Instead of searching in the working tree files, check
- the blobs registered in the index file.
+ Instead of searching tracked files in the working tree, search
+ blobs registered in the index file.
+
+--no-index::
- Search files in the current directory, not just those tracked by git.
++ Search files in the current directory that is not managed by git.
+
+ --untracked::
+ In addition to searching in the tracked files in the working
+ tree, search also in untracked files.
+
+ --no-exclude-standard::
+ Also search in ignored files by not honoring the `.gitignore`
+ mechanism. Only useful with `--untracked`.
+
+ --exclude-standard::
+ Do not pay attention to ignored files specified via the `.gitignore`
+ mechanism. Only useful when searching files in the current directory
+ with `--no-index`.
-a::
--text::
free(data);
return hit;
}
- die("unable to grep from object of type %s", typename(obj->type));
+ die(_("unable to grep from object of type %s"), typename(obj->type));
+}
+
+static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
+ const struct object_array *list)
+{
+ unsigned int i;
+ int hit = 0;
+ const unsigned int nr = list->nr;
+
+ for (i = 0; i < nr; i++) {
+ struct object *real_obj;
+ real_obj = deref_tag(list->objects[i].item, NULL, 0);
+ if (grep_object(opt, pathspec, real_obj, list->objects[i].name)) {
+ hit = 1;
+ if (opt->status_only)
+ break;
+ }
+ }
+ return hit;
}
- static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec)
-static int grep_directory(struct grep_opt *opt, const char **paths, int exc_std)
++static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
++ int exc_std)
{
struct dir_struct dir;
int i, hit = 0;
memset(&dir, 0, sizeof(dir));
- setup_standard_excludes(&dir);
+ if (exc_std)
+ setup_standard_excludes(&dir);
- fill_directory(&dir, paths);
+ fill_directory(&dir, pathspec->raw);
for (i = 0; i < dir.nr; i++) {
+ const char *name = dir.entries[i]->name;
+ int namelen = strlen(name);
+ if (!match_pathspec_depth(pathspec, name, namelen, 0, NULL))
+ continue;
hit |= grep_file(opt, dir.entries[i]->name);
if (hit && opt->status_only)
break;
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
- int cached = 0;
+ int cached = 0, untracked = 0, opt_exclude = -1;
int seen_dashdash = 0;
int external_grep_allowed__ignored;
+ const char *show_in_pager = NULL, *default_pager = "dummy";
struct grep_opt opt;
- struct object_array list = { 0, 0, NULL };
+ struct object_array list = OBJECT_ARRAY_INIT;
const char **paths = NULL;
+ struct pathspec pathspec;
+ struct string_list path_list = STRING_LIST_INIT_NODUP;
int i;
int dummy;
- int nongit = 0, use_index = 1;
+ int use_index = 1;
+ enum {
+ pattern_type_unspecified = 0,
+ pattern_type_bre,
+ pattern_type_ere,
+ pattern_type_fixed,
+ pattern_type_pcre,
+ };
+ int pattern_type = pattern_type_unspecified;
+
struct option options[] = {
OPT_BOOLEAN(0, "cached", &cached,
"search in index instead of in the work tree"),
verify_filename(prefix, argv[j]);
}
- if (i < argc)
- paths = get_pathspec(prefix, argv + i);
- else if (prefix) {
- paths = xcalloc(2, sizeof(const char *));
- paths[0] = prefix;
- paths[1] = NULL;
+ paths = get_pathspec(prefix, argv + i);
+ init_pathspec(&pathspec, paths);
+ pathspec.max_depth = opt.max_depth;
+ pathspec.recursive = 1;
+
+ if (show_in_pager && (cached || list.nr))
+ die(_("--open-files-in-pager only works on the worktree"));
+
+ if (show_in_pager && opt.pattern_list && !opt.pattern_list->next) {
+ const char *pager = path_list.items[0].string;
+ int len = strlen(pager);
+
+ if (len > 4 && is_dir_sep(pager[len - 5]))
+ pager += len - 4;
+
+ if (!strcmp("less", pager) || !strcmp("vi", pager)) {
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, "+/%s%s",
+ strcmp("less", pager) ? "" : "*",
+ opt.pattern_list->pattern);
+ string_list_append(&path_list, buf.buf);
+ strbuf_detach(&buf, NULL);
+ }
}
- die("--cached or --untracked cannot be used with --no-index.");
+ if (!show_in_pager)
+ setup_pager();
+
+ if (!use_index && (untracked || cached))
++ die(_("--cached or --untracked cannot be used with --no-index."));
- if (!use_index) {
- if (cached)
- die(_("--cached cannot be used with --no-index."));
+ if (!use_index || untracked) {
- int hit;
+ int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
if (list.nr)
- die(_("--no-index cannot be used with revs."));
- hit = grep_directory(&opt, &pathspec);
- die("--no-index or --untracked cannot be used with revs.");
- hit = grep_directory(&opt, paths, use_exclude);
- if (use_threads)
- hit |= wait_all();
- return !hit;
- }
-
- if (0 <= opt_exclude)
- die("--exclude or --no-exclude cannot be used for tracked contents.");
-
- if (!list.nr) {
- int hit;
++ die(_("--no-index or --untracked cannot be used with revs."));
++ hit = grep_directory(&opt, &pathspec, use_exclude);
++ } else if (0 <= opt_exclude) {
++ die(_("--exclude or --no-exclude cannot be used for tracked contents."));
+ } else if (!list.nr) {
if (!cached)
setup_work_tree();