diff mercurial/util.py @ 29201:a109bf7e0dc2

util: make atomictempfile avoid ambiguity of file stat if needed Ambiguity check is executed at close(), only if: - atomictempfile is created with checkambig=True, and - target file exists before renaming This restriction avoids performance decrement by needless examination of file stat (for example, filelog doesn't need exact cache validation, even though it uses atomictempfile to write changes out). See description of filestat class for detail about why the logic in this patch works as expected. This patch is a part of preparation for "Exact Cache Validation Plan": https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Thu, 19 May 2016 00:20:38 +0900
parents ca4065028e00
children ce2d81aafbae
line wrap: on
line diff
--- a/mercurial/util.py	Thu May 19 00:20:37 2016 +0900
+++ b/mercurial/util.py	Thu May 19 00:20:38 2016 +0900
@@ -1453,11 +1453,12 @@
     visible. If the object is destroyed without being closed, all your
     writes are discarded.
     '''
-    def __init__(self, name, mode='w+b', createmode=None):
+    def __init__(self, name, mode='w+b', createmode=None, checkambig=False):
         self.__name = name      # permanent name
         self._tempname = mktempcopy(name, emptyok=('w' in mode),
                                     createmode=createmode)
         self._fp = posixfile(self._tempname, mode)
+        self._checkambig = checkambig
 
         # delegated methods
         self.write = self._fp.write
@@ -1468,7 +1469,17 @@
     def close(self):
         if not self._fp.closed:
             self._fp.close()
-            rename(self._tempname, localpath(self.__name))
+            filename = localpath(self.__name)
+            oldstat = self._checkambig and filestat(filename)
+            if oldstat and oldstat.stat:
+                rename(self._tempname, filename)
+                newstat = filestat(filename)
+                if newstat.isambig(oldstat):
+                    # stat of changed file is ambiguous to original one
+                    advanced = (oldstat.stat.st_mtime + 1) & 0x7fffffff
+                    os.utime(filename, (advanced, advanced))
+            else:
+                rename(self._tempname, filename)
 
     def discard(self):
         if not self._fp.closed: