Thread (1 message) 1 message, 1 author, 2016-06-15

Re: [PATCH/RFC] grep: Add the option '--exclude'

From: Albert Yale <hidden>
Date: 2016-06-15 22:52:52

I think you're correct. That would be a better way to implement this.

I'll look into it this weekend.

Albert Yale

On Fri, Jan 27, 2012 at 9:19 PM, Junio C Hamano [off-list ref] wrote:
I'd prefer to see this done not by introducing a separate pathspec, but
instead by adding exclusion-related fields to struct pathspec. That way, the
existing callsites to  match_pathspec() do not have to change, and only the
program start-up needs to learn to stuff these negative pathspecs, no?

On Jan 27, 2012 6:06 PM, "Albert Yale" [off-list ref] wrote:
quoted
grep: Add the option '--exclude'

Signed-off-by: Albert Yale <redacted>
---
This is a work-in-progress. It's functional,
but it hasn't been thoroughly tested.

I'd like some feedback. Particularly for
init_pathspec_string_list() in dir.c.

Thank you,

Albert Yale

 Documentation/git-grep.txt |    7 ++++++
 builtin/grep.c             |   50
++++++++++++++++++++++++++++++++++++-------
 cache.h                    |    1 +
 dir.c                      |   32 ++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 6a8b1e3..8cbb161 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -22,6 +22,7 @@ SYNOPSIS
          [--color[=<when>] | --no-color]
          [-A <post-context>] [-B <pre-context>] [-C <context>]
          [-f <file>] [-e] <pattern>
+          [-x <pattern>|--exclude=<pattern>]
          [--and|--or|--not|(|)|-e <pattern>...]
          [ [--exclude-standard] [--cached | --no-index | --untracked] |
<tree>...]
          [--] [<pathspec>...]
@@ -124,6 +125,12 @@ OPTIONS
       Use fixed strings for patterns (don't interpret pattern
       as a regex).

+-x <pattern>::
+--exclude=<pattern>::
+       In addition to those found in .gitignore (per directory) and
+       $GIT_DIR/info/exclude, also consider these patterns to be in the
+       set of the ignore rules in effect.
+
 -n::
 --line-number::
       Prefix the line number to matching lines.
diff --git a/builtin/grep.c b/builtin/grep.c
index 9ce064a..106810f 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -518,7 +518,8 @@ static void run_pager(struct grep_opt *opt, const char
*prefix)
       free(argv);
 }

