patch: be more tolerant with EOLs in binary diffs (issue2870) stable
authorPatrick Mezard <patrick@mezard.eu>
Thu, 26 Apr 2012 21:44:02 +0200
branchstable
changeset 16524 ed6a74312176
parent 16523 727068417b95
child 16525 b12b65d2cbe4
patch: be more tolerant with EOLs in binary diffs (issue2870) The only place where an trailing CR could be meaningful is in the "diff --git" line as part of a filename, and existing code already rule out this possibility. Extend the CR/LF filtering to the whole binary hunk.
mercurial/patch.py
tests/test-import-git.t
--- a/mercurial/patch.py	Thu Apr 26 21:44:00 2012 +0200
+++ b/mercurial/patch.py	Thu Apr 26 21:44:02 2012 +0200
@@ -1035,18 +1035,20 @@
         return [self.text]
 
     def _read(self, lr):
-        line = lr.readline()
-        self.hunk.append(line)
+        def getline(lr, hunk):
+            l = lr.readline()
+            hunk.append(l)
+            return l.rstrip('\r\n')
+
+        line = getline(lr, self.hunk)
         while line and not line.startswith('literal '):
-            line = lr.readline()
-            self.hunk.append(line)
+            line = getline(lr, self.hunk)
         if not line:
             raise PatchError(_('could not extract "%s" binary data')
                              % self._fname)
         size = int(line[8:].rstrip())
         dec = []
-        line = lr.readline()
-        self.hunk.append(line)
+        line = getline(lr, self.hunk)
         while len(line) > 1:
             l = line[0]
             if l <= 'Z' and l >= 'A':
@@ -1054,12 +1056,11 @@
             else:
                 l = ord(l) - ord('a') + 27
             try:
-                dec.append(base85.b85decode(line[1:-1])[:l])
+                dec.append(base85.b85decode(line[1:])[:l])
             except ValueError, e:
                 raise PatchError(_('could not decode "%s" binary patch: %s')
                                  % (self._fname, str(e)))
-            line = lr.readline()
-            self.hunk.append(line)
+            line = getline(lr, self.hunk)
         text = zlib.decompress(''.join(dec))
         if len(text) != size:
             raise PatchError(_('"%s" length is %d bytes, should be %d')
@@ -1213,7 +1214,7 @@
                 yield 'file', (afile, bfile, h, gp and gp.copy() or None)
             yield 'hunk', h
         elif x.startswith('diff --git'):
-            m = gitre.match(x)
+            m = gitre.match(x.rstrip(' \r\n'))
             if not m:
                 continue
             if gitpatches is None:
--- a/tests/test-import-git.t	Thu Apr 26 21:44:00 2012 +0200
+++ b/tests/test-import-git.t	Thu Apr 26 21:44:02 2012 +0200
@@ -412,6 +412,27 @@
   abort: could not extract "binary2" binary data
   [255]
 
+Simulate a copy/paste turning LF into CRLF (issue2870)
+
+  $ hg revert -aq
+  $ cat > binary.diff <<"EOF"
+  > diff --git a/text2 b/binary2
+  > rename from text2
+  > rename to binary2
+  > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
+  > GIT binary patch
+  > literal 5
+  > Mc$`b*O5$Pw00T?_*Z=?k
+  > 
+  > EOF
+  >>> fp = file('binary.diff', 'rb')
+  >>> data = fp.read()
+  >>> fp.close()
+  >>> file('binary.diff', 'wb').write(data.replace('\n', '\r\n'))
+  $ rm binary2
+  $ hg import --no-commit binary.diff
+  applying binary.diff
+
   $ cd ..
 
 Consecutive import with renames (issue2459)