]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pickaxe -G: terminate early on matching lines
authorÆvar Arnfjörð Bjarmason <avarab@gmail.com>
Mon, 12 Apr 2021 17:15:26 +0000 (19:15 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 11 May 2021 03:47:31 +0000 (12:47 +0900)
Solve a long-standing item for "git log -Grx" of us e.g. finding "+
str" in the diff context and noting that we had a "hit", but xdiff
diligently continuing to generate and spew the rest of the diff at
us. This makes use of a new "early return" xdiff interface added by
preceding commits.

The TODO item (or, the NEEDSWORK comment) has been there since "git
log -G" was implemented. See f506b8e8b5f (git log/diff: add -G<regexp>
that greps in the patch text, 2010-08-23).

But now with the support added in the preceding changes to the
xdiff-interface we can return early. Let's assert the behavior of that
new early-return xdiff-interface by having a BUG() call here to die if
it ever starts handing us needless work again.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diffcore-pickaxe.c
xdiff-interface.h

index 27aa20be350952a6313bc61bf146e905d123f9d9..2147afef722c5879c983a150f5dfbb87406fee73 100644 (file)
@@ -27,13 +27,12 @@ static int diffgrep_consume(void *priv, char *line, unsigned long len)
        if (line[0] != '+' && line[0] != '-')
                return 0;
        if (data->hit)
-               /*
-                * NEEDSWORK: we should have a way to terminate the
-                * caller early.
-                */
-               return 0;
-       data->hit = !regexec_buf(data->regexp, line + 1, len - 1, 1,
-                                &regmatch, 0);
+               BUG("Already matched in diffgrep_consume! Broken xdiff_emit_line_fn?");
+       if (!regexec_buf(data->regexp, line + 1, len - 1, 1,
+                        &regmatch, 0)) {
+               data->hit = 1;
+               return 1;
+       }
        return 0;
 }
 
@@ -45,6 +44,7 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
        struct diffgrep_cb ecbdata;
        xpparam_t xpp;
        xdemitconf_t xecfg;
+       int ret;
 
        if (!one)
                return !regexec_buf(regexp, two->ptr, two->size,
@@ -63,10 +63,18 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
        ecbdata.hit = 0;
        xecfg.ctxlen = o->context;
        xecfg.interhunkctxlen = o->interhunkcontext;
-       if (xdi_diff_outf(one, two, discard_hunk_line, diffgrep_consume,
-                         &ecbdata, &xpp, &xecfg))
-               return 0;
-       return ecbdata.hit;
+
+       /*
+        * An xdiff error might be our "data->hit" from above. See the
+        * comment for xdiff_emit_line_fn in xdiff-interface.h
+        */
+       ret = xdi_diff_outf(one, two, discard_hunk_line, diffgrep_consume,
+                           &ecbdata, &xpp, &xecfg);
+       if (ecbdata.hit)
+               return 1;
+       if (ret)
+               return ret;
+       return 0;
 }
 
 static unsigned int contains(mmfile_t *mf, regex_t *regexp, kwset_t kws,
index 7d1724abb646839304504d67c4fd172ce66ad5e2..3b6819586da6d9e93af0116cd7069532c26cccb2 100644 (file)
  * doing so will currently make your early return indistinguishable
  * from an error internal to xdiff, xdiff itself will see that
  * non-zero return and translate it to -1.
+ *
+ * See "diff_grep" in diffcore-pickaxe.c for a trick to work around
+ * this, i.e. using the "consume_callback_data" to note the desired
+ * early return.
  */
 typedef int (*xdiff_emit_line_fn)(void *, char *, unsigned long);
 typedef void (*xdiff_emit_hunk_fn)(void *data,