-static int grep_cache(struct grep_opt *opt, const struct pathspec
*pathspec, int cached)
+static int grep_cache(struct grep_opt *opt, const struct pathspec
*pathspec,
+                         int cached, const struct pathspec
*exclude_pathspec)
 {
       int hit = 0;
       int nr;
@@ -530,6 +531,9 @@ static int grep_cache(struct grep_opt *opt, const
struct pathspec *pathspec, int
                       continue;
               if (!match_pathspec_depth(pathspec, ce->name,
ce_namelen(ce), 0, NULL))
                       continue;
+               if (exclude_pathspec->nr &&
+                       match_pathspec_depth(exclude_pathspec, ce->name,
ce_namelen(ce), 0, NULL))
+                       continue;
               /*
                * If CE_VALID is on, we assume worktree file and its cache
entry
                * are identical, even if worktree file has been modified,
so use
@@ -639,16 +643,23 @@ static int grep_object(struct grep_opt *opt, const
struct pathspec *pathspec,
 }

 static int grep_objects(struct grep_opt *opt, const struct pathspec
*pathspec,
-                       const struct object_array *list)
+                       const struct object_array *list, const struct
pathspec *exclude_pathspec)
 {
       unsigned int i;
       int hit = 0;
       const unsigned int nr = list->nr;

       for (i = 0; i < nr; i++) {
+               const char *name = list->objects[i].name;
+               int namelen = strlen(name);
               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)) {
+
+               if (exclude_pathspec->nr &&
+                       match_pathspec_depth(exclude_pathspec, name,
namelen, 0, NULL))
+                       continue;
+
+               if (grep_object(opt, pathspec, real_obj, name)) {
                       hit = 1;
                       if (opt->status_only)
                               break;
@@ -658,7 +669,7 @@ static int grep_objects(struct grep_opt *opt, const
struct pathspec *pathspec,
 }

 static int grep_directory(struct grep_opt *opt, const struct pathspec
*pathspec,
-                         int exc_std)
+                         int exc_std, struct string_list *exclude_list)
 {
       struct dir_struct dir;
       int i, hit = 0;
@@ -667,6 +678,10 @@ static int grep_directory(struct grep_opt *opt, const
struct pathspec *pathspec,
       if (exc_std)
               setup_standard_excludes(&dir);

+       for (i = 0; i < exclude_list->nr; i++)
+               add_exclude(exclude_list->items[i].string, "", 0,
+                           &dir.exclude_list[EXC_CMDL]);
+
       fill_directory(&dir, pathspec->raw);
       for (i = 0; i < dir.nr; i++) {
               const char *name = dir.entries[i]->name;
@@ -764,6 +779,14 @@ static int pattern_callback(const struct option *opt,
const char *arg,
       return 0;
 }

+static int exclude_cb(const struct option *opt, const char *arg,
+                           int unset)
+{
+       struct string_list *exclude_list = opt->value;
+       string_list_append(exclude_list, arg);
+       return 0;
+}
+
 static int help_callback(const struct option *opt, const char *arg, int
unset)
 {
       return -1;
@@ -780,6 +803,7 @@ int cmd_grep(int argc, const char **argv, const char
*prefix)
       struct object_array list = OBJECT_ARRAY_INIT;
       const char **paths = NULL;
       struct pathspec pathspec;
+       struct pathspec exclude_pathspec;
       struct string_list path_list = STRING_LIST_INIT_NODUP;
       int i;
       int dummy;
@@ -792,7 +816,7 @@ int cmd_grep(int argc, const char **argv, const char
*prefix)
               pattern_type_pcre,
       };
       int pattern_type = pattern_type_unspecified;
-
+       struct string_list exclude_list = STRING_LIST_INIT_NODUP;
       struct option options[] = {
               OPT_BOOLEAN(0, "cached", &cached,
                       "search in index instead of in the work tree"),
@@ -872,6 +896,8 @@ int cmd_grep(int argc, const char **argv, const char
*prefix)
                       "read patterns from file", file_callback),
               { OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
                       "match <pattern>", PARSE_OPT_NONEG,
pattern_callback },
+               { OPTION_CALLBACK, 'x', "exclude", &exclude_list,
"pattern",
+                 "add <pattern> to ignore rules", PARSE_OPT_NONEG,
exclude_cb },
               { OPTION_CALLBACK, 0, "and", &opt, NULL,
                 "combine patterns specified with -e",
                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
@@ -1053,6 +1079,10 @@ int cmd_grep(int argc, const char **argv, const
char *prefix)
       pathspec.max_depth = opt.max_depth;
       pathspec.recursive = 1;

+       init_pathspec_string_list(&exclude_pathspec, &exclude_list);
+       exclude_pathspec.max_depth = opt.max_depth;
+       exclude_pathspec.recursive = 1;
+
       if (show_in_pager && (cached || list.nr))
               die(_("--open-files-in-pager only works on the worktree"));
@@ -1083,18 +1113,19 @@ int cmd_grep(int argc, const char **argv, const
char *prefix)
               int use_exclude = (opt_exclude < 0) ? use_index :
!!opt_exclude;
               if (list.nr)
                       die(_("--no-index or --untracked cannot be used
with revs."));
-               hit = grep_directory(&opt, &pathspec, use_exclude);
+               hit = grep_directory(&opt, &pathspec, use_exclude,
&exclude_list);
       } else if (0 <= opt_exclude) {
               die(_("--[no-]exclude-standard cannot be used for tracked
contents."));
       } else if (!list.nr) {
               if (!cached)
                       setup_work_tree();

-               hit = grep_cache(&opt, &pathspec, cached);
+               hit = grep_cache(&opt, &pathspec, cached,
&exclude_pathspec);
       } else {
               if (cached)
                       die(_("both --cached and trees are given."));
-               hit = grep_objects(&opt, &pathspec, &list);
+
+               hit = grep_objects(&opt, &pathspec, &list,
&exclude_pathspec);
       }

       if (use_threads)
@@ -1102,5 +1133,8 @@ int cmd_grep(int argc, const char **argv, const char
*prefix)
       if (hit && show_in_pager)
               run_pager(&opt, prefix);
       free_grep_patterns(&opt);
+       free_pathspec(&pathspec);
+       free_pathspec(&exclude_pathspec);
+       string_list_clear(&exclude_list, 0);
       return !hit;
 }
diff --git a/cache.h b/cache.h
index 10afd71..5c34ccb 100644
--- a/cache.h
+++ b/cache.h
@@ -536,6 +536,7 @@ struct pathspec {
 };

 extern int init_pathspec(struct pathspec *, const char **);
+extern int init_pathspec_string_list(struct pathspec *, struct
string_list *);
 extern void free_pathspec(struct pathspec *);
 extern int ce_path_match(const struct cache_entry *ce, const struct
pathspec *pathspec);
diff --git a/dir.c b/dir.c
index 0a78d00..65749cc 100644
--- a/dir.c
+++ b/dir.c
@@ -9,6 +9,8 @@
 #include "dir.h"
 #include "refs.h"

+#include "string-list.h"
+
 struct path_simplify {
       int len;
       const char *path;
@@ -1259,6 +1261,36 @@ static int pathspec_item_cmp(const void *a_, const
void *b_)
       return strcmp(a->match, b->match);
 }

+int init_pathspec_string_list(struct pathspec *pathspec, struct
string_list *path_list)
+{
+       int i;
+
+       memset(pathspec, 0, sizeof(*pathspec));
+       if (!path_list)
+               return 0;
+       pathspec->raw = 0; /* THIS IS PROBABLY BAD!!! */
+       pathspec->nr = path_list->nr;
+       if (!pathspec->nr)
+               return 0;
+
+       pathspec->items = xmalloc(sizeof(struct
pathspec_item)*pathspec->nr);
+       for (i = 0; i < pathspec->nr; i++) {
+               struct pathspec_item *item = pathspec->items+i;
+               const char *path = path_list->items[i].string;
+
+               item->match = path;
+               item->len = strlen(path);
+               item->use_wildcard = !no_wildcard(path);
+               if (item->use_wildcard)
+                       pathspec->has_wildcard = 1;
+       }
+
+       qsort(pathspec->items, pathspec->nr,
+             sizeof(struct pathspec_item), pathspec_item_cmp);
+
+       return 0;
+}
+
 int init_pathspec(struct pathspec *pathspec, const char **paths)
 {
       const char **p = paths;
--
1.7.8.3

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help