[PATCH V2] patch: don't separate \r and \n when colorizing diff output

Sune Foldager sune.foldager at me.com
Wed Jul 11 13:03:42 UTC 2018


# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1531314149 -7200
#      Wed Jul 11 15:02:29 2018 +0200
# Node ID dc12175e9e5ba1bcb8ed7658a9218211727a9c49
# Parent  4d5fb4062f0bb159230062701461fa6cab9b539b
patch: don't separate \r and \n when colorizing diff output

When displaying diffs, \r at the end of a line is treated as trailing
whitespace. This causes an ANSI escape code to be inserted between \r and \n.
Some programs, such as less since version 530 (maybe earlier, but at least not
version 487) displays ^M when it encounters a lone \r. This causes a lot of
noise in diff output on Windows, where \r\n is used to terminate lines.

We avoid that by treating both \n and \r\n as end of line when considering
trailing whitespace.

A test case for trailing whitespace has also been added.

diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -2405,7 +2405,7 @@ def diffsinglehunk(hunklines):
     """yield tokens for a list of lines in a single hunk"""
     for line in hunklines:
         # chomp
-        chompline = line.rstrip('\n')
+        chompline = line.rstrip('\r\n')
         # highlight tabs and trailing whitespace
         stripline = chompline.rstrip()
         if line.startswith('-'):
@@ -2473,6 +2473,9 @@ def diffsinglehunkinline(hunklines):
             isendofline = token.endswith('\n')
             if isendofline:
                 chomp = token[:-1] # chomp
+                if chomp.endswith('\r'):
+                    chomp = chomp[:-1]
+                endofline = token[len(chomp):]
                 token = chomp.rstrip() # detect spaces at the end
                 endspaces = chomp[len(token):]
             # scan tabs
@@ -2488,7 +2491,7 @@ def diffsinglehunkinline(hunklines):
             if isendofline:
                 if endspaces:
                     yield (endspaces, 'diff.trailingwhitespace')
-                yield ('\n', '')
+                yield (endofline, '')
                 nextisnewline = True
 
 def difflabel(func, *args, **kw):
diff --git a/tests/test-diff-color.t b/tests/test-diff-color.t
--- a/tests/test-diff-color.t
+++ b/tests/test-diff-color.t
@@ -51,6 +51,25 @@ default context
    a
    c
 
+trailing whitespace
+
+  $ sed -i 's/^dd$/dd \r/' a
+  $ hg diff --nodates
+  \x1b[0;1mdiff -r cf9f4ba66af2 a\x1b[0m (esc)
+  \x1b[0;31;1m--- a/a\x1b[0m (esc)
+  \x1b[0;32;1m+++ b/a\x1b[0m (esc)
+  \x1b[0;35m@@ -2,7 +2,7 @@\x1b[0m (esc)
+   c
+   a
+   a
+  \x1b[0;31m-b\x1b[0m (esc)
+  \x1b[0;32m+dd\x1b[0m\x1b[0;1;41m \x1b[0m\r (esc)
+   a
+   a
+   c
+
+  $ sed -i 's/\s*\r$//' a
+
 (check that 'ui.color=yes' match '--color=auto')
 
   $ hg diff --nodates --config ui.formatted=no


More information about the Mercurial-devel mailing list