Skip to content

Commit 39d23df

Browse files
committed
Merge branch 'jk/xdiff-interface'
The interface into "xdiff" library used to discover the offset and size of a generated patch hunk by first formatting it into the textual hunk header "@@ -n,m +k,l @@" and then parsing the numbers out. A new interface has been introduced to allow callers a more direct access to them. * jk/xdiff-interface: xdiff-interface: drop parse_hunk_header() range-diff: use a hunk callback diff: convert --check to use a hunk callback combine-diff: use an xdiff hunk callback diff: use hunk callback for word-diff diff: discard hunk headers for patch-ids earlier diff: avoid generating unused hunk header lines xdiff-interface: provide a separate consume callback for hunks xdiff: provide a separate emit callback for hunks
2 parents f22838a + 5eade07 commit 39d23df

File tree

10 files changed

+143
-115
lines changed

10 files changed

+143
-115
lines changed

builtin/merge-tree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ static void show_diff(struct merge_list *entry)
110110
xpp.flags = 0;
111111
memset(&xecfg, 0, sizeof(xecfg));
112112
xecfg.ctxlen = 3;
113-
ecb.outf = show_outf;
113+
ecb.out_hunk = NULL;
114+
ecb.out_line = show_outf;
114115
ecb.priv = NULL;
115116

116117
src.ptr = origin(entry, &size);

