Skip to content

Commit e9282f0

Browse files
committed
diff: --ignore-cr-at-eol
A new option --ignore-cr-at-eol tells the diff machinery to treat a carriage-return at the end of a (complete) line as if it does not exist. Just like other "--ignore-*" options to ignore various kinds of whitespace differences, this will help reviewing the real changes you made without getting distracted by spurious CRLF<->LF conversion made by your editor program. Helped-by: Johannes Schindelin <[email protected]> [jch: squashed in command line completion by Dscho] Signed-off-by: Junio C Hamano <[email protected]>
1 parent 446d12c commit e9282f0

File tree

8 files changed

+78
-6
lines changed

8 files changed

+78
-6
lines changed

Documentation/diff-options.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,9 @@ endif::git-format-patch[]
519519
--text::
520520
Treat all files as text.
521521

522+
--ignore-cr-at-eol::
523+
Ignore carrige-return at the end of line when doing a comparison.
524+
522525
--ignore-space-at-eol::
523526
Ignore changes in whitespace at EOL.
524527

Documentation/merge-strategies.txt

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

contrib/completion/git-completion.bash

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

diff.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3888,6 +3888,8 @@ int diff_opt_parse(struct diff_options *options,
38883888
DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
38893889
else if (!strcmp(arg, "--ignore-space-at-eol"))
38903890
DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
3891+
else if (!strcmp(arg, "--ignore-cr-at-eol"))
3892+
DIFF_XDL_SET(options, IGNORE_CR_AT_EOL);
38913893
else if (!strcmp(arg, "--ignore-blank-lines"))
38923894
DIFF_XDL_SET(options, IGNORE_BLANK_LINES);
38933895
else if (!strcmp(arg, "--indent-heuristic"))

merge-recursive.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,8 @@ int parse_merge_opt(struct merge_options *o, const char *s)
22142214
DIFF_XDL_SET(o, IGNORE_WHITESPACE);
22152215
else if (!strcmp(s, "ignore-space-at-eol"))
22162216
DIFF_XDL_SET(o, IGNORE_WHITESPACE_AT_EOL);
2217+
else if (!strcmp(s, "ignore-cr-at-eol"))
2218+
DIFF_XDL_SET(o, IGNORE_CR_AT_EOL);
22172219
else if (!strcmp(s, "renormalize"))
22182220
o->renormalize = 1;
22192221
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: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ extern "C" {
3333
#define XDF_IGNORE_WHITESPACE (1 << 1)
3434
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 2)
3535
#define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 3)
36+
#define XDF_IGNORE_CR_AT_EOL (1 << 4)
3637
#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | \
3738
XDF_IGNORE_WHITESPACE_CHANGE | \
38-
XDF_IGNORE_WHITESPACE_AT_EOL)
39+
XDF_IGNORE_WHITESPACE_AT_EOL | \
40+
XDF_IGNORE_CR_AT_EOL)
3941

4042
#define XDF_IGNORE_BLANK_LINES (1 << 7)
4143

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)