Patchwork [4,of,4] bundle2: first crude version of bundling changeset with bundle2

login
register
mail settings
Submitter Pierre-Yves David
Date April 3, 2014, 10:57 p.m.
Message ID <2886b653839315fd5ef6.1396565871@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/4214/
State Superseded
Commit c7ceae0faf6997ff3c262a0b641719b6fd357055
Headers show

Comments

Pierre-Yves David - April 3, 2014, 10:57 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1395715079 25200
#      Mon Mar 24 19:37:59 2014 -0700
# Node ID 2886b653839315fd5ef6b4ad174b06399822afad
# Parent  44096fd181296f228c1f2d869b53034b55d2bac9
bundle2: first crude version of bundling changeset with bundle2

The current changegroup format is put in a "changegroup" part and processed by
an appropriate handlers.

This is not production ready code, but let us start smoke testing.
Durham Goode - April 4, 2014, 2:32 a.m.
On 4/3/14 3:57 PM, pierre-yves.david@ens-lyon.org wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1395715079 25200
> #      Mon Mar 24 19:37:59 2014 -0700
> # Node ID 2886b653839315fd5ef6b4ad174b06399822afad
> # Parent  44096fd181296f228c1f2d869b53034b55d2bac9
> bundle2: first crude version of bundling changeset with bundle2
>
> The current changegroup format is put in a "changegroup" part and processed by
> an appropriate handlers.
>
> This is not production ready code, but let us start smoke testing.
Generally looks good.  Couple inline comments.
> diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
> --- a/mercurial/bundle2.py
> +++ b/mercurial/bundle2.py
> @@ -139,10 +139,11 @@ preserve.
>   
>   import util
>   import struct
>   import urllib
>   import string
> +import StringIO
>   
>   import changegroup
>   from i18n import _
>   
>   _pack = struct.pack
> @@ -525,5 +526,19 @@ class part(object):
>               yield _pack(_fpayloadsize, len(self.data))
>               yield self.data
>           # end of payload
>           yield _pack(_fpayloadsize, 0)
>   
> +@parthandler('changegroup')
> +def handlechangegroup(op, part):
> +    """apply a changegroup part on the repo
> +
> +    This is a very early implementation that will massive rework before being
> +    inflicted to any end-user.
> +    """
> +    data = StringIO.StringIO(part.data)
> +    data.seek(0)
The StringIO docs say it starts at 0.  Is the seek necessary?

