Skip to content

Commit 61690bf

Browse files
peffgitster
authored andcommitted
diffcore-pickaxe: unify code for log -S/-G
The logic flow of has_changes() used for "log -S" and diff_grep() used for "log -G" are essentially the same. See if we have both sides that could be different in any interesting way, slurp the contents in core, possibly after applying textconv, inspect the contents, clean-up and report the result. The only difference between the two is how "inspect" step works. Unify this codeflow in a helper, pickaxe_match(), which takes a callback function that implements the specific "inspect" step. After removing the common scaffolding code from the existing has_changes() and diff_grep(), they each becomes such a callback function suitable for passing to pickaxe_match(). Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 88ff684 commit 61690bf

File tree

1 file changed

+49
-69
lines changed

1 file changed

+49
-69
lines changed

diffcore-pickaxe.c

Lines changed: 49 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
#include "xdiff-interface.h"
99
#include "kwset.h"
1010

11-
typedef int (*pickaxe_fn)(struct diff_filepair *p, struct diff_options *o, regex_t *regexp, kwset_t kws);
11+
typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
12+
struct diff_options *o,
13+
regex_t *regexp, kwset_t kws);
14+
15+
static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
16+
regex_t *regexp, kwset_t kws, pickaxe_fn fn);
1217

1318
static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
1419
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
@@ -22,7 +27,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
2227
/* Showing the whole changeset if needle exists */
2328
for (i = 0; i < q->nr; i++) {
2429
struct diff_filepair *p = q->queue[i];
25-
if (fn(p, o, regexp, kws))
30+
if (pickaxe_match(p, o, regexp, kws, fn))
2631
return; /* do not munge the queue */
2732
}
2833

@@ -37,7 +42,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
3742
/* Showing only the filepairs that has the needle */
3843
for (i = 0; i < q->nr; i++) {
3944
struct diff_filepair *p = q->queue[i];
40-
if (fn(p, o, regexp, kws))
45+
if (pickaxe_match(p, o, regexp, kws, fn))
4146
diff_q(&outq, p);
4247
else
4348
diff_free_filepair(p);
@@ -74,64 +79,33 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
7479
line[len] = hold;
7580
}
7681

77-
static int diff_grep(struct diff_filepair *p, struct diff_options *o,
82+
static int diff_grep(mmfile_t *one, mmfile_t *two,
83+
struct diff_options *o,
7884
regex_t *regexp, kwset_t kws)
7985
{
8086
regmatch_t regmatch;
81-
struct userdiff_driver *textconv_one = NULL;
82-
struct userdiff_driver *textconv_two = NULL;
83-
mmfile_t mf1, mf2;
84-
int hit;
87+
struct diffgrep_cb ecbdata;
88+
xpparam_t xpp;
89+
xdemitconf_t xecfg;
8590

86-
if (!o->pickaxe[0])
87-
return 0;
91+
if (!one)
92+
return !regexec(regexp, two->ptr, 1, &regmatch, 0);
93+
if (!two)
94+
return !regexec(regexp, one->ptr, 1, &regmatch, 0);
8895

89-
if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
90-
textconv_one = get_textconv(p->one);
91-
textconv_two = get_textconv(p->two);
92-
}
93-
94-
if (textconv_one == textconv_two && diff_unmodified_pair(p))
95-
return 0;
96-
97-
mf1.size = fill_textconv(textconv_one, p->one, &mf1.ptr);
98-
mf2.size = fill_textconv(textconv_two, p->two, &mf2.ptr);
99-
100-
if (!DIFF_FILE_VALID(p->one)) {
101-
if (!DIFF_FILE_VALID(p->two))
102-
hit = 0; /* ignore unmerged */
103-
else
104-
/* created "two" -- does it have what we are looking for? */
105-
hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);
106-
} else if (!DIFF_FILE_VALID(p->two)) {
107-
/* removed "one" -- did it have what we are looking for? */
108-
hit = !regexec(regexp, mf1.ptr, 1, &regmatch, 0);
109-
} else {
110-
/*
111-
* We have both sides; need to run textual diff and see if
112-
* the pattern appears on added/deleted lines.
113-
*/
114-
struct diffgrep_cb ecbdata;
115-
xpparam_t xpp;
116-
xdemitconf_t xecfg;
117-
118-
memset(&xpp, 0, sizeof(xpp));
119-
memset(&xecfg, 0, sizeof(xecfg));
120-
ecbdata.regexp = regexp;
121-
ecbdata.hit = 0;
122-
xecfg.ctxlen = o->context;
123-
xecfg.interhunkctxlen = o->interhunkcontext;
124-
xdi_diff_outf(&mf1, &mf2, diffgrep_consume, &ecbdata,
125-
&xpp, &xecfg);
126-
hit = ecbdata.hit;
127-
}
128-
if (textconv_one)
129-
free(mf1.ptr);
130-
if (textconv_two)
131-
free(mf2.ptr);
132-
diff_free_filespec_data(p->one);
133-
diff_free_filespec_data(p->two);
134-
return hit;
96+
/*
97+
* We have both sides; need to run textual diff and see if
98+
* the pattern appears on added/deleted lines.
99+
*/
100+
memset(&xpp, 0, sizeof(xpp));
101+
memset(&xecfg, 0, sizeof(xecfg));
102+
ecbdata.regexp = regexp;
103+
ecbdata.hit = 0;
104+
xecfg.ctxlen = o->context;
105+
xecfg.interhunkctxlen = o->interhunkcontext;
106+
xdi_diff_outf(one, two, diffgrep_consume, &ecbdata,
107+
&xpp, &xecfg);
108+
return ecbdata.hit;
135109
}
136110

137111
static void diffcore_pickaxe_grep(struct diff_options *o)
@@ -198,8 +172,19 @@ static unsigned int contains(mmfile_t *mf, struct diff_options *o,
198172
return cnt;
199173
}
200174

201-
static int has_changes(struct diff_filepair *p, struct diff_options *o,
175+
static int has_changes(mmfile_t *one, mmfile_t *two,
176+
struct diff_options *o,
202177
regex_t *regexp, kwset_t kws)
178+
{
179+
if (!one)
180+
return contains(two, o, regexp, kws) != 0;
181+
if (!two)
182+
return contains(one, o, regexp, kws) != 0;
183+
return contains(one, o, regexp, kws) != contains(two, o, regexp, kws);
184+
}
185+
186+
static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
187+
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
203188
{
204189
struct userdiff_driver *textconv_one = NULL;
205190
struct userdiff_driver *textconv_two = NULL;
@@ -209,6 +194,10 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
209194
if (!o->pickaxe[0])
210195
return 0;
211196

197+
/* ignore unmerged */
198+
if (!DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two))
199+
return 0;
200+
212201
if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
213202
textconv_one = get_textconv(p->one);
214203
textconv_two = get_textconv(p->two);
@@ -227,18 +216,9 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
227216
mf1.size = fill_textconv(textconv_one, p->one, &mf1.ptr);
228217
mf2.size = fill_textconv(textconv_two, p->two, &mf2.ptr);
229218

230-
if (!DIFF_FILE_VALID(p->one)) {
231-
if (!DIFF_FILE_VALID(p->two))
232-
ret = 0; /* ignore unmerged */
233-
else
234-
/* created */
235-
ret = contains(&mf2, o, regexp, kws) != 0;
236-
}
237-
else if (!DIFF_FILE_VALID(p->two)) /* removed */
238-
ret = contains(&mf1, o, regexp, kws) != 0;
239-
else
240-
ret = contains(&mf1, o, regexp, kws) !=
241-
contains(&mf2, o, regexp, kws);
219+
ret = fn(DIFF_FILE_VALID(p->one) ? &mf1 : NULL,
220+
DIFF_FILE_VALID(p->two) ? &mf2 : NULL,
221+
o, regexp, kws);
242222

243223
if (textconv_one)
244224
free(mf1.ptr);

0 commit comments

Comments
 (0)