diff options
-rw-r--r-- | builtin-grep.c | 1 | ||||
-rw-r--r-- | builtin-rev-list.c | 5 | ||||
-rw-r--r-- | grep.c | 46 | ||||
-rw-r--r-- | grep.h | 2 | ||||
-rw-r--r-- | revision.c | 3 | ||||
-rwxr-xr-x | t/t7002-grep.sh | 10 |
6 files changed, 57 insertions, 10 deletions
diff --git a/builtin-grep.c b/builtin-grep.c index 552ef1face..d05107dd9f 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -868,6 +868,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 c924b3a2c7..5679170e82 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; @@ -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; } @@ -184,9 +184,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) { @@ -201,7 +218,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. @@ -212,6 +231,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) @@ -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 3ba6d991f6..438cc87b17 100644 --- a/revision.c +++ b/revision.c @@ -823,6 +823,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); @@ -1801,7 +1802,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 ebae1522c8..e249c3ed41 100755 --- a/t/t7002-grep.sh +++ b/t/t7002-grep.sh @@ -353,7 +353,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 ' @@ -364,6 +364,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 && |