bundle2: allow pulling changegroups using bundle2
This changeset refactors the pull code to use a bundle2 when available. We keep
bundle2 disabled by default. The current code is not ready for prime time.
Ultimately we'll want to unify the API of `bunde10` and `bundle20` to have less
different code. But for now, testing the bundle2 exchange flow is an higher
priority.
--- a/mercurial/exchange.py Fri Apr 04 01:51:54 2014 -0700
+++ b/mercurial/exchange.py Tue Apr 01 23:41:32 2014 -0700
@@ -7,9 +7,10 @@
from i18n import _
from node import hex, nullid
+import cStringIO
import errno
import util, scmutil, changegroup, base85
-import discovery, phases, obsolete, bookmarks
+import discovery, phases, obsolete, bookmarks, bundle2
class pushoperation(object):
@@ -455,6 +456,8 @@
lock = pullop.repo.lock()
try:
_pulldiscovery(pullop)
+ if pullop.remote.capable('bundle2'):
+ _pullbundle2(pullop)
if 'changegroup' in pullop.todosteps:
_pullchangeset(pullop)
if 'phases' in pullop.todosteps:
@@ -479,6 +482,31 @@
force=pullop.force)
pullop.common, pullop.fetch, pullop.rheads = tmp
+def _pullbundle2(pullop):
+ """pull data using bundle2
+
+ For now, the only supported data are changegroup."""
+ kwargs = {'bundlecaps': set(['HG20'])}
+ # pulling changegroup
+ pullop.todosteps.remove('changegroup')
+ if not pullop.fetch:
+ pullop.repo.ui.status(_("no changes found\n"))
+ pullop.cgresult = 0
+ else:
+ kwargs['common'] = pullop.common
+ kwargs['heads'] = pullop.heads or pullop.rheads
+ if pullop.heads is None and list(pullop.common) == [nullid]:
+ pullop.repo.ui.status(_("requesting all changes\n"))
+ if kwargs.keys() == ['format']:
+ return # nothing to pull
+ bundle = pullop.remote.getbundle('pull', **kwargs)
+ try:
+ op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction)
+ except KeyError, exc:
+ raise util.Abort('missing support for %s' % exc)
+ assert len(op.records['changegroup']) == 1
+ pullop.cgresult = op.records['changegroup'][0]['return']
+
def _pullchangeset(pullop):
"""pull changeset from unbundle into the local repo"""
# We delay the open of the transaction as late as possible so we
--- a/mercurial/localrepo.py Fri Apr 04 01:51:54 2014 -0700
+++ b/mercurial/localrepo.py Tue Apr 01 23:41:32 2014 -0700
@@ -62,7 +62,8 @@
return orig(repo.unfiltered(), *args, **kwargs)
return wrapper
-moderncaps = set(('lookup', 'branchmap', 'pushkey', 'known', 'getbundle'))
+moderncaps = set(('lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
+ 'bundle2'))
legacycaps = moderncaps.union(set(['changegroupsubset']))
class localpeer(peer.peerrepository):
@@ -276,6 +277,11 @@
pass
def _restrictcapabilities(self, caps):
+ # bundle2 is not ready for prime time, drop it unless explicitly
+ # required by the tests (or some brave tester)
+ if not self.ui.configbool('server', 'bundle2', False):
+ caps = set(caps)
+ caps.remove('bundle2')
return caps
def _applyrequirements(self, requirements):
--- a/tests/test-bundle2.t Fri Apr 04 01:51:54 2014 -0700
+++ b/tests/test-bundle2.t Tue Apr 01 23:41:32 2014 -0700
@@ -142,6 +142,8 @@
$ cat >> $HGRCPATH << EOF
> [extensions]
> bundle2=$TESTTMP/bundle2.py
+ > [server]
+ > bundle2=True
> EOF
The extension requires a repo (currently unused)
@@ -560,3 +562,41 @@
added 0 changesets with 0 changes to 3 files
0 unread bytes
addchangegroup return: 1
+
+Real world exchange
+=====================
+
+
+clone --pull
+
+ $ cd ..
+ $ hg clone main other --pull --rev 9520eea781bc
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files
+ updating to branch default
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg -R other log -G
+ @ changeset: 1:9520eea781bc
+ | tag: tip
+ | user: Nicolas Dumazet <nicdumz.commits@gmail.com>
+ | date: Sat Apr 30 15:24:48 2011 +0200
+ | summary: E
+ |
+ o changeset: 0:cd010b8cd998
+ user: Nicolas Dumazet <nicdumz.commits@gmail.com>
+ date: Sat Apr 30 15:24:48 2011 +0200
+ summary: A
+
+
+pull
+
+ $ hg -R other pull
+ pulling from $TESTTMP/main (glob)
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 7 changesets with 6 changes to 6 files (+3 heads)
+ (run 'hg heads' to see heads, 'hg merge' to merge)