[PATCH 04 of 10 v2] bundle-ng: move gengroup into bundler, pass repo object to bundler

Benoit Boissinot benoit.boissinot at ens-lyon.org
Fri May 10 16:59:52 CDT 2013


# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1368214549 -7200
#      Fri May 10 21:35:49 2013 +0200
# Node ID dd33840e6a4646a6e50ae21e0d9b256434a9a8ed
# Parent  d45b76f806d474b3a9d493d257626e02fff625c8
bundle-ng: move gengroup into bundler, pass repo object to bundler

No semantic changes made.

diff --git a/contrib/shrink-revlog.py b/contrib/shrink-revlog.py
--- a/contrib/shrink-revlog.py
+++ b/contrib/shrink-revlog.py
@@ -100,7 +100,7 @@
     result.reverse()
     return result
 
-def writerevs(ui, r1, r2, order, tr):
+def writerevs(ui, repo, r1, r2, order, tr):
 
     ui.status(_('writing revs\n'))
 
@@ -117,7 +117,7 @@
     unlookup = lambda x: int(x, 10)
 
     try:
-        bundler = changegroup.bundle10()
+        bundler = changegroup.bundle10(repo)
         bundler.start(lookup)
         group = util.chunkbuffer(bundler.group(order, r1))
         group = changegroup.unbundle10(group, "UN")
@@ -238,7 +238,7 @@
                     suboptimal += 1
             ui.note(_('%d suboptimal nodes\n') % suboptimal)
 
-            writerevs(ui, r1, r2, order, tr)
+            writerevs(ui, repo, r1, r2, order, tr)
             report(ui, r1, r2)
             tr.close()
         except: # re-raises
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-from node import nullrev
+from node import nullrev, hex
 import mdiff, util, dagutil
 import struct, os, bz2, zlib, tempfile
 
@@ -225,11 +225,26 @@
 
 class bundle10(object):
     deltaheader = _BUNDLE10_DELTA_HEADER
-    def __init__(self, bundlecaps=None):
+    def __init__(self, repo, bundlecaps=None):
+        """Given a source repo, construct a bundler.
+
+        bundlecaps is optional and can be used to specify the set of
+        capabilities which can be used to build the bundle.
+        """
         # Set of capabilities we can use to build the bundle.
         if bundlecaps is None:
             bundlecaps = set()
         self._bundlecaps = bundlecaps
+        self._changelog = repo.changelog
+        self._manifest = repo.manifest
+        reorder = repo.ui.config('bundle', 'reorder', 'auto')
+        if reorder == 'auto':
+            reorder = None
+        else:
+            reorder = util.parsebool(reorder)
+        self._repo = repo
+        self._reorder = reorder
+        self.count = [0, 0]
     def start(self, lookup):
         self._lookup = lookup
     def close(self):
@@ -276,6 +291,43 @@
 
         yield self.close()
 
+    def generate(self, clnodes, getmfnodes, getfiles, getfilenodes, source):
+        '''yield a sequence of changegroup chunks (strings)'''
+        repo = self._repo
+        cl = self._changelog
+        mf = self._manifest
+        reorder = self._reorder
+        progress = repo.ui.progress
+        count = self.count
+        _bundling = _('bundling')
+
+        count[:] = [0, len(clnodes)]
+        for chunk in self.group(clnodes, cl, reorder=reorder):
+            yield chunk
+        progress(_bundling, None)
+
+        for chunk in self.group(getmfnodes(), mf, reorder=reorder):
+            yield chunk
+        progress(_bundling, None)
+
+        changedfiles = getfiles()
+        count[:] = [0, len(changedfiles)]
+        for fname in sorted(changedfiles):
+            filerevlog = repo.file(fname)
+            if not len(filerevlog):
+                raise util.Abort(_("empty or missing revlog for %s")
+                                 % fname)
+            nodelist = getfilenodes(fname, filerevlog)
+            if nodelist:
+                count[0] += 1
+                yield self.fileheader(fname)
+                for chunk in self.group(nodelist, filerevlog, reorder):
+                    yield chunk
+        yield self.close()
+        progress(_bundling, None)
+
+        if clnodes:
+            repo.hook('outgoing', node=hex(clnodes[0]), source=source)
 
     def revchunk(self, revlog, rev, prev):
         node = revlog.node(rev)
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1844,7 +1844,7 @@
                     if revs is None and not outgoing.excluded:
                         # push everything,
                         # use the fast path, no race possible on push
-                        bundler = changegroup.bundle10(bundlecaps)
+                        bundler = changegroup.bundle10(self, bundlecaps)
                         cg = self._changegroup(outgoing.missing, bundler,
                                                'push')
                     else:
@@ -1992,7 +1992,7 @@
         csets, bases, heads = cl.nodesbetween(bases, heads)
         # We assume that all ancestors of bases are known
         common = cl.ancestors([cl.rev(n) for n in bases])
-        bundler = changegroup.bundle10()
+        bundler = changegroup.bundle10(self)
         return self._changegroupsubset(common, csets, heads, bundler, source)
 
     def getlocalbundle(self, source, outgoing, bundlecaps=None):
