Skip to content

Commit fa04ae0

Browse files
apelissegitster
authored andcommitted
Allow combined diff to ignore white-spaces
The combined diff --cc output does not honor options to ignore whitespace changes (-b, -w, and --ignore-space-at-eol). Correct this by passing diff flags to diff engine, so that combined diff behaves as normal diff does with spaces, and by coalescing lines that are removed from both (or more) parents, honoring the same rule to ignore whitespace changes. With this change, a conflict-less merge done using a ignore-* strategy option will not show any conflict if shown in combined-diff using the same option. Signed-off-by: Antoine Pelisse <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 239222f commit fa04ae0

File tree

2 files changed

+161
-7
lines changed

2 files changed

+161
-7
lines changed

combine-diff.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "diffcore.h"
66
#include "quote.h"
77
#include "xdiff-interface.h"
8+
#include "xdiff/xmacros.h"
89
#include "log-tree.h"
910
#include "refs.h"
1011
#include "userdiff.h"
@@ -122,7 +123,47 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode,
122123
return blob;
123124
}
124125

125-
static void append_lost(struct sline *sline, int n, const char *line, int len)
126+
static int match_string_spaces(const char *line1, int len1,
127+
const char *line2, int len2,
128+
long flags)
129+
{
130+
if (flags & XDF_WHITESPACE_FLAGS) {
131+
for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--);
132+
for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--);
133+
}
134+
135+
if (!(flags & (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE)))
136+
return (len1 == len2 && !memcmp(line1, line2, len1));
137+
138+
while (len1 > 0 && len2 > 0) {
139+
len1--;
140+
len2--;
141+
if (XDL_ISSPACE(line1[len1]) || XDL_ISSPACE(line2[len2])) {
142+
if ((flags & XDF_IGNORE_WHITESPACE_CHANGE) &&
143+
(!XDL_ISSPACE(line1[len1]) || !XDL_ISSPACE(line2[len2])))
144+
return 0;
145+
146+
for (; len1 > 0 && XDL_ISSPACE(line1[len1]); len1--);
147+
for (; len2 > 0 && XDL_ISSPACE(line2[len2]); len2--);
148+
}
149+
if (line1[len1] != line2[len2])
150+
return 0;
151+
}
152+
153+
if (flags & XDF_IGNORE_WHITESPACE) {
154+
/* Consume remaining spaces */
155+
for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--);
156+
for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--);
157+
}
158+
159+
/* We matched full line1 and line2 */
160+
if (!len1 && !len2)
161+
return 1;
162+
163+
return 0;
164+
}
165+
166+
static void append_lost(struct sline *sline, int n, const char *line, int len, long flags)
126167
{
127168
struct lline *lline;
128169
unsigned long this_mask = (1UL<<n);
@@ -133,8 +174,8 @@ static void append_lost(struct sline *sline, int n, const char *line, int len)
133174
if (sline->lost_head) {
134175
lline = sline->next_lost;
135176
while (lline) {
136-
if (lline->len == len &&
137-
!memcmp(lline->line, line, len)) {
177+
if (match_string_spaces(lline->line, lline->len,
178+
line, len, flags)) {
138179
lline->parent_map |= this_mask;
139180
sline->next_lost = lline->next;
140181
return;
@@ -162,6 +203,7 @@ struct combine_diff_state {
162203
int n;
163204
struct sline *sline;
164205
struct sline *lost_bucket;
206+
long flags;
165207
};
166208

167209
static void consume_line(void *state_, char *line, unsigned long len)
@@ -201,7 +243,7 @@ static void consume_line(void *state_, char *line, unsigned long len)
201243
return; /* not in any hunk yet */
202244
switch (line[0]) {
203245
case '-':
204-
append_lost(state->lost_bucket, state->n, line+1, len-1);
246+
append_lost(state->lost_bucket, state->n, line+1, len-1, state->flags);
205247
break;
206248
case '+':
207249
state->sline[state->lno-1].flag |= state->nmask;
@@ -215,7 +257,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
215257
struct sline *sline, unsigned int cnt, int n,
216258
int num_parent, int result_deleted,
217259
struct userdiff_driver *textconv,
218-
const char *path)
260+
const char *path, long flags)
219261
{
220262
unsigned int p_lno, lno;
221263
unsigned long nmask = (1UL << n);
@@ -231,9 +273,10 @@ static void combine_diff(const unsigned char *parent, unsigned int mode,
231273
parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path);
232274
parent_file.size = sz;
233275
memset(&xpp, 0, sizeof(xpp));
234-
xpp.flags = 0;
276+
xpp.flags = flags;
235277
memset(&xecfg, 0, sizeof(xecfg));
236278
memset(&state, 0, sizeof(state));
279+
state.flags = flags;
237280
state.nmask = nmask;
238281
state.sline = sline;
239282
state.lno = 1;
@@ -962,7 +1005,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
9621005
elem->parent[i].mode,
9631006
&result_file, sline,
9641007
cnt, i, num_parent, result_deleted,
965-
textconv, elem->path);
1008+
textconv, elem->path, opt->xdl_opts);
9661009
}
9671010

9681011
show_hunks = make_hunks(sline, cnt, num_parent, dense);

t/t4038-diff-combined.sh

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
test_description='combined diff'
44

55
. ./test-lib.sh
6+
. "$TEST_DIRECTORY"/diff-lib.sh
67

78
setup_helper () {
89
one=$1 branch=$2 side=$3 &&
@@ -113,4 +114,114 @@ test_expect_success 'check --cc --raw with forty trees' '
113114
grep "^::::::::::::::::::::::::::::::::::::::::[^:]" out
114115
'
115116

117+
test_expect_success 'setup combined ignore spaces' '
118+
git checkout master &&
119+
>test &&
120+
git add test &&
121+
git commit -m initial &&
122+
123+
tr -d Q <<-\EOF >test &&
124+
always coalesce
125+
eol space coalesce Q
126+
space change coalesce
127+
all spa ces coalesce
128+
eol spaces Q
129+
space change
130+
all spa ces
131+
EOF
132+
git commit -m "test space change" -a &&
133+
134+
git checkout -b side HEAD^ &&
135+
tr -d Q <<-\EOF >test &&
136+
always coalesce
137+
eol space coalesce
138+
space change coalesce
139+
all spaces coalesce
140+
eol spaces
141+
space change
142+
all spaces
143+
EOF
144+
git commit -m "test other space changes" -a &&
145+
146+
test_must_fail git merge master &&
147+
tr -d Q <<-\EOF >test &&
148+
eol spaces Q
149+
space change
150+
all spa ces
151+
EOF
152+
git commit -m merged -a
153+
'
154+
155+
test_expect_success 'check combined output (no ignore space)' '
156+
git show >actual.tmp &&
157+
sed -e "1,/^@@@/d" < actual.tmp >actual &&
158+
tr -d Q <<-\EOF >expected &&
159+
--always coalesce
160+
- eol space coalesce
161+
- space change coalesce
162+
- all spaces coalesce
163+
- eol spaces
164+
- space change
165+
- all spaces
166+
-eol space coalesce Q
167+
-space change coalesce
168+
-all spa ces coalesce
169+
+ eol spaces Q
170+
+ space change
171+
+ all spa ces
172+
EOF
173+
compare_diff_patch expected actual
174+
'
175+
176+
test_expect_success 'check combined output (ignore space at eol)' '
177+
git show --ignore-space-at-eol >actual.tmp &&
178+
sed -e "1,/^@@@/d" < actual.tmp >actual &&
179+
tr -d Q <<-\EOF >expected &&
180+
--always coalesce
181+
--eol space coalesce
182+
- space change coalesce
183+
- all spaces coalesce
184+
-space change coalesce
185+
-all spa ces coalesce
186+
eol spaces Q
187+
- space change
188+
- all spaces
189+
+ space change
190+
+ all spa ces
191+
EOF
192+
compare_diff_patch expected actual
193+
'
194+
195+
test_expect_success 'check combined output (ignore space change)' '
196+
git show -b >actual.tmp &&
197+
sed -e "1,/^@@@/d" < actual.tmp >actual &&
198+
tr -d Q <<-\EOF >expected &&
199+
--always coalesce
200+
--eol space coalesce
201+
--space change coalesce
202+
- all spaces coalesce
203+
-all spa ces coalesce
204+
eol spaces Q
205+
space change
206+
- all spaces
207+
+ all spa ces
208+
EOF
209+
compare_diff_patch expected actual
210+
'
211+
212+
test_expect_success 'check combined output (ignore all spaces)' '
213+
git show -w >actual.tmp &&
214+
sed -e "1,/^@@@/d" < actual.tmp >actual &&
215+
tr -d Q <<-\EOF >expected &&
216+
--always coalesce
217+
--eol space coalesce
218+
--space change coalesce
219+
--all spaces coalesce
220+
eol spaces Q
221+
space change
222+
all spa ces
223+
EOF
224+
compare_diff_patch expected actual
225+
'
226+
116227
test_done

0 commit comments

Comments
 (0)