# HG changeset patch # User Sune Foldager # Date 2013-05-10 19:35:49 # Node ID 0455fc94ae0078cab69bde00be9d5e4df6553c9c # Parent 309c439cdbaa3850365606a3481eb414d706042a 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 @@ def toposort_postorderreverse(ui, rl): 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 @@ def writerevs(ui, r1, r2, order, tr): 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 @@ def shrink(ui, repo, **opts): 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 @@ def readbundle(fh, fname): 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 @@ class bundle10(object): 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 @@ class localrepository(object): 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 @@ class localrepository(object): 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 @@ class localrepository(object): 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 @@ class localrepository(object): @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 @@ class localrepository(object): _files = _('files') def lookup(revlog, x): + count = bundler.count if revlog == cl: c = cl.read(x) changedfiles.update(c[3]) @@ -2087,56 +2087,23 @@ class localrepository(object): 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]) - # 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 @@ class localrepository(object): 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 @@ class localrepository(object): _files = _('files') def lookup(revlog, x): + count = bundler.count if revlog == cl: c = cl.read(x) changedfiles.update(c[3]) @@ -2195,46 +2162,19 @@ class localrepository(object): 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 - - 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) + def getmfnodes(): + bundler.count[:] = [0, len(mfs)] + return gennodelst(mf) + def getfiles(): + return changedfiles + def getfilenodes(fname, filerevlog): + fstate[0] = fname + return gennodelst(filerevlog) - 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):