--- a/mercurial/bundle2.py Thu Sep 25 11:53:28 2014 +0900
+++ b/mercurial/bundle2.py Fri Oct 17 09:57:05 2014 +0900
@@ -151,6 +151,7 @@
import string
import obsolete
import pushkey
+import url
import changegroup, error
from i18n import _
@@ -797,6 +798,8 @@
'b2x:listkeys': (),
'b2x:pushkey': (),
'b2x:changegroup': (),
+ 'digests': tuple(sorted(util.DIGESTS.keys())),
+ 'b2x:remote-changegroup': ('http', 'https'),
}
def getrepocaps(repo):
@@ -850,6 +853,80 @@
part.addparam('return', '%i' % ret, mandatory=False)
assert not inpart.read()
+_remotechangegroupparams = tuple(['url', 'size', 'digests'] +
+ ['digest:%s' % k for k in util.DIGESTS.keys()])
+@parthandler('b2x:remote-changegroup', _remotechangegroupparams)
+def handleremotechangegroup(op, inpart):
+ """apply a bundle10 on the repo, given an url and validation information
+
+ All the information about the remote bundle to import are given as
+ parameters. The parameters include:
+ - url: the url to the bundle10.
+ - size: the bundle10 file size. It is used to validate what was
+ retrieved by the client matches the server knowledge about the bundle.
+ - digests: a space separated list of the digest types provided as
+ parameters.
+ - digest:<digest-type>: the hexadecimal representation of the digest with
+ that name. Like the size, it is used to validate what was retrieved by
+ the client matches what the server knows about the bundle.
+
+ When multiple digest types are given, all of them are checked.
+ """
+ try:
+ raw_url = inpart.params['url']
+ except KeyError:
+ raise util.Abort(_('remote-changegroup: missing "%s" param') % 'url')
+ parsed_url = util.url(raw_url)
+ if parsed_url.scheme not in capabilities['b2x:remote-changegroup']:
+ raise util.Abort(_('remote-changegroup does not support %s urls') %
+ parsed_url.scheme)
+
+ try:
+ size = int(inpart.params['size'])
+ except ValueError:
+ raise util.Abort(_('remote-changegroup: invalid value for param "%s"')
+ % 'size')
+ except KeyError:
+ raise util.Abort(_('remote-changegroup: missing "%s" param') % 'size')
+
+ digests = {}
+ for typ in inpart.params.get('digests', '').split():
+ param = 'digest:%s' % typ
+ try:
+ value = inpart.params[param]
+ except KeyError:
+ raise util.Abort(_('remote-changegroup: missing "%s" param') %
+ param)
+ digests[typ] = value
+
+ real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
+
+ # Make sure we trigger a transaction creation
+ #
+ # The addchangegroup function will get a transaction object by itself, but
+ # we need to make sure we trigger the creation of a transaction object used
+ # for the whole processing scope.
+ op.gettransaction()
+ import exchange
+ cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
+ if not isinstance(cg, changegroup.cg1unpacker):
+ raise util.Abort(_('%s: not a bundle version 1.0') %
+ util.hidepassword(raw_url))
+ ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
+ op.records.add('changegroup', {'return': ret})
+ if op.reply is not None:
+ # This is definitly not the final form of this
+ # return. But one need to start somewhere.
+ part = op.reply.newpart('b2x:reply:changegroup')
+ part.addparam('in-reply-to', str(inpart.id), mandatory=False)
+ part.addparam('return', '%i' % ret, mandatory=False)
+ try:
+ real_part.validate()
+ except util.Abort, e:
+ raise util.Abort(_('bundle at %s is corrupted:\n%s') %
+ (util.hidepassword(raw_url), str(e)))
+ assert not inpart.read()
+
@parthandler('b2x:reply:changegroup', ('return', 'in-reply-to'))
def handlereplychangegroup(op, inpart):
ret = int(inpart.params['return'])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-bundle2-remote-changegroup.t Fri Oct 17 09:57:05 2014 +0900
@@ -0,0 +1,592 @@
+#require killdaemons
+
+Create an extension to test bundle2 remote-changegroup parts
+
+ $ cat > bundle2.py << EOF
+ > """A small extension to test bundle2 remote-changegroup parts.
+ >
+ > Current bundle2 implementation doesn't provide a way to generate those
+ > parts, so they must be created by extensions.
+ > """
+ > from mercurial import bundle2, changegroup, exchange, util
+ >
+ > def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
+ > b2caps=None, heads=None, common=None,
+ > **kwargs):
+ > """this function replaces the changegroup part handler for getbundle.
+ > It allows to create a set of arbitrary parts containing changegroups
+ > and remote-changegroups, as described in a bundle2maker file in the
+ > repository .hg/ directory.
+ >
+ > Each line of that bundle2maker file contain a description of the
+ > part to add:
+ > - changegroup common_revset heads_revset
+ > Creates a changegroup part based, using common_revset and
+ > heads_revset for changegroup.getchangegroup.
+ > - remote-changegroup url file
+ > Creates a remote-changegroup part for a bundle at the given
+ > url. Size and digest, as required by the client, are computed
+ > from the given file.
+ > - raw-remote-changegroup <python expression>
+ > Creates a remote-changegroup part with the data given in the
+ > python expression as parameters. The python expression is
+ > evaluated with eval, and is expected to be a dict.
+ > """
+ > def newpart(name, data=''):
+ > """wrapper around bundler.newpart adding an extra part making the
+ > client output information about each processed part"""
+ > bundler.newpart('b2x:output', data=name)
+ > part = bundler.newpart(name, data=data)
+ > return part
+ >
+ > for line in open(repo.join('bundle2maker'), 'r'):
+ > line = line.strip()
+ > try:
+ > verb, args = line.split(None, 1)
+ > except ValueError:
+ > verb, args = line, ''
+ > if verb == 'remote-changegroup':
+ > url, file = args.split()
+ > bundledata = open(file, 'rb').read()
+ > digest = util.digester.preferred(b2caps['digests'])
+ > d = util.digester([digest], bundledata)
+ > part = newpart('B2X:REMOTE-CHANGEGROUP')
+ > part.addparam('url', url)
+ > part.addparam('size', str(len(bundledata)))
+ > part.addparam('digests', digest)
+ > part.addparam('digest:%s' % digest, d[digest])
+ > elif verb == 'raw-remote-changegroup':
+ > part = newpart('B2X:REMOTE-CHANGEGROUP')
+ > for k, v in eval(args).items():
+ > part.addparam(k, str(v))
+ > elif verb == 'changegroup':
+ > _common, heads = args.split()
+ > common.extend(repo.lookup(r) for r in repo.revs(_common))
+ > heads = [repo.lookup(r) for r in repo.revs(heads)]
+ > cg = changegroup.getchangegroup(repo, 'changegroup',
+ > heads=heads, common=common)
+ > newpart('B2X:CHANGEGROUP', cg.getchunks())
+ > else:
+ > raise Exception('unknown verb')
+ >
+ > exchange.getbundle2partsmapping['changegroup'] = _getbundlechangegrouppart
+ > EOF
+
+Start a simple HTTP server to serve bundles
+
+ $ python "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
+ $ cat dumb.pid >> $DAEMON_PIDS
+
+ $ cat >> $HGRCPATH << EOF
+ > [experimental]
+ > bundle2-exp=True
+ > [ui]
+ > ssh=python "$TESTDIR/dummyssh"
+ > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
+ > EOF
+
+ $ hg init repo
+
+ $ hg -R repo unbundle $TESTDIR/bundles/rebase.hg
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ (run 'hg heads' to see heads, 'hg merge' to merge)
+
+ $ hg -R repo log -G
+ o 7:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> H
+ |
+ | o 6:eea13746799a draft Nicolas Dumazet <nicdumz.commits@gmail.com> G
+ |/|
+ o | 5:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
+ | |
+ | o 4:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
+ |/
+ | o 3:32af7686d403 draft Nicolas Dumazet <nicdumz.commits@gmail.com> D
+ | |
+ | o 2:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ | |
+ | o 1:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |/
+ o 0:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+ $ hg clone repo orig
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+ $ cat > repo/.hg/hgrc << EOF
+ > [extensions]
+ > bundle2=$TESTTMP/bundle2.py
+ > EOF
+
+Test a pull with an remote-changegroup
+
+ $ hg bundle -R repo --base '0:4' -r '5:7' bundle.hg
+ 3 changesets found
+ $ cat > repo/.hg/bundle2maker << EOF
+ > remote-changegroup http://localhost:$HGPORT/bundle.hg bundle.hg
+ > EOF
+ $ hg clone orig clone -r 3 -r 4
+ adding changesets
+ adding manifests
+ adding file changes
+ added 5 changesets with 5 changes to 5 files (+1 heads)
+ updating to branch default
+ 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 2 changes to 2 files (+1 heads)
+ (run 'hg heads .' to see heads, 'hg merge' to merge)
+ $ hg -R clone log -G
+ o 7:02de42196ebe public Nicolas Dumazet <nicdumz.commits@gmail.com> H
+ |
+ | o 6:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G
+ |/|
+ o | 5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
+ | |
+ | o 4:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
+ |/
+ | @ 3:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> D
+ | |
+ | o 2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ | |
+ | o 1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |/
+ o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+ $ rm -rf clone
+
+Test a pull with an remote-changegroup and a following changegroup
+
+ $ hg bundle -R repo --base 2 -r '3:4' bundle2.hg
+ 2 changesets found
+ $ cat > repo/.hg/bundle2maker << EOF
+ > remote-changegroup http://localhost:$HGPORT/bundle2.hg bundle2.hg
+ > changegroup 0:4 5:7
+ > EOF
+ $ hg clone orig clone -r 2
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 3 changes to 3 files
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files (+1 heads)
+ remote: B2X:CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 2 changes to 2 files (+1 heads)
+ (run 'hg heads' to see heads, 'hg merge' to merge)
+ $ hg -R clone log -G
+ o 7:02de42196ebe public Nicolas Dumazet <nicdumz.commits@gmail.com> H
+ |
+ | o 6:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G
+ |/|
+ o | 5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
+ | |
+ | o 4:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
+ |/
+ | o 3:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> D
+ | |
+ | @ 2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ | |
+ | o 1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |/
+ o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+ $ rm -rf clone
+
+Test a pull with a changegroup followed by an remote-changegroup
+
+ $ hg bundle -R repo --base '0:4' -r '5:7' bundle3.hg
+ 3 changesets found
+ $ cat > repo/.hg/bundle2maker << EOF
+ > changegroup 000000000000 :4
+ > remote-changegroup http://localhost:$HGPORT/bundle3.hg bundle3.hg
+ > EOF
+ $ hg clone orig clone -r 2
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 3 changes to 3 files
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files (+1 heads)
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 2 changes to 2 files (+1 heads)
+ (run 'hg heads' to see heads, 'hg merge' to merge)
+ $ hg -R clone log -G
+ o 7:02de42196ebe public Nicolas Dumazet <nicdumz.commits@gmail.com> H
+ |
+ | o 6:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G
+ |/|
+ o | 5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
+ | |
+ | o 4:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
+ |/
+ | o 3:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> D
+ | |
+ | @ 2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ | |
+ | o 1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |/
+ o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+ $ rm -rf clone
+
+Test a pull with two remote-changegroups and a changegroup
+
+ $ hg bundle -R repo --base 2 -r '3:4' bundle4.hg
+ 2 changesets found
+ $ hg bundle -R repo --base '3:4' -r '5:6' bundle5.hg
+ 2 changesets found
+ $ cat > repo/.hg/bundle2maker << EOF
+ > remote-changegroup http://localhost:$HGPORT/bundle4.hg bundle4.hg
+ > remote-changegroup http://localhost:$HGPORT/bundle5.hg bundle5.hg
+ > changegroup 0:6 7
+ > EOF
+ $ hg clone orig clone -r 2
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 3 changes to 3 files
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files (+1 heads)
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 1 changes to 1 files
+ remote: B2X:CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files (+1 heads)
+ (run 'hg heads' to see heads, 'hg merge' to merge)
+ $ hg -R clone log -G
+ o 7:02de42196ebe public Nicolas Dumazet <nicdumz.commits@gmail.com> H
+ |
+ | o 6:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> G
+ |/|
+ o | 5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
+ | |
+ | o 4:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
+ |/
+ | o 3:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> D
+ | |
+ | @ 2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ | |
+ | o 1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |/
+ o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+ $ rm -rf clone
+
+Hash digest tests
+
+ $ hg bundle -R repo -a bundle6.hg
+ 8 changesets found
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle6.hg', 'size': 1663, 'digests': 'sha1', 'digest:sha1': '2c880cfec23cff7d8f80c2f12958d1563cbdaba6'}
+ > EOF
+ $ hg clone ssh://user@dummy/repo clone
+ requesting all changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ rm -rf clone
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle6.hg', 'size': 1663, 'digests': 'md5', 'digest:md5': 'e22172c2907ef88794b7bea6642c2394'}
+ > EOF
+ $ hg clone ssh://user@dummy/repo clone
+ requesting all changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ rm -rf clone
+
+Hash digest mismatch throws an error
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle6.hg', 'size': 1663, 'digests': 'sha1', 'digest:sha1': '0' * 40}
+ > EOF
+ $ hg clone ssh://user@dummy/repo clone
+ requesting all changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ transaction abort!
+ rollback completed
+ abort: bundle at http://localhost:$HGPORT/bundle6.hg is corrupted:
+ sha1 mismatch: expected 0000000000000000000000000000000000000000, got 2c880cfec23cff7d8f80c2f12958d1563cbdaba6
+ [255]
+
+Multiple hash digests can be given
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle6.hg', 'size': 1663, 'digests': 'md5 sha1', 'digest:md5': 'e22172c2907ef88794b7bea6642c2394', 'digest:sha1': '2c880cfec23cff7d8f80c2f12958d1563cbdaba6'}
+ > EOF
+ $ hg clone ssh://user@dummy/repo clone
+ requesting all changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ rm -rf clone
+
+If either of the multiple hash digests mismatches, an error is thrown
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle6.hg', 'size': 1663, 'digests': 'md5 sha1', 'digest:md5': '0' * 32, 'digest:sha1': '2c880cfec23cff7d8f80c2f12958d1563cbdaba6'}
+ > EOF
+ $ hg clone ssh://user@dummy/repo clone
+ requesting all changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ transaction abort!
+ rollback completed
+ abort: bundle at http://localhost:$HGPORT/bundle6.hg is corrupted:
+ md5 mismatch: expected 00000000000000000000000000000000, got e22172c2907ef88794b7bea6642c2394
+ [255]
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle6.hg', 'size': 1663, 'digests': 'md5 sha1', 'digest:md5': 'e22172c2907ef88794b7bea6642c2394', 'digest:sha1': '0' * 40}
+ > EOF
+ $ hg clone ssh://user@dummy/repo clone
+ requesting all changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 8 changesets with 7 changes to 7 files (+2 heads)
+ transaction abort!
+ rollback completed
+ abort: bundle at http://localhost:$HGPORT/bundle6.hg is corrupted:
+ sha1 mismatch: expected 0000000000000000000000000000000000000000, got 2c880cfec23cff7d8f80c2f12958d1563cbdaba6
+ [255]
+
+Corruption tests
+
+ $ hg clone orig clone -r 2
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 3 changes to 3 files
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > remote-changegroup http://localhost:$HGPORT/bundle4.hg bundle4.hg
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle5.hg', 'size': 578, 'digests': 'sha1', 'digest:sha1': '0' * 40}
+ > changegroup 0:6 7
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files (+1 heads)
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 1 changes to 1 files
+ transaction abort!
+ rollback completed
+ abort: bundle at http://localhost:$HGPORT/bundle5.hg is corrupted:
+ sha1 mismatch: expected 0000000000000000000000000000000000000000, got f29485d6bfd37db99983cfc95ecb52f8ca396106
+ [255]
+
+The entire transaction has been rolled back in the pull above
+
+ $ hg -R clone log -G
+ @ 2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ |
+ o 1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |
+ o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+
+No params
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: remote-changegroup: missing "url" param
+ [255]
+
+Missing size
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle4.hg'}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: remote-changegroup: missing "size" param
+ [255]
+
+Invalid size
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle4.hg', 'size': 'foo'}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: remote-changegroup: invalid value for param "size"
+ [255]
+
+Size mismatch
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle4.hg', 'size': 42}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files (+1 heads)
+ transaction abort!
+ rollback completed
+ abort: bundle at http://localhost:$HGPORT/bundle4.hg is corrupted:
+ size mismatch: expected 42, got 581
+ [255]
+
+Unknown digest
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle4.hg', 'size': 581, 'digests': 'foo', 'digest:foo': 'bar'}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: missing support for b2x:remote-changegroup - digest:foo
+ [255]
+
+Missing digest
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle4.hg', 'size': 581, 'digests': 'sha1'}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: remote-changegroup: missing "digest:sha1" param
+ [255]
+
+Not an HTTP url
+
+ $ cat > repo/.hg/bundle2maker << EOF
+ > raw-remote-changegroup {'url': 'ssh://localhost:$HGPORT/bundle4.hg', 'size': 581}
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: remote-changegroup does not support ssh urls
+ [255]
+
+Not a bundle
+
+ $ cat > notbundle.hg << EOF
+ > foo
+ > EOF
+ $ cat > repo/.hg/bundle2maker << EOF
+ > remote-changegroup http://localhost:$HGPORT/notbundle.hg notbundle.hg
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: http://localhost:$HGPORT/notbundle.hg: not a Mercurial bundle
+ [255]
+
+Not a bundle 1.0
+
+ $ cat > notbundle10.hg << EOF
+ > HG2Y
+ > EOF
+ $ cat > repo/.hg/bundle2maker << EOF
+ > remote-changegroup http://localhost:$HGPORT/notbundle10.hg notbundle10.hg
+ > EOF
+ $ hg pull -R clone ssh://user@dummy/repo
+ pulling from ssh://user@dummy/repo
+ searching for changes
+ remote: B2X:REMOTE-CHANGEGROUP
+ abort: http://localhost:$HGPORT/notbundle10.hg: not a bundle version 1.0
+ [255]
+
+ $ hg -R clone log -G
+ @ 2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> C
+ |
+ o 1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> B
+ |
+ o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
+
+ $ rm -rf clone
+
+ $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS