[PATCH 2 of 2] patch: implement patch.eol=auto mode

Martin Geisler mg at lazybytes.net
Wed Dec 9 17:52:47 CST 2009


# HG changeset patch
# User Martin Geisler <mg at lazybytes.net>
# Date 1260402691 -3600
# Node ID 4a5fe81023b1866d91700bad776c3ab8f2b629a1
# Parent  4d2968aed1f9042a50f9e7088f8fdc3201f6e4f5
patch: implement patch.eol=auto mode

diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -239,6 +239,7 @@
         self.fp = fp
         self.buf = []
         self.textmode = textmode
+        self.newlines = None
 
     def push(self, line):
         if line is not None:
@@ -250,6 +251,11 @@
             del self.buf[0]
             return l
         l = self.fp.readline()
+        if not self.newlines:
+            if l.endswith('\r\n'):
+                self.newlines = '\r\n'
+            elif l.endswith('\n'):
+                self.newlines = '\n'
         if self.textmode and l.endswith('\r\n'):
             l = l[:-2] + '\n'
         return l
@@ -264,13 +270,13 @@
 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
-eolmodes = ['strict', 'crlf', 'lf']
+eolmodes = ['strict', 'crlf', 'lf', 'auto']
 
 class patchfile(object):
     def __init__(self, ui, fname, opener, missing=False, eolmode='strict'):
         self.fname = fname
         self.eolmode = eolmode
-        self.eol = {'strict': None, 'crlf': '\r\n', 'lf': '\n'}[eolmode]
+        self.newlines = None
         self.opener = opener
         self.ui = ui
         self.lines = []
@@ -298,7 +304,10 @@
             return [os.readlink(fname)]
         fp = self.opener(fname, 'r')
         try:
-            return list(linereader(fp, self.eolmode != 'strict'))
+            lr = linereader(fp, self.eolmode != 'strict')
+            lines = list(lr)
+            self.newlines = lr.newlines
+            return lines
         finally:
             fp.close()
 
@@ -312,10 +321,17 @@
         else:
             fp = self.opener(fname, 'w')
         try:
-            if self.eol and self.eol != '\n':
+            if self.eolmode == 'auto' and self.newlines:
+                eol = self.newlines
+            elif self.eolmode == 'crlf':
+                eol = '\r\n'
+            else:
+                eol = '\n'
+
+            if self.eolmode != 'strict' and eol != '\n':
                 for l in lines:
                     if l and l[-1] == '\n':
-                        l = l[:-1] + self.eol
+                        l = l[:-1] + eol
                     fp.write(l)
             else:
                 fp.writelines(lines)
diff --git a/tests/test-import-eol b/tests/test-import-eol
--- a/tests/test-import-eol
+++ b/tests/test-import-eol
@@ -28,19 +28,36 @@
 python -c 'file("a", "wb").write("a\nbbb\ncc\n\nd\ne")'
 hg ci -Am adda
 python ../makepatch.py
+
 echo % invalid eol
 hg --config patch.eol='LFCR' import eol.diff
 hg revert -a
+
 echo % force LF
 hg --traceback --config patch.eol='LF' import eol.diff
 python -c 'print repr(file("a","rb").read())'
 hg st
+
 echo % force CRLF
 hg up -C 0
 hg --traceback --config patch.eol='CRLF' import eol.diff
 python -c 'print repr(file("a","rb").read())'
 hg st
 
+echo % auto EOL on LF file
+hg up -C 0
+hg --traceback --config patch.eol='auto' import eol.diff
+python -c 'print repr(file("a","rb").read())'
+hg st
+
+echo % auto EOL on CRLF file
+python -c 'file("a", "wb").write("a\r\nbbb\ncc\r\n\r\nd\r\ne")'
+hg commit -m 'switch EOLs in a'
+hg --traceback --config patch.eol='auto' import eol.diff
+python -c 'print repr(file("a","rb").read())'
+hg st
+
+
 # Test --eol and binary patches
 python -c 'file("b", "wb").write("a\x00\nb")'
 hg ci -Am addb


More information about the Mercurial-devel mailing list