> +
> +  $ hg bundle2 --debug --rev '8+7+5+4' ../rev.hg2
> +  4 changesets found
> +  list of changesets:
> +  32af7686d403cf45b5d95f2d70cebea587ac806a
> +  9520eea781bcca16c1e15acc0ba14335a0e8e5ba
> +  eea13746799a9e0bfd88f29d3c2e9dc9389f524f
> +  02de42196ebee42ef284b6780a87cdc96e8eaab6
> +  bundling: 1/4 changesets (25.00%)
> +  bundling: 2/4 changesets (50.00%)
> +  bundling: 3/4 changesets (75.00%)
> +  bundling: 4/4 changesets (100.00%)
> +  bundling: 1/4 manifests (25.00%)
> +  bundling: 2/4 manifests (50.00%)
> +  bundling: 3/4 manifests (75.00%)
> +  bundling: 4/4 manifests (100.00%)
> +  bundling: D 1/3 files (33.33%)
> +  bundling: E 2/3 files (66.67%)
> +  bundling: H 3/3 files (100.00%)
> +  start emission of HG20 stream
> +  bundle parameter:
> +  start of parts
> +  bundle part: "changegroup"
> +  end of bundle
> +
> +  $ cat ../rev.hg2
> +  HG20\x00\x00\x00\x0e\x0bchangegroup\x00\x00\x00\x00\x06\x19HG10UN\x00\x00\x00\xa42\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j_\xdd\xd9\x89W\xc8\xa5JMCm\xfe\x1d\xa9\xd8\x7f!\xa1\xb9{\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)6e1f4c47ecb533ffd0c8e52cdc88afb6cd39e20c (esc)
> +  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x02D (esc)
> +  \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01D\x00\x00\x00\xa4\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\xcd\x01\x0b\x8c\xd9\x98\xf3\x98\x1aZ\x81\x15\xf9O\x8d\xa4\xabP`\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)4dece9c826f69490507b98c6383a3009b295837d (esc)
> +  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x02E (esc)
> +  \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01E\x00\x00\x00\xa2\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)365b93d57fdf4814e2b5911d6bacff2b12014441 (esc)
> +  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x00\x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01G\x00\x00\x00\xa4\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
> +  \x87\xcd\xc9n\x8e\xaa\xb6$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
> +  \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)8bee48edc7318541fc0013ee41b089276a8c24bf (esc)
> +  \x00\x00\x00f\x00\x00\x00f\x00\x00\x00\x02H (esc)
> +  \x00\x00\x00g\x00\x00\x00h\x00\x00\x00\x01H\x00\x00\x00\x00\x00\x00\x00\x8bn\x1fLG\xec\xb53\xff\xd0\xc8\xe5,\xdc\x88\xaf\xb6\xcd9\xe2\x0cf\xa5\xa0\x18\x17\xfd\xf5#\x9c'8\x02\xb5\xb7a\x8d\x05\x1c\x89\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x81\x00\x00\x00\x81\x00\x00\x00+D\x00c3f1ca2924c16a19b0656a84900e504e5b0aec2d (esc)
> +  \x00\x00\x00\x8bM\xec\xe9\xc8&\xf6\x94\x90P{\x98\xc68:0	\xb2\x95\x83}\x00}\x8c\x9d\x88\x84\x13%\xf5\xc6\xb0cq\xb3[N\x8a+\x1a\x83\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00+\x00\x00\x00\xac\x00\x00\x00+E\x009c6fd0350a6c0d0c49d4a9c5017cf07043f54e58 (esc)
> +  \x00\x00\x00\x8b6[\x93\xd5\x7f\xdfH\x14\xe2\xb5\x91\x1dk\xac\xff+\x12\x01DA(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xceM\xec\xe9\xc8&\xf6\x94\x90P{\x98\xc68:0	\xb2\x95\x83}\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00V\x00\x00\x00V\x00\x00\x00+F\x0022bfcfd62a21a3287edbd4d656218d0f525ed76a (esc)
> +  \x00\x00\x00\x97\x8b\xeeH\xed\xc71\x85A\xfc\x00\x13\xeeA\xb0\x89'j\x8c$\xbf(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
> +  \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00+\x00\x00\x00V\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x81\x00\x00\x00+H\x008500189e74a9e0475e822093bc7db0d631aeb0b4 (esc)
> +  \x00\x00\x00\x00\x00\x00\x00\x05D\x00\x00\x00b\xc3\xf1\xca)$\xc1j\x19\xb0ej\x84\x90\x0ePN[ (esc)
> +  \xec-\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02D (esc)
> +  \x00\x00\x00\x00\x00\x00\x00\x05E\x00\x00\x00b\x9co\xd05 (esc)
> +  l\r (no-eol) (esc)
> +  \x0cI\xd4\xa9\xc5\x01|\xf0pC\xf5NX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02E (esc)
> +  \x00\x00\x00\x00\x00\x00\x00\x05H\x00\x00\x00b\x85\x00\x18\x9et\xa9\xe0G^\x82 \x93\xbc}\xb0\xd61\xae\xb0\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
> +  \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02H (esc)
> +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
> +
I'm not sure how useful having the blob of binary in the test will be. 
It will only catch issues where someone makes a change and didn't expect 
the format to change. It won't help people verify that their changes to 
the format are correct. Checking a hash, or the file size, will catch 
most of the same issues without the verboseness.
> +  $ hg unbundle2 < ../rev.hg2
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 0 changesets with 0 changes to 3 files
> +  0 unread bytes
> +  addchangegroup return: 1
>
Would it be better to strip the nodes, then unbundle? Perhaps with a 
verify to make sure it actually worked?  Seems like an odd test to do a 
no-op unbundle.
Pierre-Yves David - April 4, 2014, 5:57 p.m.
On 04/03/2014 07:32 PM, Durham Goode wrote:
>
> On 4/3/14 3:57 PM, pierre-yves.david@ens-lyon.org wrote:
>> # HG changeset patch
>> # User Pierre-Yves David <pierre-yves.david@fb.com>
>> # Date 1395715079 25200
>> #      Mon Mar 24 19:37:59 2014 -0700
>> # Node ID 2886b653839315fd5ef6b4ad174b06399822afad
>> # Parent  44096fd181296f228c1f2d869b53034b55d2bac9
>> bundle2: first crude version of bundling changeset with bundle2
>>
>> The current changegroup format is put in a "changegroup" part and
>> processed by
>> an appropriate handlers.
>>
>> This is not production ready code, but let us start smoke testing.
> Generally looks good.  Couple inline comments.
>> diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
>> --- a/mercurial/bundle2.py
>> +++ b/mercurial/bundle2.py
>> @@ -139,10 +139,11 @@ preserve.
>>   import util
>>   import struct
>>   import urllib
>>   import string
>> +import StringIO
>>   import changegroup
>>   from i18n import _
>>   _pack = struct.pack
>> @@ -525,5 +526,19 @@ class part(object):
>>               yield _pack(_fpayloadsize, len(self.data))
>>               yield self.data
>>           # end of payload
>>           yield _pack(_fpayloadsize, 0)
>> +@parthandler('changegroup')
>> +def handlechangegroup(op, part):
>> +    """apply a changegroup part on the repo
>> +
>> +    This is a very early implementation that will massive rework
>> before being
>> +    inflicted to any end-user.
>> +    """
>> +    data = StringIO.StringIO(part.data)
>> +    data.seek(0)
> The StringIO docs say it starts at 0.  Is the seek necessary?


Standard paranoia with StringIO. I would keep the seek as it is harmless.

>
>> +
>> +  $ hg bundle2 --debug --rev '8+7+5+4' ../rev.hg2
>> +  4 changesets found
>> +  list of changesets:
>> +  32af7686d403cf45b5d95f2d70cebea587ac806a
>> +  9520eea781bcca16c1e15acc0ba14335a0e8e5ba
>> +  eea13746799a9e0bfd88f29d3c2e9dc9389f524f
>> +  02de42196ebee42ef284b6780a87cdc96e8eaab6
>> +  bundling: 1/4 changesets (25.00%)
>> +  bundling: 2/4 changesets (50.00%)
>> +  bundling: 3/4 changesets (75.00%)
>> +  bundling: 4/4 changesets (100.00%)
>> +  bundling: 1/4 manifests (25.00%)
>> +  bundling: 2/4 manifests (50.00%)
>> +  bundling: 3/4 manifests (75.00%)
>> +  bundling: 4/4 manifests (100.00%)
>> +  bundling: D 1/3 files (33.33%)
>> +  bundling: E 2/3 files (66.67%)
>> +  bundling: H 3/3 files (100.00%)
>> +  start emission of HG20 stream
>> +  bundle parameter:
>> +  start of parts
>> +  bundle part: "changegroup"
>> +  end of bundle
>> +
>> +  $ cat ../rev.hg2
>> +
>> HG20\x00\x00\x00\x0e\x0bchangegroup\x00\x00\x00\x00\x06\x19HG10UN\x00\x00\x00\xa42\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j_\xdd\xd9\x89W\xc8\xa5JMCm\xfe\x1d\xa9\xd8\x7f!\xa1\xb9{\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)6e1f4c47ecb533ffd0c8e52cdc88afb6cd39e20c
>> (esc)
>> +  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x02D (esc)
>> +  \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01D\x00\x00\x00\xa4\x95
>> \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\xcd\x01\x0b\x8c\xd9\x98\xf3\x98\x1aZ\x81\x15\xf9O\x8d\xa4\xabP`\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95
>> \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)4dece9c826f69490507b98c6383a3009b295837d
>> (esc)
>> +  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x02E (esc)
>> +
>> \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01E\x00\x00\x00\xa2\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\x95
>> \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)365b93d57fdf4814e2b5911d6bacff2b12014441
>> (esc)
>> +
>> \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x00\x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01G\x00\x00\x00\xa4\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x
>> (esc)
>> +
>> \x87\xcd\xc9n\x8e\xaa\xb6$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x
>> (esc)
>> +
>> \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)8bee48edc7318541fc0013ee41b089276a8c24bf
>> (esc)
>> +  \x00\x00\x00f\x00\x00\x00f\x00\x00\x00\x02H (esc)
>> +
>> \x00\x00\x00g\x00\x00\x00h\x00\x00\x00\x01H\x00\x00\x00\x00\x00\x00\x00\x8bn\x1fLG\xec\xb53\xff\xd0\xc8\xe5,\xdc\x88\xaf\xb6\xcd9\xe2\x0cf\xa5\xa0\x18\x17\xfd\xf5#\x9c'8\x02\xb5\xb7a\x8d\x05\x1c\x89\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x81\x00\x00\x00\x81\x00\x00\x00+D\x00c3f1ca2924c16a19b0656a84900e504e5b0aec2d
>> (esc)
>> +  \x00\x00\x00\x8bM\xec\xe9\xc8&\xf6\x94\x90P{\x98\xc68:0
>> \xb2\x95\x83}\x00}\x8c\x9d\x88\x84\x13%\xf5\xc6\xb0cq\xb3[N\x8a+\x1a\x83\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95
>> \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00+\x00\x00\x00\xac\x00\x00\x00+E\x009c6fd0350a6c0d0c49d4a9c5017cf07043f54e58
>> (esc)
>> +
>> \x00\x00\x00\x8b6[\x93\xd5\x7f\xdfH\x14\xe2\xb5\x91\x1dk\xac\xff+\x12\x01DA(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xceM\xec\xe9\xc8&\xf6\x94\x90P{\x98\xc68:0
>> \xb2\x95\x83}\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00V\x00\x00\x00V\x00\x00\x00+F\x0022bfcfd62a21a3287edbd4d656218d0f525ed76a
>> (esc)
>> +
>> \x00\x00\x00\x97\x8b\xeeH\xed\xc71\x85A\xfc\x00\x13\xeeA\xb0\x89'j\x8c$\xbf(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x
>> (esc)
>> +
>> \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00+\x00\x00\x00V\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x81\x00\x00\x00+H\x008500189e74a9e0475e822093bc7db0d631aeb0b4
>> (esc)
>> +
>> \x00\x00\x00\x00\x00\x00\x00\x05D\x00\x00\x00b\xc3\xf1\xca)$\xc1j\x19\xb0ej\x84\x90\x0ePN[
>> (esc)
>> +
>> \xec-\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02D
>> (esc)
>> +  \x00\x00\x00\x00\x00\x00\x00\x05E\x00\x00\x00b\x9co\xd05 (esc)
>> +  l\r (no-eol) (esc)
>> +
>> \x0cI\xd4\xa9\xc5\x01|\xf0pC\xf5NX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95
>> \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02E
>> (esc)
>> +
>> \x00\x00\x00\x00\x00\x00\x00\x05H\x00\x00\x00b\x85\x00\x18\x9et\xa9\xe0G^\x82
>> \x93\xbc}\xb0\xd61\xae\xb0\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x
>> (esc)
>> +
>> \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02H
>> (esc)
>> +  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol)
>> (esc)
>> +
> I'm not sure how useful having the blob of binary in the test will be.
> It will only catch issues where someone makes a change and didn't expect
> the format to change. It won't help people verify that their changes to
> the format are correct. Checking a hash, or the file size, will catch
> most of the same issues without the verboseness.

We are currently building the format from the scratch. I find it useful 
to have verbose failure and comparison when anything change. And it have 
proved useful in the past.

>> +  $ hg unbundle2 < ../rev.hg2
>> +  adding changesets
>> +  adding manifests
>> +  adding file changes
>> +  added 0 changesets with 0 changes to 3 files
>> +  0 unread bytes
>> +  addchangegroup return: 1
>>
> Would it be better to strip the nodes, then unbundle? Perhaps with a
> verify to make sure it actually worked?  Seems like an odd test to do a
> no-op unbundle.

I just want to make sure the unbundling code is called. I trust the code 
to generate a valid bundle and the addchangegroup function to properly 
unbundle it. The above output is a proff that addchangegroup have been 
called and is enough for this test.

Patch

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -139,10 +139,11 @@  preserve.
 
 import util
 import struct
 import urllib
 import string
+import StringIO
 
 import changegroup
 from i18n import _
 
 _pack = struct.pack
@@ -525,5 +526,19 @@  class part(object):
             yield _pack(_fpayloadsize, len(self.data))
             yield self.data
         # end of payload
         yield _pack(_fpayloadsize, 0)
 
+@parthandler('changegroup')
+def handlechangegroup(op, part):
+    """apply a changegroup part on the repo
+
+    This is a very early implementation that will massive rework before being
+    inflicted to any end-user.
+    """
+    data = StringIO.StringIO(part.data)
+    data.seek(0)
+    cg = changegroup.readbundle(data, 'bundle2part')
+    ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
+    op.records.add('changegroup', {'return': ret})
+
+
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -10,10 +10,13 @@  Create an extension to test bundle2 API
   > 
   > import sys
   > from mercurial import cmdutil
   > from mercurial import util
   > from mercurial import bundle2
+  > from mercurial import scmutil
+  > from mercurial import discovery
+  > from mercurial import changegroup
   > cmdtable = {}
   > command = cmdutil.command(cmdtable)
   > 
   > ELEPHANTSSONG = """Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
   > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
@@ -31,11 +34,12 @@  Create an extension to test bundle2 API
   >     op.records.add('song', {'verses': verses})
   > 
   > @command('bundle2',
   >          [('', 'param', [], 'stream level parameter'),
   >           ('', 'unknown', False, 'include an unknown mandatory part in the bundle'),
-  >           ('', 'parts', False, 'include some arbitrary parts to the bundle'),],
+  >           ('', 'parts', False, 'include some arbitrary parts to the bundle'),
+  >           ('r', 'rev', [], 'includes those changeset in the bundle'),],
   >          '[OUTPUTFILE]')
   > def cmdbundle2(ui, repo, path=None, **opts):
   >     """write a bundle2 container on standard ouput"""
   >     bundler = bundle2.bundle20(ui)
   >     for p in opts['param']:
@@ -43,10 +47,27 @@  Create an extension to test bundle2 API
   >         try:
   >             bundler.addparam(*p)
   >         except ValueError, exc:
   >             raise util.Abort('%s' % exc)
   > 
+  >     revs = opts['rev']
+  >     if 'rev' in opts:
+  >         revs = scmutil.revrange(repo, opts['rev'])
+  >         if revs:
+  >             # very crude version of a changegroup part creation
+  >             bundled = repo.revs('%ld::%ld', revs, revs)
+  >             headmissing = [c.node() for c in repo.set('heads(%ld)', revs)]
+  >             headcommon  = [c.node() for c in repo.set('parents(%ld) - %ld', revs, revs)]
+  >             outgoing = discovery.outgoing(repo.changelog, headcommon, headmissing)
+  >             cg = changegroup.getlocalbundle(repo, 'test:bundle2', outgoing, None)
+  >             assert cg is not None
+  >             # make me lazy later
+  >             tempname = changegroup.writebundle(cg, None, 'HG10UN')
+  >             data = open(tempname).read()
+  >             part = bundle2.part('changegroup', data=data)
+  >             bundler.addpart(part)
+  > 
   >     if opts['parts']:
   >        part = bundle2.part('test:empty')
   >        bundler.addpart(part)
   >        # add a second one to make sure we handle multiple parts
   >        part = bundle2.part('test:empty')
@@ -84,10 +105,12 @@  Create an extension to test bundle2 API
   >         remains = sys.stdin.read()
   >         ui.write('%i unread bytes\n' % len(remains))
   >     if op.records['song']:
   >         totalverses = sum(r['verses'] for r in op.records['song'])
   >         ui.write('%i total verses sung\n' % totalverses)
+  >     for rec in op.records['changegroup']:
+  >         ui.write('addchangegroup return: %i\n' % rec['return'])
   > 
   > @command('statbundle2', [], '')
   > def cmdstatbundle2(ui, repo):
   >     """print statistic on the bundle2 container read from stdin"""
   >     unbundler = bundle2.unbundle20(ui, sys.stdin)
@@ -357,12 +380,12 @@  Test part
     :test:math:
       mandatory: 2
       advisory: 1
       payload: 2 bytes
 
-Test actual unbundling
-========================
+Test actual unbundling of test part
+=======================================
 
 Process the bundle
 
   $ hg unbundle2 --debug < ../parts.hg2
   start processing of HG20 stream
@@ -408,5 +431,125 @@  Process the bundle
       Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
       Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.
   0 unread bytes
   abort: missing support for 'test:unknown'
   [255]
+
+Support for changegroup
+===================================
+
+  $ hg unbundle $TESTDIR/bundles/rebase.hg
+  adding changesets
+  adding manifests
+  adding file changes
+  added 8 changesets with 7 changes to 7 files (+3 heads)
+  (run 'hg heads' to see heads, 'hg merge' to merge)
+
+  $ hg log -G
+  o  changeset:   8:02de42196ebe
+  |  tag:         tip
+  |  parent:      6:24b6387c8c8c
+  |  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  |  date:        Sat Apr 30 15:24:48 2011 +0200
+  |  summary:     H
+  |
+  | o  changeset:   7:eea13746799a
+  |/|  parent:      6:24b6387c8c8c
+  | |  parent:      5:9520eea781bc
+  | |  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  | |  date:        Sat Apr 30 15:24:48 2011 +0200
+  | |  summary:     G
+  | |
+  o |  changeset:   6:24b6387c8c8c
+  | |  parent:      1:cd010b8cd998
+  | |  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  | |  date:        Sat Apr 30 15:24:48 2011 +0200
+  | |  summary:     F
+  | |
+  | o  changeset:   5:9520eea781bc
+  |/   parent:      1:cd010b8cd998
+  |    user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  |    date:        Sat Apr 30 15:24:48 2011 +0200
+  |    summary:     E
+  |
+  | o  changeset:   4:32af7686d403
+  | |  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  | |  date:        Sat Apr 30 15:24:48 2011 +0200
+  | |  summary:     D
+  | |
+  | o  changeset:   3:5fddd98957c8
+  | |  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  | |  date:        Sat Apr 30 15:24:48 2011 +0200
+  | |  summary:     C
+  | |
+  | o  changeset:   2:42ccdea3bb16
+  |/   user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  |    date:        Sat Apr 30 15:24:48 2011 +0200
+  |    summary:     B
+  |
+  o  changeset:   1:cd010b8cd998
+     parent:      -1:000000000000
+     user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+     date:        Sat Apr 30 15:24:48 2011 +0200
+     summary:     A
+  
+  @  changeset:   0:3903775176ed
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+
+  $ hg bundle2 --debug --rev '8+7+5+4' ../rev.hg2
+  4 changesets found
+  list of changesets:
+  32af7686d403cf45b5d95f2d70cebea587ac806a
+  9520eea781bcca16c1e15acc0ba14335a0e8e5ba
+  eea13746799a9e0bfd88f29d3c2e9dc9389f524f
+  02de42196ebee42ef284b6780a87cdc96e8eaab6
+  bundling: 1/4 changesets (25.00%)
+  bundling: 2/4 changesets (50.00%)
+  bundling: 3/4 changesets (75.00%)
+  bundling: 4/4 changesets (100.00%)
+  bundling: 1/4 manifests (25.00%)
+  bundling: 2/4 manifests (50.00%)
+  bundling: 3/4 manifests (75.00%)
+  bundling: 4/4 manifests (100.00%)
+  bundling: D 1/3 files (33.33%)
+  bundling: E 2/3 files (66.67%)
+  bundling: H 3/3 files (100.00%)
+  start emission of HG20 stream
+  bundle parameter: 
+  start of parts
+  bundle part: "changegroup"
+  end of bundle
+
+  $ cat ../rev.hg2
+  HG20\x00\x00\x00\x0e\x0bchangegroup\x00\x00\x00\x00\x06\x19HG10UN\x00\x00\x00\xa42\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j_\xdd\xd9\x89W\xc8\xa5JMCm\xfe\x1d\xa9\xd8\x7f!\xa1\xb9{\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)6e1f4c47ecb533ffd0c8e52cdc88afb6cd39e20c (esc)
+  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x02D (esc)
+  \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01D\x00\x00\x00\xa4\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\xcd\x01\x0b\x8c\xd9\x98\xf3\x98\x1aZ\x81\x15\xf9O\x8d\xa4\xabP`\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)4dece9c826f69490507b98c6383a3009b295837d (esc)
+  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x02E (esc)
+  \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01E\x00\x00\x00\xa2\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)365b93d57fdf4814e2b5911d6bacff2b12014441 (esc)
+  \x00\x00\x00f\x00\x00\x00h\x00\x00\x00\x00\x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01G\x00\x00\x00\xa4\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
+  \x87\xcd\xc9n\x8e\xaa\xb6$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
+  \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00)8bee48edc7318541fc0013ee41b089276a8c24bf (esc)
+  \x00\x00\x00f\x00\x00\x00f\x00\x00\x00\x02H (esc)
+  \x00\x00\x00g\x00\x00\x00h\x00\x00\x00\x01H\x00\x00\x00\x00\x00\x00\x00\x8bn\x1fLG\xec\xb53\xff\xd0\xc8\xe5,\xdc\x88\xaf\xb6\xcd9\xe2\x0cf\xa5\xa0\x18\x17\xfd\xf5#\x9c'8\x02\xb5\xb7a\x8d\x05\x1c\x89\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x81\x00\x00\x00\x81\x00\x00\x00+D\x00c3f1ca2924c16a19b0656a84900e504e5b0aec2d (esc)
+  \x00\x00\x00\x8bM\xec\xe9\xc8&\xf6\x94\x90P{\x98\xc68:0	\xb2\x95\x83}\x00}\x8c\x9d\x88\x84\x13%\xf5\xc6\xb0cq\xb3[N\x8a+\x1a\x83\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00+\x00\x00\x00\xac\x00\x00\x00+E\x009c6fd0350a6c0d0c49d4a9c5017cf07043f54e58 (esc)
+  \x00\x00\x00\x8b6[\x93\xd5\x7f\xdfH\x14\xe2\xb5\x91\x1dk\xac\xff+\x12\x01DA(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xceM\xec\xe9\xc8&\xf6\x94\x90P{\x98\xc68:0	\xb2\x95\x83}\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00V\x00\x00\x00V\x00\x00\x00+F\x0022bfcfd62a21a3287edbd4d656218d0f525ed76a (esc)
+  \x00\x00\x00\x97\x8b\xeeH\xed\xc71\x85A\xfc\x00\x13\xeeA\xb0\x89'j\x8c$\xbf(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
+  \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00+\x00\x00\x00V\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x81\x00\x00\x00+H\x008500189e74a9e0475e822093bc7db0d631aeb0b4 (esc)
+  \x00\x00\x00\x00\x00\x00\x00\x05D\x00\x00\x00b\xc3\xf1\xca)$\xc1j\x19\xb0ej\x84\x90\x0ePN[ (esc)
+  \xec-\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02D (esc)
+  \x00\x00\x00\x00\x00\x00\x00\x05E\x00\x00\x00b\x9co\xd05 (esc)
+  l\r (no-eol) (esc)
+  \x0cI\xd4\xa9\xc5\x01|\xf0pC\xf5NX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x95 \xee\xa7\x81\xbc\xca\x16\xc1\xe1Z\xcc\x0b\xa1C5\xa0\xe8\xe5\xba\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02E (esc)
+  \x00\x00\x00\x00\x00\x00\x00\x05H\x00\x00\x00b\x85\x00\x18\x9et\xa9\xe0G^\x82 \x93\xbc}\xb0\xd61\xae\xb0\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xdeB\x19n\xbe\xe4.\xf2\x84\xb6x (esc)
+  \x87\xcd\xc9n\x8e\xaa\xb6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02H (esc)
+  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
+
+  $ hg unbundle2 < ../rev.hg2
+  adding changesets
+  adding manifests
+  adding file changes
+  added 0 changesets with 0 changes to 3 files
+  0 unread bytes
+  addchangegroup return: 1