changeset 28228:abf120262683

changegroup: make _packmanifests() dumber The next few patches will rewrite the manifest generation code to work with merges. We will then walk dirlogs recursively. This prepares for that by moving much of the treemanifest code out of _packmanifests() and into generatemanifests(). For this to work, it also adds _manifestsdone() method that returns the "end of manifests" close chunk for cg3 and an empty string for cg1 and cg2.
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 12 Feb 2016 15:18:56 -0800
parents 1c36cc8e7870
children 8e13b2379407
files mercurial/changegroup.py
diffstat 1 files changed, 24 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/changegroup.py	Thu Feb 11 20:19:48 2016 -0800
+++ b/mercurial/changegroup.py	Fri Feb 12 15:18:56 2016 -0800
@@ -659,20 +659,15 @@
         rr, rl = revlog.rev, revlog.linkrev
         return [n for n in missing if rl(rr(n)) not in commonrevs]
 
-    def _packmanifests(self, mfnodes, tmfnodes, lookuplinknode):
+    def _packmanifests(self, dir, mfnodes, lookuplinknode):
         """Pack flat manifests into a changegroup stream."""
-        ml = self._repo.manifest
-        size = 0
-        for chunk in self.group(
-                mfnodes, ml, lookuplinknode, units=_('manifests')):
-            size += len(chunk)
+        assert not dir
+        for chunk in self.group(mfnodes, self._repo.manifest,
+                                lookuplinknode, units=_('manifests')):
             yield chunk
-        self._verbosenote(_('%8.i (manifests)\n') % size)
-        # It looks odd to assert this here, but tmfnodes doesn't get
-        # filled in until after we've called lookuplinknode for
-        # sending root manifests, so the only way to tell the streams
-        # got crossed is to check after we've done all the work.
-        assert not tmfnodes
+
+    def _manifestsdone(self):
+        return ''
 
     def generate(self, commonrevs, clnodes, fastpathlinkrev, source):
         '''yield a sequence of changegroup chunks (strings)'''
@@ -825,9 +820,15 @@
                 return clnode
 
         mfnodes = self.prune(ml, mfs, commonrevs)
-        for x in self._packmanifests(
-            mfnodes, tmfnodes, lookupmflinknode):
+        size = 0
+        for x in self._packmanifests('', mfnodes, lookupmflinknode):
+            size += len(x)
             yield x
+        self._verbosenote(_('%8.i (manifests)\n') % size)
+        for dir, nodes in tmfnodes.iteritems():
+            for x in self._packmanifests(dir, nodes, nodes.get):
+                yield x
+        yield self._manifestsdone()
 
     # The 'source' parameter is useful for extensions
     def generatefiles(self, changedfiles, linknodes, commonrevs, source):
@@ -928,23 +929,15 @@
     version = '03'
     deltaheader = _CHANGEGROUPV3_DELTA_HEADER
 
-    def _packmanifests(self, mfnodes, tmfnodes, lookuplinknode):
-        # Note that debug prints are super confusing in this code, as
-        # tmfnodes gets populated by the calls to lookuplinknode in
-        # the superclass's manifest packer. In the future we should
-        # probably see if we can refactor this somehow to be less
-        # confusing.
-        for x in super(cg3packer, self)._packmanifests(
-            mfnodes, {}, lookuplinknode):
-            yield x
-        dirlog = self._repo.manifest.dirlog
-        for name, nodes in tmfnodes.iteritems():
-            # For now, directory headers are simply file headers with
-            # a trailing '/' on the path (already in the name).
-            yield self.fileheader(name)
-            for chunk in self.group(nodes, dirlog(name), nodes.get):
-                yield chunk
-        yield self.close()
+    def _packmanifests(self, dir, mfnodes, lookuplinknode):
+        if dir:
+            yield self.fileheader(dir)
+        for chunk in self.group(mfnodes, self._repo.manifest.dirlog(dir),
+                                lookuplinknode, units=_('manifests')):
+            yield chunk
+
+    def _manifestsdone(self):
+        return self.close()
 
     def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
         return struct.pack(