revlog: specify checkambig at writing to avoid file stat ambiguity
authorFUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Thu, 22 Sep 2016 21:51:58 +0900
changeset 29997 b5e5ddf48bd2
parent 29996 9766d88c2465
child 29998 14ad8e2a4abe
revlog: specify checkambig at writing to avoid file stat ambiguity This allows revlog-style files to be written out with checkambig=True easily. Because avoiding file stat ambiguity is needed only for filecache-ed manifest and changelog, this patch does: - use False for default value of checkambig - focus only on writing changes of index file out This patch also adds optional argument checkambig to _divert/_delay for changelog, to safely accept checkambig specified in revlog layer. But this argument can be fully ignored, because: - changes are written into other than index file, if name != target - changes are never written into index file, otherwise (into pending file by _divert, or into in-memory buffer by _delay) This is a part of ExactCacheValidationPlan. https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
mercurial/changelog.py
mercurial/revlog.py
--- a/mercurial/changelog.py	Thu Sep 22 21:51:57 2016 +0900
+++ b/mercurial/changelog.py	Thu Sep 22 21:51:58 2016 +0900
@@ -124,7 +124,7 @@
 
 def _divertopener(opener, target):
     """build an opener that writes in 'target.a' instead of 'target'"""
-    def _divert(name, mode='r'):
+    def _divert(name, mode='r', checkambig=False):
         if name != target:
             return opener(name, mode)
         return opener(name + ".a", mode)
@@ -132,7 +132,7 @@
 
 def _delayopener(opener, target, buf):
     """build an opener that stores chunks in 'buf' instead of 'target'"""
-    def _delay(name, mode='r'):
+    def _delay(name, mode='r', checkambig=False):
         if name != target:
             return opener(name, mode)
         return appender(opener, name, mode, buf)
--- a/mercurial/revlog.py	Thu Sep 22 21:51:57 2016 +0900
+++ b/mercurial/revlog.py	Thu Sep 22 21:51:58 2016 +0900
@@ -212,8 +212,11 @@
     fashion, which means we never need to rewrite a file to insert or
     remove data, and can use some simple techniques to avoid the need
     for locking while reading.
+
+    If checkambig, indexfile is opened with checkambig=True at
+    writing, to avoid file stat ambiguity.
     """
-    def __init__(self, opener, indexfile):
+    def __init__(self, opener, indexfile, checkambig=False):
         """
         create a revlog object
 
@@ -223,6 +226,9 @@
         self.indexfile = indexfile
         self.datafile = indexfile[:-2] + ".d"
         self.opener = opener
+        #  When True, indexfile is opened with checkambig=True at writing, to
+        #  avoid file stat ambiguity.
+        self._checkambig = checkambig
         # 3-tuple of (node, rev, text) for a raw revision.
         self._cache = None
         # Maps rev to chain base rev.
@@ -1276,7 +1282,8 @@
         finally:
             df.close()
 
-        fp = self.opener(self.indexfile, 'w', atomictemp=True)
+        fp = self.opener(self.indexfile, 'w', atomictemp=True,
+                         checkambig=self._checkambig)
         self.version &= ~(REVLOGNGINLINEDATA)
         self._inline = False
         for i in self:
@@ -1319,7 +1326,7 @@
         dfh = None
         if not self._inline:
             dfh = self.opener(self.datafile, "a+")
-        ifh = self.opener(self.indexfile, "a+")
+        ifh = self.opener(self.indexfile, "a+", checkambig=self._checkambig)
         try:
             return self._addrevision(node, text, transaction, link, p1, p2,
                                      REVIDX_DEFAULT_FLAGS, cachedelta, ifh, dfh)
@@ -1567,7 +1574,7 @@
         end = 0
         if r:
             end = self.end(r - 1)
-        ifh = self.opener(self.indexfile, "a+")
+        ifh = self.opener(self.indexfile, "a+", checkambig=self._checkambig)
         isize = r * self._io.size
         if self._inline:
             transaction.add(self.indexfile, end + isize, r)
@@ -1641,7 +1648,8 @@
                     # reopen the index
                     ifh.close()
                     dfh = self.opener(self.datafile, "a+")
-                    ifh = self.opener(self.indexfile, "a+")
+                    ifh = self.opener(self.indexfile, "a+",
+                                      checkambig=self._checkambig)
         finally:
             if dfh:
                 dfh.close()