builtin/rerere.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ static int diff_two(const char *file1, const char *label1,
4141
xpp.flags = 0;
4242
memset(&xecfg, 0, sizeof(xecfg));
4343
xecfg.ctxlen = 3;
44-
ecb.outf = outf;
44+
ecb.out_hunk = NULL;
45+
ecb.out_line = outf;
4546
ret = xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
4647

4748
free(minus.ptr);

combine-diff.c

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -345,38 +345,43 @@ struct combine_diff_state {
345345
struct sline *lost_bucket;
346346
};
347347

348-
static void consume_line(void *state_, char *line, unsigned long len)
348+
static void consume_hunk(void *state_,
349+
long ob, long on,
350+
long nb, long nn,
351+
const char *funcline, long funclen)
349352
{
350353
struct combine_diff_state *state = state_;
351-
if (5 < len && !memcmp("@@ -", line, 4)) {
352-
if (parse_hunk_header(line, len,
353-
&state->ob, &state->on,
354-
&state->nb, &state->nn))
355-
return;
356-
state->lno = state->nb;
357-
if (state->nn == 0) {
358-
/* @@ -X,Y +N,0 @@ removed Y lines
359-
* that would have come *after* line N
360-
* in the result. Our lost buckets hang
361-
* to the line after the removed lines,
362-
*
363-
* Note that this is correct even when N == 0,
364-
* in which case the hunk removes the first
365-
* line in the file.
366-
*/
367-
state->lost_bucket = &state->sline[state->nb];
368-
if (!state->nb)
369-
state->nb = 1;
370-
} else {
371-
state->lost_bucket = &state->sline[state->nb-1];
372-
}
373-
if (!state->sline[state->nb-1].p_lno)
374-
state->sline[state->nb-1].p_lno =
375-
xcalloc(state->num_parent,
376-
sizeof(unsigned long));
377-
state->sline[state->nb-1].p_lno[state->n] = state->ob;
378-
return;
354+
355+
state->ob = ob;
356+
state->on = on;
357+
state->nb = nb;
358+
state->nn = nn;
359+
state->lno = state->nb;
360+
if (state->nn == 0) {
361+
/* @@ -X,Y +N,0 @@ removed Y lines
362+
* that would have come *after* line N
363+
* in the result. Our lost buckets hang
364+
* to the line after the removed lines,
365+
*
366+
* Note that this is correct even when N == 0,
367+
* in which case the hunk removes the first
368+
* line in the file.
369+
*/
370+
state->lost_bucket = &state->sline[state->nb];
371+
if (!state->nb)
372+
state->nb = 1;
373+
} else {
374+
state->lost_bucket = &state->sline[state->nb-1];
379375
}
376+
if (!state->sline[state->nb-1].p_lno)
377+
state->sline[state->nb-1].p_lno =
378+
xcalloc(state->num_parent, sizeof(unsigned long));
379+
state->sline[state->nb-1].p_lno[state->n] = state->ob;
380+
}
381+
382+
static void consume_line(void *state_, char *line, unsigned long len)
383+
{
384+
struct combine_diff_state *state = state_;
380385
if (!state->lost_bucket)
381386
return; /* not in any hunk yet */
382387
switch (line[0]) {
@@ -421,8 +426,8 @@ static void combine_diff(struct repository *r,
421426
state.num_parent = num_parent;
422427
state.n = n;
423428

424-
if (xdi_diff_outf(&parent_file, result_file, consume_line, &state,
425-
&xpp, &xecfg))
429+
if (xdi_diff_outf(&parent_file, result_file, consume_hunk,
430+
consume_line, &state, &xpp, &xecfg))
426431
die("unable to generate combined diff for %s",
427432
oid_to_hex(parent));
428433
free(parent_file.ptr);

diff.c

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,19 +1912,17 @@ static int color_words_output_graph_prefix(struct diff_words_data *diff_words)
19121912
}
19131913
}
19141914

1915-
static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
1915+
static void fn_out_diff_words_aux(void *priv,
1916+
long minus_first, long minus_len,
1917+
long plus_first, long plus_len,
1918+
const char *func, long funclen)
19161919
{
19171920
struct diff_words_data *diff_words = priv;
19181921
struct diff_words_style *style = diff_words->style;
1919-
int minus_first, minus_len, plus_first, plus_len;
19201922
const char *minus_begin, *minus_end, *plus_begin, *plus_end;
19211923
struct diff_options *opt = diff_words->opt;
19221924
const char *line_prefix;
19231925

1924-
if (line[0] != '@' || parse_hunk_header(line, len,
1925-
&minus_first, &minus_len, &plus_first, &plus_len))
1926-
return;
1927-
19281926
assert(opt);
19291927
line_prefix = diff_line_prefix(opt);
19301928

@@ -2074,8 +2072,8 @@ static void diff_words_show(struct diff_words_data *diff_words)
20742072
xpp.flags = 0;
20752073
/* as only the hunk header will be parsed, we need a 0-context */
20762074
xecfg.ctxlen = 0;
2077-
if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
2078-
&xpp, &xecfg))
2075+
if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, NULL,
2076+
diff_words, &xpp, &xecfg))
20792077
die("unable to generate word diff");
20802078
free(minus.ptr);
20812079
free(plus.ptr);
@@ -3130,6 +3128,15 @@ static int is_conflict_marker(const char *line, int marker_size, unsigned long l
31303128
return 1;
31313129
}
31323130

3131+
static void checkdiff_consume_hunk(void *priv,
3132+
long ob, long on, long nb, long nn,
3133+
const char *func, long funclen)
3134+
3135+
{
3136+
struct checkdiff_t *data = priv;
3137+
data->lineno = nb - 1;
3138+
}
3139+
31333140
static void checkdiff_consume(void *priv, char *line, unsigned long len)
31343141
{
31353142
struct checkdiff_t *data = priv;
@@ -3165,12 +3172,6 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
31653172
data->o->file, set, reset, ws);
31663173
} else if (line[0] == ' ') {
31673174
data->lineno++;
3168-
} else if (line[0] == '@') {
3169-
char *plus = strchr(line, '+');
3170-
if (plus)
3171-
data->lineno = strtol(plus, NULL, 10) - 1;
3172-
else
3173-
die("invalid diff");
31743175
}
31753176
}
31763177

