Patchwork [1,of,3,V2] manifest: add treemanifestctx class

login
register
mail settings
Submitter Durham Goode
Date Aug. 31, 2016, 8:30 p.m.
Message ID <abce9af35512d8589683.1472675419@dev8486.prn1.facebook.com>
Download mbox | patch
Permalink /patch/16516/
State Accepted
Headers show

Comments

Durham Goode - Aug. 31, 2016, 8:30 p.m.
# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 1472675389 25200
#      Wed Aug 31 13:29:49 2016 -0700
# Node ID abce9af35512d8589683d94f34f6d8aa21163568
# Parent  318e2b600b80e4ed3c6f37df46ec7544f60d4c0b
manifest: add treemanifestctx class

Before we start using repo.manifestlog in the rest of the code base, we need to
make sure that it's capable of returning treemanifests. As we add new
functionality to manifestctx, we'll add it to treemanifestctx at the same time.

We also comment out the manifestctx p1, p2, and linkrev fields for now, since
we're not implementing them on treemanifest yet.

Patch

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -944,22 +944,20 @@  class manifestlog(object):
         """Retrieves the manifest instance for the given node. Throws a KeyError
         if not found.
         """
-        if (self._oldmanifest._treeondisk
-            or self._oldmanifest._treeinmem):
-            # TODO: come back and support tree manifests directly
-            return self._oldmanifest.read(node)
-
-        if node == revlog.nullid:
-            return manifestdict()
         if node in self._mancache:
             cachemf = self._mancache[node]
             # The old manifest may put non-ctx manifests in the cache, so skip
             # those since they don't implement the full api.
-            if isinstance(cachemf, manifestctx):
+            if (isinstance(cachemf, manifestctx) or
+                isinstance(cachemf, treemanifestctx)):
                 return cachemf
 
-        m = manifestctx(self._revlog, node)
-        self._mancache[node] = m
+        if self._oldmanifest._treeinmem:
+            m = treemanifestctx(self._revlog, '', node)
+        else:
+            m = manifestctx(self._revlog, node)
+        if node != revlog.nullid:
+            self._mancache[node] = m
         return m
 
 class manifestctx(manifestdict):
@@ -970,9 +968,13 @@  class manifestctx(manifestdict):
         self._revlog = revlog
 
         self._node = node
-        self.p1, self.p2 = revlog.parents(node)
-        rev = revlog.rev(node)
-        self.linkrev = revlog.linkrev(rev)
+
+        # TODO: We eventually want p1, p2, and linkrev exposed on this class,
+        # but let's add it later when something needs it and we can load it
+        # lazily.
+        #self.p1, self.p2 = revlog.parents(node)
+        #rev = revlog.rev(node)
+        #self.linkrev = revlog.linkrev(rev)
 
         # This should eventually be made lazy loaded, so consumers can access
         # the node/p1/linkrev data without having to parse the whole manifest.
@@ -984,6 +986,38 @@  class manifestctx(manifestdict):
     def node(self):
         return self._node
 
+class treemanifestctx(treemanifest):
+    def __init__(self, revlog, dir, node):
+        revlog = revlog.dirlog(dir)
+        self._revlog = revlog
+        self._dir = dir
+
+        self._node = node
+
+        # TODO: Load p1/p2/linkrev lazily. They need to be lazily loaded so that
+        # we can instantiate treemanifestctx objects for directories we don't
+        # have on disk.
+        #self.p1, self.p2 = revlog.parents(node)
+        #rev = revlog.rev(node)
+        #self.linkrev = revlog.linkrev(rev)
+
+        if revlog._treeondisk:
+            super(treemanifestctx, self).__init__(dir=dir)
+            def gettext():
+                return revlog.revision(node)
+            def readsubtree(dir, subm):
+                return revlog.dirlog(dir).read(subm)
+            self.read(gettext, readsubtree)
+            self.setnode(node)
+        else:
+            text = revlog.revision(node)
+            arraytext = array.array('c', text)
+            revlog.fulltextcache[node] = arraytext
+            super(treemanifestctx, self).__init__(dir=dir, text=text)
+
+    def node(self):
+        return self._node
+
 class manifest(manifestrevlog):
     def __init__(self, opener, dir='', dirlogcache=None):
         '''The 'dir' and 'dirlogcache' arguments are for internal use by