[PATCH v2] log: teach --invert-grep option

2015-01-12 Thread Christoph Junghans
"git log --grep=" shows only commits with messages that
match the given string, but sometimes it is useful to be able to
show only commits that do *not* have certain messages (e.g. "show
me ones that are not FIXUP commits").

Originally, we had the invert-grep flag in grep_opt, but because
"git grep --invert-grep" does not make sense except in conjunction
with "--files-with-matches", which is already covered by
"--files-without-matches", it was moved it to revisions structure.
To have the flag there expresses the function to the feature better.

When the newly inserted two tests run, the history would have commits
with messages "initial", "second", "third", "fourth", "fifth", "sixth"
and "Second", committed in this order.  The commits that does not match
either "th" or "Sec" is "second" and "initial". For the case insensitive
case only "initial" matches.

Signed-off-by: Christoph Junghans 
---
 Documentation/rev-list-options.txt |  4 
 contrib/completion/git-completion.bash |  2 +-
 gitk-git/gitk  |  1 +
 revision.c |  4 +++-
 revision.h |  2 ++
 t/t4202-log.sh | 15 +++
 6 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/Documentation/rev-list-options.txt 
b/Documentation/rev-list-options.txt
index afccfdc..6d4671f 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -66,6 +66,10 @@ if it is part of the log message.
Limit the commits output to ones that match all given `--grep`,
instead of ones that match at least one.
 
+--invert-grep::
+   Limit the commits output to ones with log message that do not
+   match the pattern specified with `--grep=`.
+
 -i::
 --regexp-ignore-case::
Match the regular expression limiting patterns without regard to letter
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index cd76579..aaeac50 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1425,7 +1425,7 @@ __git_log_gitk_options="
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
--author= --committer= --grep=
-   --all-match
+   --all-match --invert-grep
 "
 
 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 78358a7..5a78432 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -3977,6 +3977,7 @@ set known_view_options {
 {committer t15  .  "--committer=*"  {mc "Committer:"}}
 {loginfo   t15  .. "--grep=*"   {mc "Commit Message:"}}
 {allmatch  b.. "--all-match"{mc "Matches all Commit Info 
criteria"}}
+{igrep b.. "--invert-grep"  {mc "Matches none Commit Info 
criteria"}}
 {changes_l l+  {}   {mc "Changes to Files:"}}
 {pickaxe_s r0   .  {}   {mc "Fixed String"}}
 {pickaxe_t r1   .  "--pickaxe-regex"  {mc "Regular Expression"}}
diff --git a/revision.c b/revision.c
index 14e0e03..4d03338 100644
--- a/revision.c
+++ b/revision.c
@@ -2011,6 +2011,8 @@ static int handle_revision_opt(struct rev_info *revs, int 
argc, const char **arg
grep_set_pattern_type_option(GREP_PATTERN_TYPE_PCRE, 
&revs->grep_filter);
} else if (!strcmp(arg, "--all-match")) {
revs->grep_filter.all_match = 1;
+   } else if (!strcmp(arg, "--invert-grep")) {
+   revs->invert_grep = 1;
} else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
if (strcmp(optarg, "none"))
git_log_output_encoding = xstrdup(optarg);
@@ -2909,7 +2911,7 @@ static int commit_match(struct commit *commit, struct 
rev_info *opt)
 (char *)message, strlen(message));
strbuf_release(&buf);
unuse_commit_buffer(commit, message);
-   return retval;
+   return opt->invert_grep ? !retval : retval;
 }
 
 static inline int want_ancestry(const struct rev_info *revs)
diff --git a/revision.h b/revision.h
index 9cb5adc..bc27098 100644
--- a/revision.h
+++ b/revision.h
@@ -168,6 +168,8 @@ struct rev_info {
 
/* Filter by commit log message */
struct grep_opt grep_filter;
+   /* Negate the match of grep_filter */
+   int invert_grep;
 
/* Display history graph */
struct git_graph *graph;
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 99ab7ca..5f2b290 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -212,

[PATCH v2] git-log: added --none-match option

2015-01-11 Thread Christoph Junghans
Implements a none match for git log, which is useful from time to
time to e.g. filter FIXUP message out of git log.

Internally, the bol 'all_match' was changed to an int 'all_or_none'
taken the values 0, GREP_ALL_MATCH or GREP_NONE_MATCH.

For git grep a similar functionality can achieved by the existing
--files-without-match option.

Signed-off-by: Christoph Junghans 
---
 Documentation/rev-list-options.txt |  4 
 builtin/grep.c |  5 +++--
 contrib/completion/git-completion.bash |  2 +-
 gitk-git/gitk  |  1 +
 grep.c | 24 ++--
 grep.h |  4 +++-
 revision.c |  4 +++-
 7 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/Documentation/rev-list-options.txt 
b/Documentation/rev-list-options.txt
index afccfdc..08e4ed8 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -66,6 +66,10 @@ if it is part of the log message.
Limit the commits output to ones that match all given `--grep`,
instead of ones that match at least one.
 
+--none-match::
+   Limit the commits output to ones that do not match any of the 
+   given `--grep`, instead of ones that match at least one.
+
 -i::
 --regexp-ignore-case::
Match the regular expression limiting patterns without regard to letter
diff --git a/builtin/grep.c b/builtin/grep.c
index 4063882..1ec8ce1 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -727,8 +727,9 @@ int cmd_grep(int argc, const char **argv, const char 
*prefix)
  close_callback },
OPT__QUIET(&opt.status_only,
   N_("indicate hit with exit status without output")),
-   OPT_BOOL(0, "all-match", &opt.all_match,
-   N_("show only matches from files that match all 
patterns")),
+   OPT_SET_INT(0, "all-match", &opt.all_or_none,
+   N_("show only matches from files that match all 
patterns"),
+   GREP_ALL_MATCH),
{ OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
  N_("show parse tree for grep expression"),
  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index cd76579..47ed970 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1425,7 +1425,7 @@ __git_log_gitk_options="
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
--author= --committer= --grep=
-   --all-match
+   --all-match --none-match
 "
 
 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 78358a7..c67674f 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -3977,6 +3977,7 @@ set known_view_options {
 {committer t15  .  "--committer=*"  {mc "Committer:"}}
 {loginfo   t15  .. "--grep=*"   {mc "Commit Message:"}}
 {allmatch  b.. "--all-match"{mc "Matches all Commit Info 
criteria"}}
+{nonematch b.. "--none-match"   {mc "Matches none Commit Info 
criteria"}}
 {changes_l l+  {}   {mc "Changes to Files:"}}
 {pickaxe_s r0   .  {}   {mc "Fixed String"}}
 {pickaxe_t r1   .  "--pickaxe-regex"  {mc "Regular Expression"}}
diff --git a/grep.c b/grep.c
index 6e085f8..f6eb044 100644
--- a/grep.c
+++ b/grep.c
@@ -609,8 +609,14 @@ static void dump_grep_expression(struct grep_opt *opt)
 {
struct grep_expr *x = opt->pattern_expression;
 
-   if (opt->all_match)
+   switch (opt->all_or_none) {
+   case GREP_ALL_MATCH:
fprintf(stderr, "[all-match]\n");
+   case GREP_NONE_MATCH:
+   fprintf(stderr, "[none-match]\n");
+   default:
+   break;
+   }
dump_grep_expression_1(x, 0);
fflush(NULL);
 }
@@ -713,7 +719,7 @@ static void compile_grep_patterns_real(struct grep_opt *opt)
}
}
 
-   if (opt->all_match || header_expr)
+   if ((opt->all_or_none == GREP_ALL_MATCH) || header_expr)
opt->extended = 1;
else if (!opt->extended && !opt->debug)
return;
@@ -729,13 +735,13 @@ static void compile_grep_patterns_real(struct grep_opt 
*opt)
 
if (!opt->pattern_expression)
opt->pattern_expression = header_expr;
-   else if (opt->all_match)
+   else if (opt->all_or_none == GREP_ALL_MATCH)
opt->pat

Re: [PATCH] git-log: added --none-match option

2015-01-09 Thread Christoph Junghans
2015-01-06 16:02 GMT-07:00 Junio C Hamano :
> Christoph Junghans  writes:
>
>> Implements a inverted match for "git log", like in the case of
>> "git grep -v", which is useful from time to time to e.g. filter
>> FIXUP message out of "git log".
>>
>> Internally, a new bol 'none_match' has been introduces as
>> revs->grep_filter.invert inverts the match line-wise, which cannot
>> work as i.e. empty line always not match the pattern given.
>>
>> Signed-off-by: Christoph Junghans 
>> ---
>
> The patch itself looks like a good start, except that the above
> description no longer matches the implementation.
>
> I further suspect it would be better to rename all_match to
> all_or_none and then you can lose the "these two are mutually
> incompatible" check that is placed together with a wrong existing
> comment.  I also notice that you forgot to update the "git grep"
> where the original "--all-match" came from.
That was on purpose. I am not quite sure what would be the point of
"showing only matches from files that match no patterns" (option
description from your patch below).
If a file matches none of the patterns, what matches are there to show?

The only useful thing I could image is using it in conjunction with
--files-with-matches, but that is what --files-without-match is for.

>
> A partial fix-up may start like this on top of your version.  By
> renaming the variable used in the existing code, the compiler will
> remind you that there are a few more places that your patch did not
> touch that does something special for --all-match, which are a good
> candidates you need to think if doing something similarly special
> for the --none-match case is necessary.
>
> Thanks.
>
> diff --git a/builtin/grep.c b/builtin/grep.c
> index 4063882..9ba4254 100644
> --- a/builtin/grep.c
> +++ b/builtin/grep.c
> @@ -727,8 +727,12 @@ int cmd_grep(int argc, const char **argv, const char 
> *prefix)
>   close_callback },
> OPT__QUIET(&opt.status_only,
>N_("indicate hit with exit status without 
> output")),
> -   OPT_BOOL(0, "all-match", &opt.all_match,
> -   N_("show only matches from files that match all 
> patterns")),
> +   OPT_SET_INT(0, "all-match", &opt.all_or_none,
> +   N_("show only matches from files that match all 
> patterns"),
> +   GREP_ALL_MATCH),
> +   OPT_SET_INT(0, "none-match", &opt.all_or_none,
> +   N_("show only matches from files that match no 
> patterns"),
> +   GREP_NONE_MATCH),
> { OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
>   N_("show parse tree for grep expression"),
>   PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },
> diff --git a/grep.c b/grep.c
> index f486ee5..1ff5dea 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -1622,14 +1622,18 @@ static int chk_hit_marker(struct grep_expr *x)
>
>  int grep_source(struct grep_opt *opt, struct grep_source *gs)
>  {
> -   if(opt->none_match)
> -   return !grep_source_1(opt, gs, 0);
> /*
>  * we do not have to do the two-pass grep when we do not check
> -* buffer-wide "all-match".
> +* buffer-wide "all-match" or "none-match".
>  */
> -   if (!opt->all_match)
> +   switch (opt->all_or_none) {
> +   case GREP_ALL_MATCH:
> return grep_source_1(opt, gs, 0);
> +   case GREP_NONE_MATCH:
> +   return !grep_source_1(opt, gs, 0);
> +   default:
> +   break;
> +   }
>
> /* Otherwise the toplevel "or" terms hit a bit differently.
>  * We first clear hit markers from them.
> diff --git a/grep.h b/grep.h
> index 8e50c95..2cdabf2 100644
> --- a/grep.h
> +++ b/grep.h
> @@ -101,8 +101,9 @@ struct grep_opt {
> int count;
> int word_regexp;
> int fixed;
> -   int all_match;
> -   int none_match;
> +#define GREP_ALL_MATCH 1
> +#define GREP_NONE_MATCH 2
> +   int all_or_none;
> int debug;
>  #define GREP_BINARY_DEFAULT0
>  #define GREP_BINARY_NOMATCH1
> diff --git a/revision.c b/revision.c
> index d43779e..b955848 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -2010,9 +2010,9 @@ static int handle_revision_opt(struct rev_info *revs, 
> int ar

[PATCH] git-log: added --none-match option

2015-01-03 Thread Christoph Junghans
Implements a inverted match for "git log", like in the case of
"git grep -v", which is useful from time to time to e.g. filter
FIXUP message out of "git log".

Internally, a new bol 'none_match' has been introduces as
revs->grep_filter.invert inverts the match line-wise, which cannot
work as i.e. empty line always not match the pattern given.

Signed-off-by: Christoph Junghans 
---
 Documentation/rev-list-options.txt | 4 
 contrib/completion/git-completion.bash | 2 +-
 grep.c | 2 ++
 grep.h | 1 +
 revision.c | 4 
 5 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/Documentation/rev-list-options.txt 
b/Documentation/rev-list-options.txt
index afccfdc..08e4ed8 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -66,6 +66,10 @@ if it is part of the log message.
Limit the commits output to ones that match all given `--grep`,
instead of ones that match at least one.
 
+--none-match::
+   Limit the commits output to ones that do not match any of the 
+   given `--grep`, instead of ones that match at least one.
+
 -i::
 --regexp-ignore-case::
Match the regular expression limiting patterns without regard to letter
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 23988ec..b0720e9 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1425,7 +1425,7 @@ __git_log_gitk_options="
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
--author= --committer= --grep=
-   --all-match
+   --all-match --none-match
 "
 
 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
diff --git a/grep.c b/grep.c
index 6e085f8..eadf8d9 100644
--- a/grep.c
+++ b/grep.c
@@ -1622,6 +1622,8 @@ static int chk_hit_marker(struct grep_expr *x)
 
 int grep_source(struct grep_opt *opt, struct grep_source *gs)
 {
+   if(opt->none_match)
+   return !grep_source_1(opt, gs, 0);  
/*
 * we do not have to do the two-pass grep when we do not check
 * buffer-wide "all-match".
diff --git a/grep.h b/grep.h
index 95f197a..8e50c95 100644
--- a/grep.h
+++ b/grep.h
@@ -102,6 +102,7 @@ struct grep_opt {
int word_regexp;
int fixed;
int all_match;
+   int none_match;
int debug;
 #define GREP_BINARY_DEFAULT0
 #define GREP_BINARY_NOMATCH1
diff --git a/revision.c b/revision.c
index 75dda92..d43779e 100644
--- a/revision.c
+++ b/revision.c
@@ -2011,6 +2011,8 @@ static int handle_revision_opt(struct rev_info *revs, int 
argc, const char **arg
grep_set_pattern_type_option(GREP_PATTERN_TYPE_PCRE, 
&revs->grep_filter);
} else if (!strcmp(arg, "--all-match")) {
revs->grep_filter.all_match = 1;
+   } else if (!strcmp(arg, "--none-match")) {
+   revs->grep_filter.none_match = 1;
} else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
if (strcmp(optarg, "none"))
git_log_output_encoding = xstrdup(optarg);
@@ -2333,6 +2335,8 @@ int setup_revisions(int argc, const char **argv, struct 
rev_info *revs, struct s
die("cannot combine --walk-reflogs with --graph");
if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
die("cannot use --grep-reflog without --walk-reflogs");
+   if (revs->grep_filter.all_match && revs->grep_filter.none_match)
+   die("cannot combine --all-match with --none-match");
 
return left;
 }
-- 
2.0.5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] git-log: added --invert-grep option

2014-12-23 Thread Christoph Junghans
Ok, I drafted a first version of the suggest --grep-begin ...
--grep-end syntax.

However, I could not find a good ways to invert the match on a commit
basis instead of the normal line-wise version. Any suggestions?


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] git-log: added --grep-begin .. --grep-end syntax

2014-12-23 Thread Christoph Junghans
This is useful to specify more complicated pattern as with '--grep'.

Signed-off-by: Christoph Junghans 
---
 builtin/grep.c | 73 +-
 grep.c | 62 +
 grep.h | 10 
 revision.c | 56 
 4 files changed, 134 insertions(+), 67 deletions(-)

diff --git a/builtin/grep.c b/builtin/grep.c
index 4063882..0127fa0 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -551,67 +551,6 @@ static int context_callback(const struct option *opt, 
const char *arg,
return 0;
 }
 
-static int file_callback(const struct option *opt, const char *arg, int unset)
-{
-   struct grep_opt *grep_opt = opt->value;
-   int from_stdin = !strcmp(arg, "-");
-   FILE *patterns;
-   int lno = 0;
-   struct strbuf sb = STRBUF_INIT;
-
-   patterns = from_stdin ? stdin : fopen(arg, "r");
-   if (!patterns)
-   die_errno(_("cannot open '%s'"), arg);
-   while (strbuf_getline(&sb, patterns, '\n') == 0) {
-   /* ignore empty line like grep does */
-   if (sb.len == 0)
-   continue;
-
-   append_grep_pat(grep_opt, sb.buf, sb.len, arg, ++lno,
-   GREP_PATTERN);
-   }
-   if (!from_stdin)
-   fclose(patterns);
-   strbuf_release(&sb);
-   return 0;
-}
-
-static int not_callback(const struct option *opt, const char *arg, int unset)
-{
-   struct grep_opt *grep_opt = opt->value;
-   append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
-   return 0;
-}
-
-static int and_callback(const struct option *opt, const char *arg, int unset)
-{
-   struct grep_opt *grep_opt = opt->value;
-   append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
-   return 0;
-}
-
-static int open_callback(const struct option *opt, const char *arg, int unset)
-{
-   struct grep_opt *grep_opt = opt->value;
-   append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
-   return 0;
-}
-
-static int close_callback(const struct option *opt, const char *arg, int unset)
-{
-   struct grep_opt *grep_opt = opt->value;
-   append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
-   return 0;
-}
-
-static int pattern_callback(const struct option *opt, const char *arg,
-   int unset)
-{
-   struct grep_opt *grep_opt = opt->value;
-   append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
-   return 0;
-}
-
 static int help_callback(const struct option *opt, const char *arg, int unset)
 {
return -1;
@@ -710,21 +649,21 @@ int cmd_grep(int argc, const char **argv, const char 
*prefix)
N_("show the surrounding function")),
OPT_GROUP(""),
OPT_CALLBACK('f', NULL, &opt, N_("file"),
-   N_("read patterns from file"), file_callback),
+   N_("read patterns from file"), grep_file_callback),
{ OPTION_CALLBACK, 'e', NULL, &opt, N_("pattern"),
-   N_("match "), PARSE_OPT_NONEG, 
pattern_callback },
+   N_("match "), PARSE_OPT_NONEG, 
grep_pattern_callback },
{ OPTION_CALLBACK, 0, "and", &opt, NULL,
  N_("combine patterns specified with -e"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, grep_and_callback },
OPT_BOOL(0, "or", &dummy, ""),
{ OPTION_CALLBACK, 0, "not", &opt, NULL, "",
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, grep_not_callback },
{ OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
- open_callback },
+ grep_open_callback },
{ OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
- close_callback },
+ grep_close_callback },
OPT__QUIET(&opt.status_only,
   N_("indicate hit with exit status without output")),
OPT_BOOL(0, "all-match", &opt.all_match,
diff --git a/grep.c b/grep.c
index 6e085f8..0c9a977 100644
--- a/grep.c
+++ b/grep.c

[PATCH] git-log: added --invert-grep option

2014-12-18 Thread Christoph Junghans
Implements a inverted match for "git log", like in the case of
"git grep -v", which is useful from time to time to e.g. filter
FIXUP message out of "git log".

Internally, a new bol 'global_invert' has been introduces as
revs->grep_filter.invert inverts the match line-wise, which cannot
work as i.e. empty line always not match the pattern given.

Signed-off-by: Christoph Junghans 
---
 Documentation/rev-list-options.txt | 4 
 contrib/completion/git-completion.bash | 2 +-
 grep.h | 3 ++-
 revision.c | 4 +++-
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/Documentation/rev-list-options.txt 
b/Documentation/rev-list-options.txt
index afccfdc..6d4671f 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -66,6 +66,10 @@ if it is part of the log message.
Limit the commits output to ones that match all given `--grep`,
instead of ones that match at least one.
 
+--invert-grep::
+   Limit the commits output to ones with log message that do not
+   match the pattern specified with `--grep=`.
+
 -i::
 --regexp-ignore-case::
Match the regular expression limiting patterns without regard to letter
diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 2fece98..914c317 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1425,7 +1425,7 @@ __git_log_gitk_options="
 # Options that go well for log and shortlog (not gitk)
 __git_log_shortlog_options="
--author= --committer= --grep=
-   --all-match
+   --all-match --invert-grep
 "
 
 __git_log_pretty_formats="oneline short medium full fuller email raw format:"
diff --git a/grep.h b/grep.h
index 95f197a..c137103 100644
--- a/grep.h
+++ b/grep.h
@@ -93,7 +93,8 @@ struct grep_opt {
int prefix_length;
regex_t regexp;
int linenum;
-   int invert;
+   int invert; /** line-wise invert match */
+   int global_invert; /** final global invert match */
int ignore_case;
int status_only;
int name_only;
diff --git a/revision.c b/revision.c
index 75dda92..c8d4c49 100644
--- a/revision.c
+++ b/revision.c
@@ -2011,6 +2011,8 @@ static int handle_revision_opt(struct rev_info *revs, int 
argc, const char **arg
grep_set_pattern_type_option(GREP_PATTERN_TYPE_PCRE, 
&revs->grep_filter);
} else if (!strcmp(arg, "--all-match")) {
revs->grep_filter.all_match = 1;
+   } else if (!strcmp(arg, "--invert-grep")) {
+   revs->grep_filter.global_invert = 1;
} else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
if (strcmp(optarg, "none"))
git_log_output_encoding = xstrdup(optarg);
@@ -2909,7 +2911,7 @@ static int commit_match(struct commit *commit, struct 
rev_info *opt)
 (char *)message, strlen(message));
strbuf_release(&buf);
unuse_commit_buffer(commit, message);
-   return retval;
+   return opt->grep_filter.global_invert ? !retval : retval;
 }
 
 static inline int want_ancestry(const struct rev_info *revs)
-- 
2.0.4

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html