summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin-grep.c1
-rw-r--r--builtin-rev-list.c5
-rw-r--r--grep.c46
-rw-r--r--grep.h2
-rw-r--r--revision.c3
-rwxr-xr-xt/t7002-grep.sh10
6 files changed, 57 insertions, 10 deletions
diff --git a/builtin-grep.c b/builtin-grep.c
index 529461fb8f..d57c4d9bed 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -820,6 +820,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.relative = 1;
opt.pathname = 1;
opt.pattern_tail = &opt.pattern_list;
+ opt.header_tail = &opt.header_list;
opt.regflags = REG_NEWLINE;
opt.max_depth = -1;
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index cd97ded4d2..c53ad9fa08 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -371,8 +371,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
revs.diff)
usage(rev_list_usage);
- save_commit_buffer = revs.verbose_header ||
- revs.grep_filter.pattern_list;
+ save_commit_buffer = (revs.verbose_header ||
+ revs.grep_filter.pattern_list ||
+ revs.grep_filter.header_list);
if (bisect_list)
revs.limited = 1;
diff --git a/grep.c b/grep.c
index bdadf2c0cc..eee99f31f1 100644
--- a/grep.c
+++ b/grep.c
@@ -11,8 +11,8 @@ void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field fie
p->no = 0;
p->token = GREP_PATTERN_HEAD;
p->field = field;
- *opt->pattern_tail = p;
- opt->pattern_tail = &p->next;
+ *opt->header_tail = p;
+ opt->header_tail = &p->next;
p->next = NULL;
}
@@ -172,9 +172,26 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
void compile_grep_patterns(struct grep_opt *opt)
{
struct grep_pat *p;
-
- if (opt->all_match)
- opt->extended = 1;
+ struct grep_expr *header_expr = NULL;
+
+ if (opt->header_list) {
+ p = opt->header_list;
+ header_expr = compile_pattern_expr(&p);
+ if (p)
+ die("incomplete pattern expression: %s", p->pattern);
+ for (p = opt->header_list; p; p = p->next) {
+ switch (p->token) {
+ case GREP_PATTERN: /* atom */
+ case GREP_PATTERN_HEAD:
+ case GREP_PATTERN_BODY:
+ compile_regexp(p, opt);
+ break;
+ default:
+ opt->extended = 1;
+ break;
+ }
+ }
+ }
for (p = opt->pattern_list; p; p = p->next) {
switch (p->token) {
@@ -189,7 +206,9 @@ void compile_grep_patterns(struct grep_opt *opt)
}
}
- if (!opt->extended)
+ if (opt->all_match || header_expr)
+ opt->extended = 1;
+ else if (!opt->extended)
return;
/* Then bundle them up in an expression.
@@ -200,6 +219,21 @@ void compile_grep_patterns(struct grep_opt *opt)
opt->pattern_expression = compile_pattern_expr(&p);
if (p)
die("incomplete pattern expression: %s", p->pattern);
+
+ if (!header_expr)
+ return;
+
+ if (opt->pattern_expression) {
+ struct grep_expr *z;
+ z = xcalloc(1, sizeof(*z));
+ z->node = GREP_NODE_OR;
+ z->u.binary.left = opt->pattern_expression;
+ z->u.binary.right = header_expr;
+ opt->pattern_expression = z;
+ } else {
+ opt->pattern_expression = header_expr;
+ }
+ opt->all_match = 1;
}
static void free_pattern_expr(struct grep_expr *x)
diff --git a/grep.h b/grep.h
index 75370f60d7..e39e5146d8 100644
--- a/grep.h
+++ b/grep.h
@@ -59,6 +59,8 @@ struct grep_expr {
struct grep_opt {
struct grep_pat *pattern_list;
struct grep_pat **pattern_tail;
+ struct grep_pat *header_list;
+ struct grep_pat **header_tail;
struct grep_expr *pattern_expression;
const char *prefix;
int prefix_length;
diff --git a/revision.c b/revision.c
index 25fa14d93e..c84243d7bb 100644
--- a/revision.c
+++ b/revision.c
@@ -806,6 +806,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
revs->grep_filter.status_only = 1;
revs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);
+ revs->grep_filter.header_tail = &(revs->grep_filter.header_list);
revs->grep_filter.regflags = REG_NEWLINE;
diff_setup(&revs->diffopt);
@@ -1751,7 +1752,7 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
static int commit_match(struct commit *commit, struct rev_info *opt)
{
- if (!opt->grep_filter.pattern_list)
+ if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
return 1;
return grep_buffer(&opt->grep_filter,
NULL, /* we say nothing, not even filename */
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 76c5e091b7..6baa4461f7 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -357,7 +357,7 @@ test_expect_success 'log grep (4)' '
'
test_expect_success 'log grep (5)' '
- git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
+ git log --author=Thor -F --pretty=tformat:%s >actual &&
( echo third ; echo initial ) >expect &&
test_cmp expect actual
'
@@ -368,6 +368,14 @@ test_expect_success 'log grep (6)' '
test_cmp expect actual
'
+test_expect_success 'log --grep --author implicitly uses all-match' '
+ # grep matches initial and second but not third
+ # author matches only initial and third
+ git log --author="A U Thor" --grep=s --grep=l --format=%s >actual &&
+ echo initial >expect &&
+ test_cmp expect actual
+'
+
test_expect_success 'grep with CE_VALID file' '
git update-index --assume-unchanged t/t &&
rm t/t &&