@@ -5,13 +5,14 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
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):
"""A object that represent a single push operation
@@ -453,10 +454,12 @@ def pull(repo, remote, heads=None, force
raise util.Abort(msg)
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:
_pullphase(pullop)
if 'obsmarkers' in pullop.todosteps:
@@ -477,10 +480,35 @@ def _pulldiscovery(pullop):
pullop.remote,
heads=pullop.heads,
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
# don't open transaction for nothing or you break future useful
# rollback call
@@ -60,11 +60,12 @@ def unfilteredmethod(orig):
"""decorate method that always need to be run on unfiltered version"""
def wrapper(repo, *args, **kwargs):
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):
'''peer for a local repo; reflects only the most recent API'''
@@ -274,10 +275,15 @@ class localrepository(object):
def close(self):
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):
self.requirements = requirements
self.sopener.options = dict((r, 1) for r in requirements
@@ -140,10 +140,12 @@ Create an extension to test bundle2 API
> ui.write(' payload: %i bytes\n' % len(p.data))
> EOF
$ cat >> $HGRCPATH << EOF
> [extensions]
> bundle2=$TESTTMP/bundle2.py
+ > [server]
+ > bundle2=True
> EOF
The extension requires a repo (currently unused)
$ hg init main
@@ -558,5 +560,43 @@ Support for changegroup
adding manifests
adding file changes
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)