[PATCH 7 of 7 V3] bundle2: client side support for a part to import external bundles

Pierre-Yves David pierre-yves.david at ens-lyon.org
Thu Oct 16 05:07:12 CDT 2014



On 10/16/2014 01:22 AM, Mike Hommey wrote:
> # HG changeset patch
> # User Mike Hommey <mh at glandium.org>
> # Date 1413447617 -32400
> #      Thu Oct 16 17:20:17 2014 +0900
> # Node ID e06c0786c2e17846cced1c74122a2cda713f8cff
> # Parent  dad191f49c35873419268b31cef19dbc251ad812
> bundle2: client side support for a part to import external bundles
>
> Bundle2 opens doors to advanced features allowing to reduce load on
> mercurial servers, and improve clone experience for users on unstable or
> slow networks.
>
> For instance, it could be possible to pre-generate a bundle of a
> repository, and give a pointer to it to clients cloning the repository,
> followed by another changegroup with the remainder. For significantly
> big repositories, this could come as several base bundles with e.g. 10k
> changesets, which, combined with checkpoints (not part of this change),
> would prevent users with flaky networks from starting over any time
> their connection fails.
>
> While the server-side support for those features doesn't exist yet, it
> is preferable to have client-side support for this early-on, allowing
> experiments on servers only requiring a vanilla client with bundle2
> enabled.
>
> diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
> --- a/mercurial/bundle2.py
> +++ b/mercurial/bundle2.py
> @@ -143,16 +143,17 @@ preserve.
>   """
>
>   import util
>   import struct
>   import urllib
>   import string
>   import obsolete
>   import pushkey
> +import hg
>
>   import changegroup, error
>   from i18n import _
>
>   _pack = struct.pack
>   _unpack = struct.unpack
>
>   _magicstring = 'HG2X'
> @@ -775,16 +776,18 @@ class unbundlepart(unpackermixin):
>           if size is None or len(data) < size:
>               self.consumed = True
>           return data
>
>   capabilities = {'HG2X': (),
>                   'b2x:listkeys': (),
>                   'b2x:pushkey': (),
>                   'b2x:changegroup': (),
> +                'digests': tuple(sorted(util.DIGESTS.keys())),
> +                'b2x:remote-changegroup': ('http', 'https'),
>                  }
>
>   def getrepocaps(repo):
>       """return the bundle2 capabilities for a given repo
>
>       Exists to allow extensions (like evolution) to mutate the capabilities.
>       """
>       caps = capabilities.copy()
> @@ -826,16 +829,85 @@ def handlechangegroup(op, inpart):
>       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)
>       assert not inpart.read()
>
> + at parthandler('b2x:remote-changegroup', tuple(['url', 'size', 'digests'] +
> +                                             util.DIGESTS.keys()))
> +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-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.
> +    """

I'm not sure how the changegroup type is handled here. Does it -has- to 
be HG10 or another variant (coming HG11 would work too?) If not you want 
to grow a "version" parameter as the b2x:changegroup part did.

> +    lines = []
> +    try:
> +        url = inpart.params['url']
> +    except KeyError:
> +        raise util.Abort(_('remote-changegroup: missing "%s" param') % 'url')

We have some exception dedicated to "This bundle2 is valid but crap" we 
should use them instead. (not sure exactly how mature it is)

> +    parsed_url = util.url(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, KeyError):
> +        raise util.Abort(_('remote-changegroup: missing "%s" param') % 'size')

In the ValueError case your exception message is wrong.

> +
> +    digests = {}
> +    for typ in inpart.params.get('digests', '').split():
> +        try:
> +            value = inpart.params[typ]
> +        except KeyError:
> +            raise util.Abort(_('remote-changegroup: missing "%s" param') % typ)
> +        digests[typ] = value

you maybe want to prefix the key for "digest:" to avoid silly collision.

