Merge branch 'jc/maint-grep-untracked-exclude' into jc/grep-untracked-exclude
authorJunio C Hamano <gitster@pobox.com>
Wed, 5 Oct 2011 01:40:41 +0000 (18:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 5 Oct 2011 01:40:41 +0000 (18:40 -0700)
* jc/maint-grep-untracked-exclude:
  grep: teach --untracked and --exclude-standard options
  grep --no-index: don't use git standard exclusions
  grep: do not use --index in the short usage output

Conflicts:
Documentation/git-grep.txt
builtin/grep.c

1  2 
Documentation/git-grep.txt
builtin/grep.c
t/t7810-grep.sh

index e44a4988b7a7ed7100da6e2ba098d7fda17a2f83,6269007b9449aea8a762849b28a80561174e4438..15d6711d46754e9659561b4372b46ec3c6654d6b
@@@ -19,12 -18,11 +19,12 @@@ SYNOPSI
           [-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
  -----------
@@@ -45,11 -33,21 +45,24 @@@ grep.extendedRegexp:
  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::
diff --cc builtin/grep.c
index 1c359c2671536287d97f2049b27a390d33b51e88,2da6bc61b66eea3594b3d0321de4a39cc3f49f8f..5e6d3c335224ce5acb38c9aea8bee30b04ea09e2
@@@ -615,42 -643,20 +615,44 @@@ static int grep_object(struct grep_opt 
                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;
@@@ -750,27 -751,15 +752,27 @@@ static int help_callback(const struct o
  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();
  
diff --cc t/t7810-grep.sh
index 0d600163c8284a318fbd21f3a00dd7853b2f8956,bf7877d93051eddf96da3e4cb7ebc27a760ba910..81263b78516cbe2949ad7e426a5e44af188cccdd
@@@ -583,9 -484,13 +599,13 @@@ test_expect_success 'inside git reposit
        {
                echo file1:hello &&
                echo sub/file2:world
+       } >is/expect.unignored &&
+       {
+               echo ".gitignore:.*o*" &&
+               cat is/expect.unignored
        } >is/expect.full &&
        : >is/expect.empty &&
 -      echo file2:world >is/expect.sub
 +      echo file2:world >is/expect.sub &&
        (
                cd is/git &&
                git init &&