Skip to content

Commit fa59e7b

Browse files
avargitster
authored andcommitted
pickaxe -G: terminate early on matching lines
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 f506b8e (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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9e20442 commit fa59e7b

File tree

2 files changed

+23
-11
lines changed

2 files changed

+23
-11
lines changed

diffcore-pickaxe.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ static int diffgrep_consume(void *priv, char *line, unsigned long len)
2727
if (line[0] != '+' && line[0] != '-')
2828
return 0;
2929
if (data->hit)
30-
/*
31-
* NEEDSWORK: we should have a way to terminate the
32-
* caller early.
33-
*/
34-
return 0;
35-
data->hit = !regexec_buf(data->regexp, line + 1, len - 1, 1,
36-
&regmatch, 0);
30+
BUG("Already matched in diffgrep_consume! Broken xdiff_emit_line_fn?");
31+
if (!regexec_buf(data->regexp, line + 1, len - 1, 1,
32+
&regmatch, 0)) {
33+
data->hit = 1;
34+
return 1;
35+
}
3736
return 0;
3837
}
3938

@@ -45,6 +44,7 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
4544
struct diffgrep_cb ecbdata;
4645
xpparam_t xpp;
4746
xdemitconf_t xecfg;
47+
int ret;
4848

4949
if (!one)
5050
return !regexec_buf(regexp, two->ptr, two->size,
@@ -63,10 +63,18 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
6363
ecbdata.hit = 0;
6464
xecfg.ctxlen = o->context;
6565
xecfg.interhunkctxlen = o->interhunkcontext;
66-
if (xdi_diff_outf(one, two, discard_hunk_line, diffgrep_consume,
67-
&ecbdata, &xpp, &xecfg))
68-
return 0;
69-
return ecbdata.hit;
66+
67+
/*
68+
* An xdiff error might be our "data->hit" from above. See the
69+
* comment for xdiff_emit_line_fn in xdiff-interface.h
70+
*/
71+
ret = xdi_diff_outf(one, two, discard_hunk_line, diffgrep_consume,
72+
&ecbdata, &xpp, &xecfg);
73+
if (ecbdata.hit)
74+
return 1;
75+
if (ret)
76+
return ret;
77+
return 0;
7078
}
7179

7280
static unsigned int contains(mmfile_t *mf, regex_t *regexp, kwset_t kws,

xdiff-interface.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
* doing so will currently make your early return indistinguishable
2828
* from an error internal to xdiff, xdiff itself will see that
2929
* non-zero return and translate it to -1.
30+
*
31+
* See "diff_grep" in diffcore-pickaxe.c for a trick to work around
32+
* this, i.e. using the "consume_callback_data" to note the desired
33+
* early return.
3034
*/
3135
typedef int (*xdiff_emit_line_fn)(void *, char *, unsigned long);
3236
typedef void (*xdiff_emit_hunk_fn)(void *data,

0 commit comments

Comments
 (0)