Skip to content

Commit

Permalink
log --grep/--author: honor --all-match honored for multiple --grep pa…
Browse files Browse the repository at this point in the history
…tterns

When we have both header expression (which has to be an OR node by
construction) and a pattern expression (which could be anything), we
create a new top-level OR node to bind them together, and the
resulting expression structure looks like this:

             OR
        /          \
       /            \
   pattern            OR
     / \           /     \
    .....    committer    OR
                         /   \
                     author   TRUE

The three elements on the top-level backbone that are 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 the "pattern" part of the subtree is an OR, and that node is
inspected by "all-match".

The result ends up ignoring the "--all-match" given from the command
line.  A match on either side of the pattern is considered a match,
hence:

        git log --grep=A --grep=B --author=C --all-match

shows the same "authored by C and has either A or B" that is correct
only when run without "--all-match".

Fix this by turning the resulting expression around when "--all-match"
is in effect, like this:

              OR
          /        \
         /          \
        /              OR
    committer        /    \
                 author    \
                           pattern

The set of nodes on the top-level backbone in the resulting
expression becomes "committer", "author", and the nodes that are on
the top-level backbone of the "pattern" subexpression.  This makes
the "all-match" logic inspect the same nodes in "pattern" as the
case without the author and/or the committer restriction, and makes
the earlier "log" example to show "authored by C and has A and has
B", which is what the command line expects.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Junio C Hamano committed Sep 14, 2012
1 parent 208f5aa commit 13e4fc7
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 13e4fc7

Please sign in to comment.