diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1544,18 +1544,23 @@ class localrepository(repo.repository): return fstate[1][x] bundler = changegroup.bundle10(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. - for chunk in cl.group(csets, bundler): + for chunk in cl.group(csets, bundler, reorder=reorder): yield chunk self.ui.progress(_('bundling'), None) # Create a generator for the manifestnodes that calls our lookup # and data collection functions back. count[0] = 0 - for chunk in mf.group(prune(mf, mfs), bundler): + for chunk in mf.group(prune(mf, mfs), bundler, reorder=reorder): yield chunk self.ui.progress(_('bundling'), None) @@ -1572,7 +1577,7 @@ class localrepository(repo.repository): first = True for chunk in filerevlog.group(prune(filerevlog, fstate[1]), - bundler): + bundler, reorder=reorder): if first: if chunk == bundler.close(): break @@ -1640,17 +1645,22 @@ class localrepository(repo.repository): return cl.node(revlog.linkrev(revlog.rev(x))) bundler = changegroup.bundle10(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 - for chunk in cl.group(nodes, bundler): + for chunk in cl.group(nodes, bundler, reorder=reorder): yield chunk self.ui.progress(_('bundling'), None) count[0] = 0 - for chunk in mf.group(gennodelst(mf), bundler): + for chunk in mf.group(gennodelst(mf), bundler, reorder=reorder): yield chunk self.ui.progress(_('bundling'), None) @@ -1661,7 +1671,8 @@ class localrepository(repo.repository): raise util.Abort(_("empty or missing revlog for %s") % fname) fstate[0] = fname first = True - for chunk in filerevlog.group(gennodelst(filerevlog), bundler): + for chunk in filerevlog.group(gennodelst(filerevlog), bundler, + reorder=reorder): if first: if chunk == bundler.close(): break diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -14,7 +14,7 @@ and O(changes) merge between branches. # import stuff from node for others to import from revlog from node import bin, hex, nullid, nullrev, short #@UnusedImport from i18n import _ -import ancestor, mdiff, parsers, error, util +import ancestor, mdiff, parsers, error, util, dagutil import struct, zlib, errno _pack = struct.pack @@ -1086,7 +1086,7 @@ class revlog(object): self._basecache = (curr, chainbase) return node - def group(self, nodelist, bundler): + def group(self, nodelist, bundler, reorder=None): """Calculate a delta group, yielding a sequence of changegroup chunks (strings). @@ -1098,7 +1098,14 @@ class revlog(object): changegroup starts with a full revision. """ - revs = sorted([self.rev(n) for n in nodelist]) + # for generaldelta revlogs, we linearize the revs; this will both be + # much quicker and generate a much smaller bundle + if (self._generaldelta and reorder is not False) or reorder: + dag = dagutil.revlogdag(self) + revs = set(self.rev(n) for n in nodelist) + revs = dag.linearize(revs) + else: + revs = sorted([self.rev(n) for n in nodelist]) # if we don't have any revisions touched by these changesets, bail if not revs: