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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <gitster@xxxxxxxxx> 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" <surfingalbert@xxxxxxxxx> wrote:
>>
>> grep: Add the option '--exclude'
>>
>> Signed-off-by: Albert Yale <surfingalbert@xxxxxxxxx>
>> ---
>> 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@xxxxxxxxxxxxxxx
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]