# HG changeset patch # User FUJIWARA Katsunori # Date 2016-09-22 12:51:58 # Node ID b5e5ddf48bd2650efe06d31551214498c0d5d572 # Parent 9766d88c2465a5febc46265ea74bf3b7618c2654 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 diff --git a/mercurial/changelog.py b/mercurial/changelog.py --- a/mercurial/changelog.py +++ b/mercurial/changelog.py @@ -124,7 +124,7 @@ class appender(object): 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 _divertopener(opener, target): 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) diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -212,8 +212,11 @@ class revlog(object): 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 @@ class revlog(object): 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 @@ class revlog(object): 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 @@ class revlog(object): 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 @@ class revlog(object): 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 @@ class revlog(object): # 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()