@@ -3526,8 +3527,8 @@ static void builtin_diff(const char *name_a,
35263527
xecfg.ctxlen = strtoul(v, NULL, 10);
35273528
if (o->word_diff)
35283529
init_diff_words_data(&ecbdata, o, one, two);
3529-
if (xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
3530-
&xpp, &xecfg))
3530+
if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
3531+
&ecbdata, &xpp, &xecfg))
35313532
die("unable to generate diff for %s", one->path);
35323533
if (o->word_diff)
35333534
free_diff_words_data(&ecbdata);
@@ -3637,8 +3638,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
36373638
xpp.anchors_nr = o->anchors_nr;
36383639
xecfg.ctxlen = o->context;
36393640
xecfg.interhunkctxlen = o->interhunkcontext;
3640-
if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
3641-
&xpp, &xecfg))
3641+
if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
3642+
diffstat_consume, diffstat, &xpp, &xecfg))
36423643
die("unable to generate diffstat for %s", one->path);
36433644
}
36443645

@@ -3686,7 +3687,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
36863687
memset(&xecfg, 0, sizeof(xecfg));
36873688
xecfg.ctxlen = 1; /* at least one context line */
36883689
xpp.flags = 0;
3689-
if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
3690+
if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume_hunk,
3691+
checkdiff_consume, &data,
36903692
&xpp, &xecfg))
36913693
die("unable to generate checkdiff for %s", one->path);
36923694

@@ -5666,10 +5668,6 @@ static void patch_id_consume(void *priv, char *line, unsigned long len)
56665668
struct patch_id_t *data = priv;
56675669
int new_len;
56685670

5669-
/* Ignore line numbers when computing the SHA1 of the patch */
5670-
if (starts_with(line, "@@ -"))
5671-
return;
5672-
56735671
new_len = remove_space(line, len);
56745672

56755673
git_SHA1_Update(data->ctx, line, new_len);
@@ -5771,8 +5769,8 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid
57715769
xpp.flags = 0;
57725770
xecfg.ctxlen = 3;
57735771
xecfg.flags = 0;
5774-
if (xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
5775-
&xpp, &xecfg))
5772+
if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
5773+
patch_id_consume, &data, &xpp, &xecfg))
57765774
return error("unable to generate patch-id diff for %s",
57775775
p->one->path);
57785776
}

diffcore-pickaxe.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
6262
ecbdata.hit = 0;
6363
xecfg.ctxlen = o->context;
6464
xecfg.interhunkctxlen = o->interhunkcontext;
65-
if (xdi_diff_outf(one, two, diffgrep_consume, &ecbdata, &xpp, &xecfg))
65+
if (xdi_diff_outf(one, two, discard_hunk_line, diffgrep_consume,
66+
&ecbdata, &xpp, &xecfg))
6667
return 0;
6768
return ecbdata.hit;
6869
}

range-diff.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ static void diffsize_consume(void *data, char *line, unsigned long len)
197197
(*(int *)data)++;
198198
}
199199