> +    real_part = util.digestchecker(hg.openpath(op.ui, 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, url)
> +    if not isinstance(cg, changegroup.cg1unpacker):
> +        raise util.Abort(_('%s: not a bundle version 1.0') %
> +            util.hidepassword(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(url), e.message))
> +    assert not inpart.read()
> +
>   @parthandler('b2x:reply:changegroup', ('return', 'in-reply-to'))
>   def handlereplychangegroup(op, inpart):
>       ret = int(inpart.params['return'])
>       replyto = int(inpart.params['in-reply-to'])
>       op.records.add('changegroup', {'return': ret}, replyto)
>
>   @parthandler('b2x:check:heads')
>   def handlecheckheads(op, inpart):
> diff --git a/tests/test-bundle2-remote-changegroup.t b/tests/test-bundle2-remote-changegroup.t
> new file mode 100644
> --- /dev/null
> +++ b/tests/test-bundle2-remote-changegroup.t
> @@ -0,0 +1,694 @@
> +#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, 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 at gmail.com>  H
> +  |
> +  | o  6:eea13746799a draft Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc draft Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | o  2:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 draft Nicolas Dumazet <nicdumz.commits at 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 clone with a single remote-changegroup.
> +
> +  $ hg bundle -R repo -a bundle.hg
> +  8 changesets found
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > remote-changegroup http://localhost:$HGPORT/bundle.hg bundle.hg
> +  > 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
> +  $ hg -R clone log -G
> +  @  7:02de42196ebe public Nicolas Dumazet <nicdumz.commits at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | o  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at gmail.com>  A
> +
> +  $ rm -rf clone
> +
> +Test a clone with an remote-changegroup and a following changegroup
> +
> +  $ hg bundle -R repo --base 000000000000 -r '0:4' bundle2.hg
> +  5 changesets found
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > remote-changegroup http://localhost:$HGPORT/bundle2.hg bundle2.hg
> +  > changegroup 0:4 5:7
> +  > EOF
> +  $ hg clone ssh://user@dummy/repo clone
> +  requesting all changes
> +  remote: B2X:REMOTE-CHANGEGROUP
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 5 changesets with 5 changes to 5 files (+1 heads)
> +  remote: B2X:CHANGEGROUP
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 3 changesets with 2 changes to 2 files (+1 heads)
> +  updating to branch default
> +  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg -R clone log -G
> +  @  7:02de42196ebe public Nicolas Dumazet <nicdumz.commits at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | o  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at gmail.com>  A
> +
> +  $ rm -rf clone
> +
> +Test a clone 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 ssh://user@dummy/repo clone
> +  requesting all changes
> +  remote: B2X:CHANGEGROUP
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 5 changesets with 5 changes to 5 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)
> +  updating to branch default
> +  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg -R clone log -G
> +  @  7:02de42196ebe public Nicolas Dumazet <nicdumz.commits at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | o  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at gmail.com>  A
> +
> +  $ rm -rf clone
> +
> +Test a pull with an remote-changegroup
> +
> +  $ hg bundle -R repo --base '0:4' -r '5:7' bundle4.hg
> +  3 changesets found
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > remote-changegroup http://localhost:$HGPORT/bundle4.hg bundle4.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 at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | @  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | o  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at 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' bundle5.hg
> +  2 changesets found
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > remote-changegroup http://localhost:$HGPORT/bundle5.hg bundle5.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 at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | @  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at 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' bundle6.hg
> +  3 changesets found
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > changegroup 000000000000 :4
> +  > remote-changegroup http://localhost:$HGPORT/bundle6.hg bundle6.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 at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | @  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at 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' bundle7.hg
> +  2 changesets found
> +  $ hg bundle -R repo --base '3:4' -r '5:6' bundle8.hg
> +  2 changesets found
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > remote-changegroup http://localhost:$HGPORT/bundle7.hg bundle7.hg
> +  > remote-changegroup http://localhost:$HGPORT/bundle8.hg bundle8.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 at gmail.com>  H
> +  |
> +  | o  6:eea13746799a public Nicolas Dumazet <nicdumz.commits at gmail.com>  G
> +  |/|
> +  o |  5:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits at gmail.com>  F
> +  | |
> +  | o  4:9520eea781bc public Nicolas Dumazet <nicdumz.commits at gmail.com>  E
> +  |/
> +  | o  3:32af7686d403 public Nicolas Dumazet <nicdumz.commits at gmail.com>  D
> +  | |
> +  | @  2:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits at gmail.com>  C
> +  | |
> +  | o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |/
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at gmail.com>  A
> +
> +  $ rm -rf clone
> +
> +Hash digest tests
> +
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle.hg', 'size': 1663, 'digests': 'sha1', '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/bundle.hg', 'size': 1663, 'digests': 'md5', '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/bundle.hg', 'size': 1663, 'digests': 'sha1', '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/bundle.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/bundle.hg', 'size': 1663, 'digests': 'md5 sha1', 'md5': 'e22172c2907ef88794b7bea6642c2394', '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/bundle.hg', 'size': 1663, 'digests': 'md5 sha1', 'md5': '0' * 32, '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/bundle.hg is corrupted:
> +  md5 mismatch: expected 00000000000000000000000000000000, got e22172c2907ef88794b7bea6642c2394
> +  [255]
> +
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle.hg', 'size': 1663, 'digests': 'md5 sha1', 'md5': 'e22172c2907ef88794b7bea6642c2394', '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/bundle.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/bundle7.hg bundle7.hg
> +  > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle8.hg', 'size': 578, 'digests': 'sha1', '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/bundle8.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 at gmail.com>  C
> +  |
> +  o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at 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/bundle7.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]
> +
> +Size mismatch
> +
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle7.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/bundle7.hg is corrupted:
> +  size mismatch: expected 42, got 581
> +  [255]
> +
> +Unknown digest
> +
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle7.hg', 'size': 581, 'digests': 'foo', '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 - foo
> +  [255]
> +
> +Missing digest
> +
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > raw-remote-changegroup {'url': 'http://localhost:$HGPORT/bundle7.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 "sha1" param
> +  [255]
> +
> +Not an HTTP url
> +
> +  $ cat > repo/.hg/bundle2maker << EOF
> +  > raw-remote-changegroup {'url': 'ssh://localhost:$HGPORT/bundle7.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
> +  > HG2X
> +  > 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 at gmail.com>  C
> +  |
> +  o  1:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits at gmail.com>  B
> +  |
> +  o  0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits at gmail.com>  A
> +
> +  $ rm -rf clone
> +
> +  $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
>

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list