Skip to content

Commit 10f65c2

Browse files
committed
Merge branch 'jc/ignore-cr-at-eol'
The "diff" family of commands learned to ignore differences in carriage return at the end of line. * jc/ignore-cr-at-eol: diff: --ignore-cr-at-eol xdiff: reassign xpparm_t.flags bits
2 parents 14c63a9 + e9282f0 commit 10f65c2

File tree

8 files changed

+92
-18
lines changed

8 files changed

+92
-18
lines changed

Documentation/diff-options.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,9 @@ endif::git-format-patch[]
557557
--text::
558558
Treat all files as text.
559559

560+
--ignore-cr-at-eol::
561+
Ignore carrige-return at the end of line when doing a comparison.
562+
560563
--ignore-space-at-eol::
561564
Ignore changes in whitespace at EOL.
562565

Documentation/merge-strategies.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ diff-algorithm=[patience|minimal|histogram|myers];;
5858
ignore-space-change;;
5959
ignore-all-space;;
6060
ignore-space-at-eol;;
61+
ignore-cr-at-eol;;
6162
Treats lines with the indicated type of whitespace change as
6263
unchanged for the sake of a three-way merge. Whitespace
6364
changes mixed with other changes to a line are not ignored.
64-
See also linkgit:git-diff[1] `-b`, `-w`, and
65-
`--ignore-space-at-eol`.
65+
See also linkgit:git-diff[1] `-b`, `-w`,
66+
`--ignore-space-at-eol`, and `--ignore-cr-at-eol`.
6667
+
6768
* If 'their' version only introduces whitespace changes to a line,
6869
'our' version is used;

contrib/completion/git-completion.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1400,7 +1400,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
14001400
--patch-with-stat --name-only --name-status --color
14011401
--no-color --color-words --no-renames --check
14021402
--full-index --binary --abbrev --diff-filter=
1403-
--find-copies-harder
1403+
--find-copies-harder --ignore-cr-at-eol
14041404
--text --ignore-space-at-eol --ignore-space-change
14051405
--ignore-all-space --ignore-blank-lines --exit-code
14061406
--quiet --ext-diff --no-ext-diff

diff.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,9 +4129,7 @@ void diff_setup_done(struct diff_options *options)
41294129
* inside contents.
41304130
*/
41314131

4132-
if (DIFF_XDL_TST(options, IGNORE_WHITESPACE) ||
4133-
DIFF_XDL_TST(options, IGNORE_WHITESPACE_CHANGE) ||
4134-
DIFF_XDL_TST(options, IGNORE_WHITESPACE_AT_EOL))
4132+
if ((options->xdl_opts & XDF_WHITESPACE_FLAGS))
41354133
options->flags.diff_from_contents = 1;
41364134
else
41374135
options->flags.diff_from_contents = 0;
@@ -4588,6 +4586,8 @@ int diff_opt_parse(struct diff_options *options,
45884586
DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
45894587
else if (!strcmp(arg, "--ignore-space-at-eol"))
45904588
DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
4589+
else if (!strcmp(arg, "--ignore-cr-at-eol"))
4590+
DIFF_XDL_SET(options, IGNORE_CR_AT_EOL);
45914591
else if (!strcmp(arg, "--ignore-blank-lines"))
45924592
DIFF_XDL_SET(options, IGNORE_BLANK_LINES);
45934593
else if (!strcmp(arg, "--indent-heuristic"))

merge-recursive.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,6 +2252,8 @@ int parse_merge_opt(struct merge_options *o, const char *s)
22522252
DIFF_XDL_SET(o, IGNORE_WHITESPACE);
22532253
else if (!strcmp(s, "ignore-space-at-eol"))
22542254
DIFF_XDL_SET(o, IGNORE_WHITESPACE_AT_EOL);
2255+
else if (!strcmp(s, "ignore-cr-at-eol"))
2256+
DIFF_XDL_SET(o, IGNORE_CR_AT_EOL);
22552257
else if (!strcmp(s, "renormalize"))
22562258
o->renormalize = 1;
22572259
else if (!strcmp(s, "no-renormalize"))

t/t4015-diff-whitespace.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ test_expect_success 'another test, without options' '
106106
git diff -w -b --ignore-space-at-eol >out &&
107107
test_cmp expect out &&
108108
109+
git diff -w --ignore-cr-at-eol >out &&
110+
test_cmp expect out &&
109111
110112
tr "Q_" "\015 " <<-\EOF >expect &&
111113
diff --git a/x b/x
@@ -128,6 +130,9 @@ test_expect_success 'another test, without options' '
128130
git diff -b --ignore-space-at-eol >out &&
129131
test_cmp expect out &&
130132
133+
git diff -b --ignore-cr-at-eol >out &&
134+
test_cmp expect out &&
135+
131136
tr "Q_" "\015 " <<-\EOF >expect &&
132137
diff --git a/x b/x
133138
index d99af23..22d9f73 100644
@@ -145,6 +150,29 @@ test_expect_success 'another test, without options' '
145150
CR at end
146151
EOF
147152
git diff --ignore-space-at-eol >out &&
153+
test_cmp expect out &&
154+
155+
git diff --ignore-space-at-eol --ignore-cr-at-eol >out &&
156+
test_cmp expect out &&
157+
158+
tr "Q_" "\015 " <<-\EOF >expect &&
159+
diff --git a/x b/x
160+
index_d99af23..22d9f73 100644
161+
--- a/x
162+
+++ b/x
163+
@@ -1,6 +1,6 @@
164+
-whitespace at beginning
165+
-whitespace change
166+
-whitespace in the middle
167+
-whitespace at end
168+
+_ whitespace at beginning
169+
+whitespace_ _change
170+
+white space in the middle
171+
+whitespace at end__
172+
unchanged line
173+
CR at end
174+
EOF
175+
git diff --ignore-cr-at-eol >out &&
148176
test_cmp expect out
149177
'
150178

xdiff/xdiff.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,28 @@
2727
extern "C" {
2828
#endif /* #ifdef __cplusplus */
2929

30+
/* xpparm_t.flags */
31+
#define XDF_NEED_MINIMAL (1 << 0)
32+
33+
#define XDF_IGNORE_WHITESPACE (1 << 1)
34+
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 2)
35+
#define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 3)
36+
#define XDF_IGNORE_CR_AT_EOL (1 << 4)
37+
#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | \
38+
XDF_IGNORE_WHITESPACE_CHANGE | \
39+
XDF_IGNORE_WHITESPACE_AT_EOL | \
40+
XDF_IGNORE_CR_AT_EOL)
3041

31-
#define XDF_NEED_MINIMAL (1 << 1)
32-
#define XDF_IGNORE_WHITESPACE (1 << 2)
33-
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
34-
#define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4)
35-
#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)
42+
#define XDF_IGNORE_BLANK_LINES (1 << 7)
3643

37-
#define XDF_PATIENCE_DIFF (1 << 5)
38-
#define XDF_HISTOGRAM_DIFF (1 << 6)
44+
#define XDF_PATIENCE_DIFF (1 << 14)
45+
#define XDF_HISTOGRAM_DIFF (1 << 15)
3946
#define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF)
4047
#define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK)
4148

42-
#define XDF_IGNORE_BLANK_LINES (1 << 7)
43-
44-
#define XDF_INDENT_HEURISTIC (1 << 8)
49+
#define XDF_INDENT_HEURISTIC (1 << 23)
4550

51+
/* xdemitconf_t.flags */
4652
#define XDL_EMIT_FUNCNAMES (1 << 0)
4753
#define XDL_EMIT_FUNCCONTEXT (1 << 2)
4854

xdiff/xutils.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,24 @@ int xdl_blankline(const char *line, long size, long flags)
156156
return (i == size);
157157
}
158158

159+
/*
160+
* Have we eaten everything on the line, except for an optional
161+
* CR at the very end?
162+
*/
163+
static int ends_with_optional_cr(const char *l, long s, long i)
164+
{
165+
int complete = s && l[s-1] == '\n';
166+
167+
if (complete)
168+
s--;
169+
if (s == i)
170+
return 1;
171+
/* do not ignore CR at the end of an incomplete line */
172+
if (complete && s == i + 1 && l[i] == '\r')
173+
return 1;
174+
return 0;
175+
}
176+
159177
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
160178
{
161179
int i1, i2;
@@ -170,7 +188,8 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
170188

171189
/*
172190
* -w matches everything that matches with -b, and -b in turn
173-
* matches everything that matches with --ignore-space-at-eol.
191+
* matches everything that matches with --ignore-space-at-eol,
192+
* which in turn matches everything that matches with --ignore-cr-at-eol.
174193
*
175194
* Each flavor of ignoring needs different logic to skip whitespaces
176195
* while we have both sides to compare.
@@ -204,6 +223,14 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
204223
i1++;
205224
i2++;
206225
}
226+
} else if (flags & XDF_IGNORE_CR_AT_EOL) {
227+
/* Find the first difference and see how the line ends */
228+
while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) {
229+
i1++;
230+
i2++;
231+
}
232+
return (ends_with_optional_cr(l1, s1, i1) &&
233+
ends_with_optional_cr(l2, s2, i2));
207234
}
208235

209236
/*
@@ -230,9 +257,16 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
230257
char const *top, long flags) {
231258
unsigned long ha = 5381;
232259
char const *ptr = *data;
260+
int cr_at_eol_only = (flags & XDF_WHITESPACE_FLAGS) == XDF_IGNORE_CR_AT_EOL;
233261

234262
for (; ptr < top && *ptr != '\n'; ptr++) {
235-
if (XDL_ISSPACE(*ptr)) {
263+
if (cr_at_eol_only) {
264+
/* do not ignore CR at the end of an incomplete line */
265+
if (*ptr == '\r' &&
266+
(ptr + 1 < top && ptr[1] == '\n'))
267+
continue;
268+
}
269+
else if (XDL_ISSPACE(*ptr)) {
236270
const char *ptr2 = ptr;
237271
int at_eol;
238272
while (ptr + 1 < top && XDL_ISSPACE(ptr[1])

0 commit comments

Comments
 (0)