1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-06-09 15:16:11 +02:00

Merge branch 'rs/log-invert-grep-with-headers'

"git log --invert-grep --author=<name>" used to exclude commits
written by the given author, but now "--invert-grep" only affects
the matches made by the "--grep=<pattern>" option.

* rs/log-invert-grep-with-headers:
  log: let --invert-grep only invert --grep
This commit is contained in:
Junio C Hamano 2022-01-05 14:01:30 -08:00
commit 2043ce828e
5 changed files with 42 additions and 7 deletions

22
grep.c
View File

@ -699,6 +699,14 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
return compile_pattern_or(list);
}
static struct grep_expr *grep_not_expr(struct grep_expr *expr)
{
struct grep_expr *z = xcalloc(1, sizeof(*z));
z->node = GREP_NODE_NOT;
z->u.unary = expr;
return z;
}
static struct grep_expr *grep_true_expr(void)
{
struct grep_expr *z = xcalloc(1, sizeof(*z));
@ -797,7 +805,7 @@ void compile_grep_patterns(struct grep_opt *opt)
}
}
if (opt->all_match || header_expr)
if (opt->all_match || opt->no_body_match || header_expr)
opt->extended = 1;
else if (!opt->extended)
return;
@ -808,6 +816,9 @@ void compile_grep_patterns(struct grep_opt *opt)
if (p)
die("incomplete pattern expression: %s", p->pattern);
if (opt->no_body_match && opt->pattern_expression)
opt->pattern_expression = grep_not_expr(opt->pattern_expression);
if (!header_expr)
return;
@ -1057,6 +1068,8 @@ static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x,
if (h && (*col < 0 || tmp.rm_so < *col))
*col = tmp.rm_so;
}
if (x->u.atom->token == GREP_PATTERN_BODY)
opt->body_hit |= h;
break;
case GREP_NODE_NOT:
/*
@ -1825,16 +1838,19 @@ int grep_source(struct grep_opt *opt, struct grep_source *gs)
* we do not have to do the two-pass grep when we do not check
* buffer-wide "all-match".
*/
if (!opt->all_match)
if (!opt->all_match && !opt->no_body_match)
return grep_source_1(opt, gs, 0);
/* Otherwise the toplevel "or" terms hit a bit differently.
* We first clear hit markers from them.
*/
clr_hit_marker(opt->pattern_expression);
opt->body_hit = 0;
grep_source_1(opt, gs, 1);
if (!chk_hit_marker(opt->pattern_expression))
if (opt->all_match && !chk_hit_marker(opt->pattern_expression))
return 0;
if (opt->no_body_match && opt->body_hit)
return 0;
return grep_source_1(opt, gs, 0);

2
grep.h
View File

@ -148,6 +148,8 @@ struct grep_opt {
int word_regexp;
int fixed;
int all_match;
int no_body_match;
int body_hit;
#define GREP_BINARY_DEFAULT 0
#define GREP_BINARY_NOMATCH 1
#define GREP_BINARY_TEXT 2

View File

@ -2498,7 +2498,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!strcmp(arg, "--all-match")) {
revs->grep_filter.all_match = 1;
} else if (!strcmp(arg, "--invert-grep")) {
revs->invert_grep = 1;
revs->grep_filter.no_body_match = 1;
} else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
if (strcmp(optarg, "none"))
git_log_output_encoding = xstrdup(optarg);
@ -3783,7 +3783,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 opt->invert_grep ? !retval : retval;
return retval;
}
static inline int want_ancestry(const struct rev_info *revs)

View File

@ -246,8 +246,6 @@ 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;

View File

@ -2090,4 +2090,23 @@ test_expect_success 'log --end-of-options' '
test_cmp expect actual
'
test_expect_success 'set up commits with different authors' '
git checkout --orphan authors &&
test_commit --author "Jim <jim@example.com>" jim_1 &&
test_commit --author "Val <val@example.com>" val_1 &&
test_commit --author "Val <val@example.com>" val_2 &&
test_commit --author "Jim <jim@example.com>" jim_2 &&
test_commit --author "Val <val@example.com>" val_3 &&
test_commit --author "Jim <jim@example.com>" jim_3
'
test_expect_success 'log --invert-grep --grep --author' '
cat >expect <<-\EOF &&
val_3
val_1
EOF
git log --format=%s --author=Val --grep 2 --invert-grep >actual &&
test_cmp expect actual
'
test_done