diff mercurial/patch.py @ 14391:1e64e1e12195

patch: unify backend file access interface - Rename readlines() into getfile(), return data and mode - Make setfile() write a data buffer instead of lines, make mode mandatory.
author Patrick Mezard <pmezard@gmail.com>
date Thu, 19 May 2011 22:49:43 +0200
parents ce77c275bec3
children bb5cbc16349e
line wrap: on
line diff
--- a/mercurial/patch.py	Thu May 19 22:44:01 2011 +0200
+++ b/mercurial/patch.py	Thu May 19 22:49:43 2011 +0200
@@ -366,16 +366,16 @@
     def __init__(self, ui):
         self.ui = ui
 
-    def readlines(self, fname):
-        """Return target file lines, or its content as a single line
-        for symlinks.
+    def getfile(self, fname):
+        """Return target file data and flags as a (data, (islink,
+        isexec)) tuple.
         """
         raise NotImplementedError
 
-    def setfile(self, fname, lines, mode):
-        """Write lines to target file. mode is a (islink, isexec)
-        tuple, or None if there is no mode information. If lines is None,
-        the file must exists and its content is left unchanged.
+    def setfile(self, fname, data, mode):
+        """Write data to target file fname and set its mode. mode is a
+        (islink, isexec) tuple. If data is None, the file content should
+        be left unchanged.
         """
         raise NotImplementedError
 
@@ -408,35 +408,28 @@
     def _join(self, f):
         return os.path.join(self.opener.base, f)
 
-    def readlines(self, fname):
-        if os.path.islink(self._join(fname)):
-            return [os.readlink(self._join(fname))]
-        fp = self.opener(fname, 'r')
+    def getfile(self, fname):
+        path = self._join(fname)
+        if os.path.islink(path):
+            return (os.readlink(path), (True, False))
+        isexec, islink = False, False
         try:
-            return list(fp)
-        finally:
-            fp.close()
+            isexec = os.lstat(path).st_mode & 0100 != 0
+            islink = os.path.islink(path)
+        except OSError, e:
+            if e.errno != errno.ENOENT:
+                raise
+        return (self.opener.read(fname), (islink, isexec))
 
-    def setfile(self, fname, lines, mode):
-        if lines is None:
-            if mode:
-                util.setflags(self._join(fname), mode[0], mode[1])
+    def setfile(self, fname, data, mode):
+        islink, isexec = mode
+        if data is None:
+            util.setflags(self._join(fname), islink, isexec)
             return
-        if not mode:
-            # Preserve mode information
-            isexec, islink = False, False
-            try:
-                isexec = os.lstat(self._join(fname)).st_mode & 0100 != 0
-                islink = os.path.islink(self._join(fname))
-            except OSError, e:
-                if e.errno != errno.ENOENT:
-                    raise
+        if islink:
+            self.opener.symlink(data, fname)
         else:
-            islink, isexec = mode
-        if islink:
-            self.opener.symlink(''.join(lines), fname)
-        else:
-            self.opener(fname, 'w').writelines(lines)
+            self.opener.write(fname, data)
             if isexec:
                 util.setflags(self._join(fname), False, True)
 
@@ -485,8 +478,8 @@
         self.changed = set()
         self.copied = []
 
-    def setfile(self, fname, lines, mode):
-        super(workingbackend, self).setfile(fname, lines, mode)
+    def setfile(self, fname, data, mode):
+        super(workingbackend, self).setfile(fname, data, mode)
         self.changed.add(fname)
 
     def unlink(self, fname):
@@ -534,7 +527,11 @@
         self.mode = mode
         if not missing:
             try:
-                self.lines = self.backend.readlines(fname)
+                data, mode = self.backend.getfile(fname)
+                if data:
+                    self.lines = data.splitlines(True)
+                if self.mode is None:
+                    self.mode = mode
                 if self.lines:
                     # Normalize line endings
                     if self.lines[0].endswith('\r\n'):
@@ -550,7 +547,8 @@
                         self.lines = nlines
                 self.exists = True
             except IOError:
-                pass
+                if self.mode is None:
+                    self.mode = (False, False)
         else:
             self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
 
@@ -579,7 +577,7 @@
                 rawlines.append(l)
             lines = rawlines
 
-        self.backend.setfile(fname, lines, mode)
+        self.backend.setfile(fname, ''.join(lines), mode)
 
     def printfile(self, warn):
         if self.fileprinted:
@@ -1250,7 +1248,7 @@
                     if gp.op == 'ADD':
                         # Added files without content have no hunk and
                         # must be created
-                        data = []
+                        data = ''
                     backend.setfile(path, data, gp.mode)
             if not first_hunk:
                 continue