# HG changeset patch # User Martin von Zweigbergk # Date 2016-02-12 23:18:56 # Node ID abf12026268386310559fdd581b0420343f0bfb3 # Parent 1c36cc8e78709eb403938837473a632874a2cf5e 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. diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py --- a/mercurial/changegroup.py +++ b/mercurial/changegroup.py @@ -659,20 +659,15 @@ class cg1packer(object): 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 @@ class cg1packer(object): 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 @@ class cg3packer(cg2packer): 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(