200+
static void diffsize_hunk(void *data, long ob, long on, long nb, long nn,
201+
const char *funcline, long funclen)
202+
{
203+
diffsize_consume(data, NULL, 0);
204+
}
205+
200206
static int diffsize(const char *a, const char *b)
201207
{
202208
xpparam_t pp = { 0 };
@@ -210,7 +216,9 @@ static int diffsize(const char *a, const char *b)
210216
mf2.size = strlen(b);
211217

212218
cfg.ctxlen = 3;
213-
if (!xdi_diff_outf(&mf1, &mf2, diffsize_consume, &count, &pp, &cfg))
219+
if (!xdi_diff_outf(&mf1, &mf2,
220+
diffsize_hunk, diffsize_consume, &count,
221+
&pp, &cfg))
214222
return count;
215223

216224
error(_("failed to generate diff"));

xdiff-interface.c

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,54 +9,26 @@
99
#include "xdiff/xutils.h"
1010

1111
struct xdiff_emit_state {
12-
xdiff_emit_consume_fn consume;
12+
xdiff_emit_hunk_fn hunk_fn;
13+
xdiff_emit_line_fn line_fn;
1314
void *consume_callback_data;
1415
struct strbuf remainder;
1516
};
1617

17-
static int parse_num(char **cp_p, int *num_p)
18+
static int xdiff_out_hunk(void *priv_,
19+
long old_begin, long old_nr,
20+
long new_begin, long new_nr,
21+
const char *func, long funclen)
1822
{
19-
char *cp = *cp_p;
20-
int num = 0;
23+
struct xdiff_emit_state *priv = priv_;
2124

22-
while ('0' <= *cp && *cp <= '9')
23-
num = num * 10 + *cp++ - '0';
24-
if (!(cp - *cp_p))
25-
return -1;
26-
*cp_p = cp;
27-
*num_p = num;
28-
return 0;
29-
}
25+
if (priv->remainder.len)
26+
BUG("xdiff emitted hunk in the middle of a line");
3027

31-
int parse_hunk_header(char *line, int len,
32-
int *ob, int *on,
33-
int *nb, int *nn)
34-
{
35-
char *cp;
36-
cp = line + 4;
37-
if (parse_num(&cp, ob)) {
38-
bad_line:
39-
return error("malformed diff output: %s", line);
40-
}
41-
if (*cp == ',') {
42-
cp++;
43-
if (parse_num(&cp, on))
44-
goto bad_line;
45-
}
46-
else
47-
*on = 1;
48-
if (*cp++ != ' ' || *cp++ != '+')
49-
goto bad_line;
50-
if (parse_num(&cp, nb))
51-
goto bad_line;
52-
if (*cp == ',') {
53-
cp++;
54-
if (parse_num(&cp, nn))
55-
goto bad_line;
56-
}
57-
else
58-
*nn = 1;
59-
return -!!memcmp(cp, " @@", 3);
28+
priv->hunk_fn(priv->consume_callback_data,
29+
old_begin, old_nr, new_begin, new_nr,
30+
func, funclen);
31+
return 0;
6032
}
6133

6234
static void consume_one(void *priv_, char *s, unsigned long size)
@@ -67,7 +39,7 @@ static void consume_one(void *priv_, char *s, unsigned long size)
6739
unsigned long this_size;
6840
ep = memchr(s, '\n', size);
6941
this_size = (ep == NULL) ? size : (ep - s + 1);
70-
priv->consume(priv->consume_callback_data, s, this_size);
42+
priv->line_fn(priv->consume_callback_data, s, this_size);
7143
size -= this_size;
7244
s += this_size;
7345
}
@@ -78,6 +50,9 @@ static int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
7850
struct xdiff_emit_state *priv = priv_;
7951
int i;
8052

53+
if (!priv->line_fn)
54+
return 0;
55+
8156
for (i = 0; i < nbuf; i++) {
8257
if (mb[i].ptr[mb[i].size-1] != '\n') {
8358
/* Incomplete line */
@@ -140,19 +115,30 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co
140115
return xdl_diff(&a, &b, xpp, xecfg, xecb);
141116
}
142117

118+
void discard_hunk_line(void *priv,
119+
long ob, long on, long nb, long nn,
120+
const char *func, long funclen)
121+
{
122+
}
123+
143124
int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
144-
xdiff_emit_consume_fn fn, void *consume_callback_data,
125+
xdiff_emit_hunk_fn hunk_fn,
126+
xdiff_emit_line_fn line_fn,
127+
void *consume_callback_data,
145128
xpparam_t const *xpp, xdemitconf_t const *xecfg)
146129
{
147130
int ret;
148131
struct xdiff_emit_state state;
149132
xdemitcb_t ecb;
150133

151134
memset(&state, 0, sizeof(state));
152-
state.consume = fn;
135+
state.hunk_fn = hunk_fn;
136+
state.line_fn = line_fn;
153137
state.consume_callback_data = consume_callback_data;
154138
memset(&ecb, 0, sizeof(ecb));
155-
ecb.outf = xdiff_outf;
139+
if (hunk_fn)
140+
ecb.out_hunk = xdiff_out_hunk;
141+
ecb.out_line = xdiff_outf;
156142
ecb.priv = &state;
157143
strbuf_init(&state.remainder, 0);
158144
ret = xdi_diff(mf1, mf2, xpp, xecfg, &ecb);

0 commit comments

Comments
 (0)