]> git.ipfire.org Git - thirdparty/git.git/commitdiff
grep: refactor next_match() and match_one_pattern() for external use
authorHamza Mahfooz <someguy@effective-light.com>
Wed, 29 Sep 2021 11:57:15 +0000 (07:57 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 29 Sep 2021 20:23:11 +0000 (13:23 -0700)
These changes are made in preparation of, the colorization support for the
"git log" subcommands that, rely on regex functionality (i.e. "--author",
"--committer" and "--grep"). These changes are necessary primarily because
match_one_pattern() expects header lines to be prefixed, however, in
pretty, the prefixes are stripped from the lines because the name-email
pairs need to go through additional parsing, before they can be printed and
because next_match() doesn't handle the case of
"ctx == GREP_CONTEXT_HEAD" at all. So, teach next_match() how to handle the
new case and move match_one_pattern()'s core logic to
headerless_match_one_pattern() while preserving match_one_pattern()'s uses
that depend on the additional processing.

Signed-off-by: Hamza Mahfooz <someguy@effective-light.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
grep.c
grep.h

diff --git a/grep.c b/grep.c
index 14fe8a0fd23a9e4d196c7813c64b8e24edb74a6f..fe847a0111a209279656c5a14318d2fa196df2ed 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -944,10 +944,10 @@ static struct {
        { "reflog ", 7 },
 };
 
-static int match_one_pattern(struct grep_pat *p,
-                            const char *bol, const char *eol,
-                            enum grep_context ctx,
-                            regmatch_t *pmatch, int eflags)
+static int headerless_match_one_pattern(struct grep_pat *p,
+                                       const char *bol, const char *eol,
+                                       enum grep_context ctx,
+                                       regmatch_t *pmatch, int eflags)
 {
        int hit = 0;
        const char *start = bol;
@@ -956,25 +956,6 @@ static int match_one_pattern(struct grep_pat *p,
            ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
                return 0;
 
-       if (p->token == GREP_PATTERN_HEAD) {
-               const char *field;
-               size_t len;
-               assert(p->field < ARRAY_SIZE(header_field));
-               field = header_field[p->field].field;
-               len = header_field[p->field].len;
-               if (strncmp(bol, field, len))
-                       return 0;
-               bol += len;
-               switch (p->field) {
-               case GREP_HEADER_AUTHOR:
-               case GREP_HEADER_COMMITTER:
-                       strip_timestamp(bol, &eol);
-                       break;
-               default:
-                       break;
-               }
-       }
-
  again:
        hit = patmatch(p, bol, eol, pmatch, eflags);
 
@@ -1025,6 +1006,36 @@ static int match_one_pattern(struct grep_pat *p,
        return hit;
 }
 
+static int match_one_pattern(struct grep_pat *p,
+                            const char *bol, const char *eol,
+                            enum grep_context ctx, regmatch_t *pmatch,
+                            int eflags)
+{
+       const char *field;
+       size_t len;
+
+       if (p->token == GREP_PATTERN_HEAD) {
+               assert(p->field < ARRAY_SIZE(header_field));
+               field = header_field[p->field].field;
+               len = header_field[p->field].len;
+               if (strncmp(bol, field, len))
+                       return 0;
+               bol += len;
+
+               switch (p->field) {
+               case GREP_HEADER_AUTHOR:
+               case GREP_HEADER_COMMITTER:
+                       strip_timestamp(bol, &eol);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return headerless_match_one_pattern(p, bol, eol, ctx, pmatch, eflags);
+}
+
+
 static int match_expr_eval(struct grep_opt *opt, struct grep_expr *x,
                           const char *bol, const char *eol,
                           enum grep_context ctx, ssize_t *col,
@@ -1143,7 +1154,7 @@ static int match_next_pattern(struct grep_pat *p,
 {
        regmatch_t match;
 
-       if (!match_one_pattern(p, bol, eol, ctx, &match, eflags))
+       if (!headerless_match_one_pattern(p, bol, eol, ctx, &match, eflags))
                return 0;
        if (match.rm_so < 0 || match.rm_eo < 0)
                return 0;
@@ -1158,19 +1169,26 @@ static int match_next_pattern(struct grep_pat *p,
        return 1;
 }
 
-static int next_match(struct grep_opt *opt,
-                     const char *bol, const char *eol,
-                     enum grep_context ctx, regmatch_t *pmatch, int eflags)
+int grep_next_match(struct grep_opt *opt,
+                   const char *bol, const char *eol,
+                   enum grep_context ctx, regmatch_t *pmatch,
+                   enum grep_header_field field, int eflags)
 {
        struct grep_pat *p;
        int hit = 0;
 
        pmatch->rm_so = pmatch->rm_eo = -1;
        if (bol < eol) {
-               for (p = opt->pattern_list; p; p = p->next) {
+               for (p = ((ctx == GREP_CONTEXT_HEAD)
+                          ? opt->header_list : opt->pattern_list);
+                         p; p = p->next) {
                        switch (p->token) {
-                       case GREP_PATTERN: /* atom */
                        case GREP_PATTERN_HEAD:
+                               if ((field != GREP_HEADER_FIELD_MAX) &&
+                                   (p->field != field))
+                                       continue;
+                               /* fall thru */
+                       case GREP_PATTERN: /* atom */
                        case GREP_PATTERN_BODY:
                                hit |= match_next_pattern(p, bol, eol, ctx,
                                                          pmatch, eflags);
@@ -1261,7 +1279,8 @@ static void show_line(struct grep_opt *opt,
                        else if (sign == '=')
                                line_color = opt->colors[GREP_COLOR_FUNCTION];
                }
-               while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+               while (grep_next_match(opt, bol, eol, ctx, &match,
+                                      GREP_HEADER_FIELD_MAX, eflags)) {
                        if (match.rm_so == match.rm_eo)
                                break;
 
diff --git a/grep.h b/grep.h
index 3cb8a83ae8ca584bc1b3f7a5d0e9dd6b92381777..808ad76f0c53f9296ad2397d19a4925b217bc5a9 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -191,6 +191,15 @@ void compile_grep_patterns(struct grep_opt *opt);
 void free_grep_patterns(struct grep_opt *opt);
 int grep_buffer(struct grep_opt *opt, const char *buf, unsigned long size);
 
+/* The field parameter is only used to filter header patterns
+ * (where appropriate). If filtering isn't desirable
+ * GREP_HEADER_FIELD_MAX should be supplied.
+ */
+int grep_next_match(struct grep_opt *opt,
+                   const char *bol, const char *eol,
+                   enum grep_context ctx, regmatch_t *pmatch,
+                   enum grep_header_field field, int eflags);
+
 struct grep_source {
        char *name;