[PATCH] util: refactor opener

Adrian Buehlmann adrian at cadifra.com
Thu Nov 4 08:45:45 CDT 2010


# HG changeset patch
# User Adrian Buehlmann <adrian at cadifra.com>
# Date 1288857877 -3600
# Node ID 1fe20f15a22b08aedfdc2b6d21a2d441706f314e
# Parent  a419cb2395d5d8167d58f9466d2bee34e87d6b3a
util: refactor opener

- Don't call atomictempfile or nlinks() if the path is malformed
  (no basename). Let posixfile() raise IOError directly.
- atomictempfile already breaks up hardlinks, no need to poke
  at the file with nlinks() if atomictemp.
- No need to copy the file contents to break hardlinks for 'w'rite
  modes (w, wb, w+, w+b). Unlinking and recreating the file is faster.

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -858,23 +858,34 @@ class opener(object):
             mode += "b" # for that other OS
 
         nlink = -1
-        if mode not in ("r", "rb"):
+        st_mode = None
+        dirname, basename = os.path.split(f)
+        # If basename is empty, then the path is malformed because it points
+        # to a directory. Let the posixfile() call below raise IOError.
+        if basename and mode not in ('r', 'rb'):
+            if atomictemp:
+                if not os.path.isdir(dirname):
+                    makedirs(dirname, self.createmode)
+                return atomictempfile(f, mode, self.createmode)
             try:
-                nlink = nlinks(f)
+                if 'w' in mode:
+                    st_mode = os.lstat(f).st_mode & 0777
+                    os.unlink(f)
+                    nlink = 0
+                else:
+                    nlink = nlinks(f)
             except OSError:
                 nlink = 0
-                dirname, basename = os.path.split(f)
-                # Avoid calling makedirs when the path points to a
-                # directory -- the open will raise IOError below.
-                if basename and not os.path.isdir(dirname):
+                if not os.path.isdir(dirname):
                     makedirs(dirname, self.createmode)
-            if atomictemp:
-                return atomictempfile(f, mode, self.createmode)
             if nlink > 1:
                 rename(mktempcopy(f), f)
         fp = posixfile(f, mode)
         if nlink == 0:
-            self._fixfilemode(f)
+            if st_mode is None:
+                self._fixfilemode(f)
+            else:
+                os.chmod(f, st_mode)
         return fp
 
     def symlink(self, src, dst):


More information about the Mercurial-devel mailing list