[PATCH 5 of 9] bundle-ng: unify _changegroup and _changegroupsubset
Sune Foldager
cryo at cyanite.org
Thu Feb 14 13:40:15 CST 2013
# HG changeset patch
# User Benoit Boissinot <benoit.boissinot at ens-lyon.org>
# Date 1360507643 -3600
# Node ID 3821b9f543fbeabc29a2c34b3f78272837364586
# Parent 1107b6c3ba5652700ecaa0184d00490f81d2b063
bundle-ng: unify _changegroup and _changegroupsubset
diff -r 1107b6c3ba56 -r 3821b9f543fb mercurial/localrepo.py
--- a/mercurial/localrepo.py Sun Feb 10 01:12:44 2013 +0100
+++ b/mercurial/localrepo.py Sun Feb 10 15:47:23 2013 +0100
@@ -1827,9 +1827,13 @@
if revs is None and not outgoing.excluded:
# push everything,
# use the fast path, no race possible on push
- bundler = changegroup.bundle10(bundlecaps)
- cg = self._changegroup(outgoing.missing, bundler,
- 'push')
+ bundler = changegroup.bundle10(bundlecaps, self)
+ cg = self._changegroupsubset(outgoing.common,
+ outgoing.missing,
+ outgoing.missingheads,
+ bundler,
+ 'push',
+ fastpath=True)
else:
cg = self.getlocalbundle('push', outgoing, bundlecaps)
@@ -2023,10 +2027,10 @@
bundlecaps=bundlecaps)
@unfilteredmethod
- def _changegroupsubset(self, commonrevs, csets, heads, bundler, source):
-
- cl = self.changelog
- mf = self.manifest
+ def _changegroupsubset(self, commonrevs, csets, heads, bundler, source,
+ fastpath=False):
+ cl = bundler._changelog
+ mf = bundler._manifest
mfs = {} # needed manifests
fnodes = {} # needed file nodes
changedfiles = set()
@@ -2035,10 +2039,8 @@
# can we go through the fast path ?
heads.sort()
- if heads == sorted(self.heads()):
- return self._changegroup(csets, bundler, source)
+ fastpathlinkrev = fastpath or heads == sorted(self.heads())
- # slow path
self.hook('preoutgoing', throw=True, source=source)
self.changegroupinfo(csets, source)
@@ -2065,10 +2067,11 @@
return x
elif revlog == mf:
clnode = mfs[x]
- mdata = mf.readfast(x)
- for f, n in mdata.iteritems():
- if f in changedfiles:
- fnodes[f].setdefault(n, clnode)
+ if not fastpathlinkrev:
+ mdata = mf.readfast(x)
+ for f, n in mdata.iteritems():
+ if f in changedfiles:
+ fnodes[f].setdefault(n, clnode)
count[0] += 1
progress(_bundling, count[0],
unit=_manifests, total=count[1])
@@ -2103,6 +2106,19 @@
progress(_bundling, None)
mfs.clear()
+ return changedfiles
+ def getfilenodes(fname, filerevlog):
+ if fastpathlinkrev:
+ ln, llr = filerevlog.node, filerevlog.linkrev
+ def genfilenodes():
+ for r in filerevlog:
+ linkrev = llr(r)
+ if linkrev not in commonrevs:
+ yield filerevlog.node(r), cl.node(linkrev)
+ fnodes[fname] = dict(genfilenodes())
+ 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)]
@@ -2135,100 +2151,6 @@
return self.changegroupsubset(basenodes, self.heads(), source)
@unfilteredmethod
- def _changegroup(self, nodes, bundler, source):
- """Compute the changegroup of all nodes that we have that a recipient
- doesn't. Return a chunkbuffer object whose read() method will return
- successive changegroup chunks.
-
- This is much easier than the previous function as we can assume that
- the recipient has any changenode we aren't sending them.
-
- nodes is the set of nodes to send"""
-
- cl = self.changelog
- mf = self.manifest
- mfs = {}
- changedfiles = set()
- fstate = ['']
- count = [0, 0]
-
- self.hook('preoutgoing', throw=True, source=source)
- self.changegroupinfo(nodes, source)
-
- revset = set([cl.rev(n) for n in nodes])
-
- def gennodelst(log):
- ln, llr = log.node, log.linkrev
- return [ln(r) for r in log if llr(r) in revset]
-
- progress = self.ui.progress
- _bundling = _('bundling')
- _changesets = _('changesets')
- _manifests = _('manifests')
- _files = _('files')
-
- def lookup(revlog, x):
- if revlog == cl:
- c = cl.read(x)
- changedfiles.update(c[3])
- mfs.setdefault(c[0], x)
- count[0] += 1
- progress(_bundling, count[0],
- unit=_changesets, total=count[1])
- return x
- elif revlog == mf:
- count[0] += 1
- progress(_bundling, count[0],
- unit=_manifests, total=count[1])
- return cl.node(revlog.linkrev(revlog.rev(x)))
- else:
- progress(_bundling, count[0], item=fstate[0],
- total=count[1], unit=_files)
- 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)
-
- if nodes:
- self.hook('outgoing', node=hex(nodes[0]), source=source)
-
- return changegroup.unbundle10(util.chunkbuffer(gengroup()), 'UN')
-
- @unfilteredmethod
def addchangegroup(self, source, srctype, url, emptyok=False):
"""Add the changegroup returned by source.read() to this repo.
srctype is a string like 'push', 'pull', or 'unbundle'. url is
More information about the Mercurial-devel
mailing list