[PATCHv3 04/11] log --grep/--author: honor --all-match honored for multiple --grep patterns
From: Michael J Gruber <hidden>
Date: 2016-06-15 22:54:45
Subsystem:
the rest · Maintainer:
Linus Torvalds
From: Junio C Hamano <redacted>
Earlier, when we have both header expression (which has to be an OR
node by construction) and a pattern expression (which could be
anything), we created a top-level OR node that looks like this to
bind them together:
OR
/ \
/ \
pattern OR
/ \ / \
..... committer OR
/ \
author TRUE
In other words, the three elements on the top-level backbone that
were inspected by the "all-match" logic are "pattern", "committer"
and "author". When there are more than one elements in the
"pattern", the top-level node of it is that OR, so that node is
inspected by "all-match", hence the result ends up ignoring the
"--all-match" given from the command line. A match on either side
of the pattern was considered a match, hence
git log --grep=A --grep=B --author=C --all-match
showed the same "authored by C and has either A or B" with or
without --all-match.
This patch turns the grep expression into this form:
OR
/ \
/ \
/ OR
committer / \
author \
pattern
when "--all-match" was given from the command line. This way, the
set of nodes on the top-level backbone in the resulting expression
consists of "committer", "author", and whatever nodes were on the
top-level backbone of the "pattern" expression. The "all-match"
logic inspects the same nodes in "pattern" as the case without the
author and/or the committer restriction.
Signed-off-by: Junio C Hamano <redacted>
Signed-off-by: Michael J Gruber <redacted>
---
grep.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/grep.c b/grep.c
index be15c47..925aa92 100644
--- a/grep.c
+++ b/grep.c@@ -476,6 +476,22 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt) return header_expr; } +static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y) +{ + struct grep_expr *z = x; + + while (x) { + assert(x->node == GREP_NODE_OR); + if (x->u.binary.right && + x->u.binary.right->node == GREP_NODE_TRUE) { + x->u.binary.right = y; + break; + } + x = x->u.binary.right; + } + return z; +} + static void compile_grep_patterns_real(struct grep_opt *opt) { struct grep_pat *p;
@@ -510,6 +526,9 @@ static void compile_grep_patterns_real(struct grep_opt *opt) if (!opt->pattern_expression) opt->pattern_expression = header_expr; + else if (opt->all_match) + opt->pattern_expression = grep_splice_or(header_expr, + opt->pattern_expression); else opt->pattern_expression = grep_or_expr(opt->pattern_expression, header_expr);
--
1.7.12.592.g41e7905