manifest: make treemanifestctx store the repo stable
authorDurham Goode <durham@fb.com>
Tue, 18 Oct 2016 17:44:42 -0700
branchstable
changeset 30221 f2c5b9d48b29
parent 30220 acc8885a6450
child 30222 7b428b00a1d4
manifest: make treemanifestctx store the repo Same as in the last commit, the old treemanifestctx stored a reference to the revlog. If the inmemory revlog became invalid, the ctx now held an old copy and would be incorrect. To fix this, we need the ctx to go through the manifestlog for each access. This is the same pattern that changectx already uses (it stores the repo, and accesses commit data through self._repo.changelog).
mercurial/manifest.py
--- a/mercurial/manifest.py	Tue Oct 18 17:44:26 2016 -0700
+++ b/mercurial/manifest.py	Tue Oct 18 17:44:42 2016 -0700
@@ -1274,7 +1274,7 @@
                 return cachemf
 
         if self._treeinmem:
-            m = treemanifestctx(self._revlog, '', node)
+            m = treemanifestctx(self._repo, '', node)
         else:
             m = manifestctx(self._repo, node)
         if node != revlog.nullid:
@@ -1344,9 +1344,8 @@
         return manifestdict(d)
 
 class treemanifestctx(object):
-    def __init__(self, revlog, dir, node):
-        revlog = revlog.dirlog(dir)
-        self._revlog = revlog
+    def __init__(self, repo, dir, node):
+        self._repo = repo
         self._dir = dir
         self._data = None
 
@@ -1359,23 +1358,27 @@
         #rev = revlog.rev(node)
         #self.linkrev = revlog.linkrev(rev)
 
+    def _revlog(self):
+        return self._repo.manifestlog._revlog.dirlog(self._dir)
+
     def read(self):
         if not self._data:
+            rl = self._revlog()
             if self._node == revlog.nullid:
                 self._data = treemanifest()
-            elif self._revlog._treeondisk:
+            elif rl._treeondisk:
                 m = treemanifest(dir=self._dir)
                 def gettext():
-                    return self._revlog.revision(self._node)
+                    return rl.revision(self._node)
                 def readsubtree(dir, subm):
-                    return treemanifestctx(self._revlog, dir, subm).read()
+                    return treemanifestctx(self._repo, dir, subm).read()
                 m.read(gettext, readsubtree)
                 m.setnode(self._node)
                 self._data = m
             else:
-                text = self._revlog.revision(self._node)
+                text = revlog.revision(self._node)
                 arraytext = array.array('c', text)
-                self._revlog.fulltextcache[self._node] = arraytext
+                rl.fulltextcache[self._node] = arraytext
                 self._data = treemanifest(dir=self._dir, text=text)
 
         return self._data
@@ -1385,9 +1388,9 @@
 
     def readdelta(self):
         # Need to perform a slow delta
-        revlog = self._revlog
+        revlog = self._revlog()
         r0 = revlog.deltaparent(revlog.rev(self._node))
-        m0 = treemanifestctx(revlog, self._dir, revlog.node(r0)).read()
+        m0 = treemanifestctx(self._repo, self._dir, revlog.node(r0)).read()
         m1 = self.read()
         md = treemanifest(dir=self._dir)
         for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).iteritems():
@@ -1398,7 +1401,7 @@
         return md
 
     def readfast(self):
-        rl = self._revlog
+        rl = self._revlog()
         r = rl.rev(self._node)
         deltaparent = rl.deltaparent(r)
         if deltaparent != revlog.nullrev and deltaparent in rl.parentrevs(r):