git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 2/2] diff: --ignore-cr-at-eol

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Nov 7, 2017, 13:23 UTC
Message-ID
<alpine.DEB.2.21.1.1711071345430.6482@virtualbox>
In-Reply-To
<20171107064011.18399-3-gitster@pobox.com>
Hi Junio,
On Tue, 7 Nov 2017, Junio C Hamano wrote:
Show 6 quoted lines
> 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.
> 
> This would make it easier to review a change whose only effect is to
> turn line endings from CRLF to LF or the other way around.

If the goal is to make CR/LF -> LF conversions easier to review (or for that matter, LF -> CR/LF), then this option may not be *completely* satisfactory, as it would hide mixed changes (i.e. where some lines are converted from CR/LF to LF and others are converted in the other direction *in the same patch*).

I wonder whether it would make this patch series even more useful if you would instead introduce --hide-crlf-to-lf and --hide-lf-to-crlf options (not even necessarily mutually exclusive, in case the reviewer really wants to ignore all line ending conversions).

Show 10 quoted lines
> diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
> index 89cc0f48de..aa2c0ff74d 100644
> --- a/Documentation/diff-options.txt
> +++ b/Documentation/diff-options.txt
> @@ -519,6 +519,9 @@ endif::git-format-patch[]
>  --text::
>  	Treat all files as text.
>  
> +--ignore-cr-at-eol::
> +	Ignore carrige-return at the end of line when doing a comparison.

I am not a native speaker, either, yet I have the impression that "do a comparison" may be more colloquial than not. Also, it is a carriage-return (as in Sinatra's famous song about Love and Marriage) not a carrige-return.

How about "Hide changed line endings"?
Show 20 quoted lines
> diff --git a/xdiff/xutils.c b/xdiff/xutils.c
> index 04d7b32e4e..b2cbcc818f 100644
> --- a/xdiff/xutils.c
> +++ b/xdiff/xutils.c
> @@ -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;
What is the role of `s`, what of `i`? Maybe `length` and `current_offset`?
> +	/* do not ignore CR at the end of an incomplete line */
> +	if (complete && s == i + 1 && l[i] == '\r')
> +		return 1;

This made me scratch my head: too many negations. The comment may better read "ignore CR only at the end of a complete line".

And now I understand even less why `1` is returned if `s == i`? Is this not an empty line (complete or incomplete) *without* a CR?

Show 12 quoted lines
> @@ -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));
There are extra parentheses around the `return` expression.

To accommodate the tentative --hide-crlf-to-lf and --hide-lf-to-crlf options that I suggested earlier, this would simply become something like this:

	} else if (flags & (XDF_IGNORE_CRLF_TO_LF | XDF_IGNORE_LF_TO_CRLF)) {
		/* Early exit: length must be equal or differ by 1 */
		if (s1 - i1 != s2 - i2 &&
		    s1 - i1 != s2 + 1 - i2 && s1 + 1 - i1 != s2 - i2)
			return 0;
		/* Early exit: skip incomplete lines */
		if (!s1 || !s2 || l1[s1-1] != '\n' || l2[s2-1] != '\n')
			return 0;
		/* Find the first difference and see how the line ends */
		while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) {
			i1++;
			i2++;
		}
		/* Lines must be identical or have the indicated EOL change */
		return ((i1 == s1 && i2 == s2) ||
			((flags & XDF_IGNORE_CRLF_TO_LF) &&
			 i1 + 2 == s1 && l1[i1] == '\r' && i2 + 1 == s2) ||
			((flags & XDF_IGNORE_LF_TO_CRLF) &&
			 i1 + 1 == s1 && i2 + 2 == s2 && l2[i2] == '\r');
Note: I do not even know whether the code in this function has to assume
that the lines can be byte-wise identical or not, I just erred on the side
of caution. I also do not know whether the return value 0 indicates a
mistmatch, I just assumed it did. I really wish that I could have reviewed
the real code, not a patch in a mail program that lacks the context.

Caveat emptor: my proposed code change has been written in the mail program (if we had a more code-centric review process, you would have a PR with a suggested alternative already, I am really sorry for the inconvenience).

Ciao, Dscho

Previous: Junio C HamanoNext: Junio C Hamano
Message 20 of 44 in “Consequences of CRLF in index?”
  1. Lars SchneiderOct 24, 2017
  2. Jonathan NiederOct 24, 2017
  3. Torsten BögershausenOct 24, 2017
  4. Johannes SchindelinOct 25, 2017
  5. Junio C HamanoOct 25, 2017
  6. Junio C HamanoOct 25, 2017
  7. Stefan BellerOct 25, 2017
  8. Junio C HamanoOct 26, 2017
  9. Re* Consequences of CRLF in index?Junio C Hamano, Oct 27, 2017
  10. Stefan BellerOct 27, 2017
  11. 0/2 Re* Consequences of CRLF in index?Stefan Beller, Oct 27, 2017
  12. 1/2 xdiff/xdiff.h: remove unused flagsStefan Beller, Oct 27, 2017
  13. 2/2 xdiff/xdiffi.c: remove unneeded function declarationsStefan Beller, Oct 27, 2017
  14. Stefan BellerOct 30, 2017
  15. Junio C HamanoOct 31, 2017
  16. Stefan BellerOct 31, 2017
  17. Jeff KingOct 31, 2017
  18. 0/2 Teach "diff" to ignore only CR at EOLJunio C Hamano, Nov 7, 2017
  19. 2/2 diff: --ignore-cr-at-eolJunio C Hamano, Nov 7, 2017
  20. Johannes SchindelinNov 7, 2017
  21. Junio C HamanoNov 8, 2017
  22. Junio C HamanoNov 8, 2017
  23. Junio C HamanoNov 15, 2017
  24. 1/2 xdiff: reassign xpparm_t.flags bitsJunio C Hamano, Nov 7, 2017
  25. Johannes SchindelinNov 7, 2017
  26. Junio C HamanoNov 7, 2017
  27. Johannes SchindelinNov 7, 2017
  28. Junio C HamanoNov 7, 2017
  29. Stefan BellerNov 7, 2017
  30. Lars SchneiderOct 25, 2017
  31. Jonathan NiederOct 25, 2017
  32. Lars SchneiderOct 26, 2017
  33. Torsten BögershausenOct 26, 2017
  34. Johannes SixtOct 24, 2017
  35. Johannes SchindelinOct 25, 2017
  36. Johannes SixtOct 26, 2017
  37. Lars SchneiderOct 26, 2017
  38. Torsten BögershausenOct 26, 2017
  39. Johannes SixtOct 26, 2017
  40. Jonathan NiederOct 26, 2017
  41. Johannes SixtOct 26, 2017
  42. Ross KabusOct 26, 2017
  43. Junio C HamanoOct 27, 2017
  44. Johannes SchindelinOct 27, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.