]> git.ipfire.org Git - thirdparty/git.git/blobdiff - grep.c
Merge git://git.kernel.org/pub/scm/gitk/gitk
[thirdparty/git.git] / grep.c
diff --git a/grep.c b/grep.c
index b641305ff6e9a05b20d92e9c0274004625bd7f28..543b1d53784c16020dea089f23c431c7f2608425 100644 (file)
--- 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;
 }
 
@@ -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)
@@ -536,8 +570,7 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
                        if (opt->show_hunk_mark) {
                                output_color(opt, "--", 2, opt->color_sep);
                                opt->output(opt, "\n", 1);
-                       } else
-                               opt->show_hunk_mark = 1;
+                       }
                } else if (lno > opt->last_shown + 1) {
                        output_color(opt, "--", 2, opt->color_sep);
                        opt->output(opt, "\n", 1);
@@ -738,14 +771,6 @@ int grep_threads_ok(const struct grep_opt *opt)
            !opt->name_only)
                return 0;
 
-       /* If we are showing hunk marks, we should not do it for the
-        * first match. The synchronization problem we get for this
-        * constraint is not yet solved, so we disable threading in
-        * this case.
-        */
-       if (opt->pre_context || opt->post_context)
-               return 0;
-
        return 1;
 }
 
@@ -767,11 +792,14 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
        enum grep_context ctx = GREP_CONTEXT_HEAD;
        xdemitconf_t xecfg;
 
-       opt->last_shown = 0;
-
        if (!opt->output)
                opt->output = std_output;
 
+       if (opt->last_shown && (opt->pre_context || opt->post_context) &&
+           opt->output == std_output)
+               opt->show_hunk_mark = 1;
+       opt->last_shown = 0;
+
        if (buffer_is_binary(buf, size)) {
                switch (opt->binary) {
                case GREP_BINARY_DEFAULT: