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
This commit is contained in:
Junio C Hamano
2017-11-27 11:06:31 +09:00
8 changed files with 93 additions and 19 deletions

View File

@ -156,6 +156,24 @@ int xdl_blankline(const char *line, long size, long flags)
return (i == size);
}
/*
* Have we eaten everything on the line, except for an optional
* CR at the very end?
*/
static int ends_with_optional_cr(const char *l, long s, long i)
{
int complete = s && l[s-1] == '\n';
if (complete)
s--;
if (s == i)
return 1;
/* do not ignore CR at the end of an incomplete line */
if (complete && s == i + 1 && l[i] == '\r')
return 1;
return 0;
}
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
{
int i1, i2;
@ -170,7 +188,8 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
/*
* -w matches everything that matches with -b, and -b in turn
* matches everything that matches with --ignore-space-at-eol.
* matches everything that matches with --ignore-space-at-eol,
* which in turn matches everything that matches with --ignore-cr-at-eol.
*
* Each flavor of ignoring needs different logic to skip whitespaces
* 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)
i1++;
i2++;
}
} else if (flags & XDF_IGNORE_CR_AT_EOL) {
/* Find the first difference and see how the line ends */
while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) {
i1++;
i2++;
}
return (ends_with_optional_cr(l1, s1, i1) &&
ends_with_optional_cr(l2, s2, i2));
}
/*
@ -230,9 +257,16 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
char const *top, long flags) {
unsigned long ha = 5381;
char const *ptr = *data;
int cr_at_eol_only = (flags & XDF_WHITESPACE_FLAGS) == XDF_IGNORE_CR_AT_EOL;
for (; ptr < top && *ptr != '\n'; ptr++) {
if (XDL_ISSPACE(*ptr)) {
if (cr_at_eol_only) {
/* do not ignore CR at the end of an incomplete line */
if (*ptr == '\r' &&
(ptr + 1 < top && ptr[1] == '\n'))
continue;
}
else if (XDL_ISSPACE(*ptr)) {
const char *ptr2 = ptr;
int at_eol;
while (ptr + 1 < top && XDL_ISSPACE(ptr[1])