@@ -2002,7 +2002,7 @@
         precomputed sets in outgoing."""
         if not outgoing.missing:
             return None
-        bundler = changegroup.bundle10(bundlecaps)
+        bundler = changegroup.bundle10(self, bundlecaps)
         return self._changegroupsubset(outgoing.common,
                                        outgoing.missing,
                                        outgoing.missingheads,
@@ -2033,13 +2033,12 @@
     @unfilteredmethod
     def _changegroupsubset(self, commonrevs, csets, heads, bundler, source):
 
-        cl = self.changelog
-        mf = self.manifest
+        cl = bundler._changelog
+        mf = bundler._manifest
         mfs = {} # needed manifests
         fnodes = {} # needed file nodes
         changedfiles = set()
         fstate = ['', {}]
-        count = [0, 0]
 
         # can we go through the fast path ?
         heads.sort()
@@ -2063,6 +2062,7 @@
         _files = _('files')
 
         def lookup(revlog, x):
+            count = bundler.count
             if revlog == cl:
                 c = cl.read(x)
                 changedfiles.update(c[3])
@@ -2087,56 +2087,23 @@
                 return fstate[1][x]
 
         bundler.start(lookup)
-        reorder = self.ui.config('bundle', 'reorder', 'auto')
-        if reorder == 'auto':
-            reorder = None
-        else:
-            reorder = util.parsebool(reorder)
 
-        def gengroup():
-            # Create a changenode group generator that will call our functions
-            # back to lookup the owning changenode and collect information.
-            count[:] = [0, len(csets)]
-            for chunk in bundler.group(csets, cl, reorder=reorder):
-                yield chunk
-            progress(_bundling, None)
-
-            # Create a generator for the manifestnodes that calls our lookup
-            # and data collection functions back.
+        def getmfnodes():
             for f in changedfiles:
                 fnodes[f] = {}
-            count[:] = [0, len(mfs)]
-            for chunk in bundler.group(prune(mf, mfs), mf, reorder=reorder):
-                yield chunk
-            progress(_bundling, None)
+            bundler.count[:] = [0, len(mfs)]
+            return prune(mf, mfs)
+        def getfiles():
+            mfs.clear()
+            return changedfiles
+        def getfilenodes(fname, filerevlog):
+            fstate[0] = fname
+            fstate[1] = fnodes.pop(fname, {})
+            return prune(filerevlog, fstate[1])
 
-            mfs.clear()
-
-            # Go through all our files in order sorted by name.
-            count[:] = [0, len(changedfiles)]
-            for fname in sorted(changedfiles):
-                filerevlog = self.file(fname)
-                if not len(filerevlog):
-                    raise util.Abort(_("empty or missing revlog for %s")
-                                     % fname)
-                fstate[0] = fname
-                fstate[1] = fnodes.pop(fname, {})
-
-                nodelist = prune(filerevlog, fstate[1])
-                if nodelist:
-                    count[0] += 1
-                    yield bundler.fileheader(fname)
-                    for chunk in bundler.group(nodelist, filerevlog, reorder):
-                        yield chunk
-
-            # Signal that no more groups are left.
-            yield bundler.close()
-            progress(_bundling, None)
-
-            if csets:
-                self.hook('outgoing', node=hex(csets[0]), source=source)
-
-        return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
+        gengroup = bundler.generate(csets, getmfnodes, getfiles, getfilenodes,
+                                    source)
+        return changegroup.unbundle10(util.chunkbuffer(gengroup), 'UN')
 
     def changegroup(self, basenodes, source):
         # to avoid a race we use changegroupsubset() (issue1320)
@@ -2153,12 +2120,11 @@
 
         nodes is the set of nodes to send"""
 
-        cl = self.changelog
-        mf = self.manifest
+        cl = bundler._changelog
+        mf = bundler._manifest
         mfs = {}
         changedfiles = set()
         fstate = ['']
-        count = [0, 0]
 
         self.hook('preoutgoing', throw=True, source=source)
         self.changegroupinfo(nodes, source)
@@ -2176,6 +2142,7 @@
         _files = _('files')
 
         def lookup(revlog, x):
+            count = bundler.count
             if revlog == cl:
                 c = cl.read(x)
                 changedfiles.update(c[3])
@@ -2195,46 +2162,19 @@
                 return cl.node(revlog.linkrev(revlog.rev(x)))
 
         bundler.start(lookup)
-        reorder = self.ui.config('bundle', 'reorder', 'auto')
-        if reorder == 'auto':
-            reorder = None
-        else:
-            reorder = util.parsebool(reorder)
 
-        def gengroup():
-            '''yield a sequence of changegroup chunks (strings)'''
-            # construct a list of all changed files
+        def getmfnodes():
+            bundler.count[:] = [0, len(mfs)]
+            return gennodelst(mf)
+        def getfiles():
+            return changedfiles
+        def getfilenodes(fname, filerevlog):
+            fstate[0] = fname
+            return gennodelst(filerevlog)
 
-            count[:] = [0, len(nodes)]
-            for chunk in bundler.group(nodes, cl, reorder=reorder):
-                yield chunk
-            progress(_bundling, None)
-
-            count[:] = [0, len(mfs)]
-            for chunk in bundler.group(gennodelst(mf), mf, reorder=reorder):
-                yield chunk
-            progress(_bundling, None)
-
-            count[:] = [0, len(changedfiles)]
-            for fname in sorted(changedfiles):
-                filerevlog = self.file(fname)
-                if not len(filerevlog):
-                    raise util.Abort(_("empty or missing revlog for %s")
-                                     % fname)
-                fstate[0] = fname
-                nodelist = gennodelst(filerevlog)
-                if nodelist:
-                    count[0] += 1
-                    yield bundler.fileheader(fname)
-                    for chunk in bundler.group(nodelist, filerevlog, reorder):
-                        yield chunk
-            yield bundler.close()
-            progress(_bundling, None)
-
-            if nodes:
-                self.hook('outgoing', node=hex(nodes[0]), source=source)
-
-        return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
+        gengroup = bundler.generate(nodes, getmfnodes, getfiles, getfilenodes,
+                                    source)
+        return changegroup.unbundle10(util.chunkbuffer(gengroup), 'UN')
 
     @unfilteredmethod
     def addchangegroup(self, source, srctype, url, emptyok=False):


More information about the Mercurial-devel mailing list