[PATCH 2 of 2] bundle2: add support for changegroup2

Pierre-Yves David pierre-yves.david at ens-lyon.org
Wed Sep 3 11:12:33 CDT 2014



On 09/02/2014 12:43 PM, Sune Foldager wrote:
> # HG changeset patch
> # User Sune Foldager <cryo at cyanite.org>
> # Date 1409654405 -7200
> #      Tue Sep 02 12:40:05 2014 +0200
> # Node ID 67ef070167adfe202310ac0a3783df82b813ee38
> # Parent  6e8fe07ad948009f64ea7f199d1c3e3ca22b92c4
> bundle2: add support for changegroup2
>
> Changegroup format 2 includes the delta parent for each chunk so we can create
> more efficient changegroups when using generaldelta.

This changesets needs to be split into multiple ones so that each 
semantic changes can be reviewed as its own context. This will also 
helps to get the consensual bits in while we polish the last ones.

It is okay to introduce code that stay unused until other patches land.


> diff -r 6e8fe07ad948 -r 67ef070167ad mercurial/bundle2.py
> --- a/mercurial/bundle2.py	Tue Sep 02 12:11:36 2014 +0200
> +++ b/mercurial/bundle2.py	Tue Sep 02 12:40:05 2014 +0200
> @@ -820,7 +820,7 @@
>       # we need to make sure we trigger the creation of a transaction object used
>       # for the whole processing scope.
>       op.gettransaction()
> -    cg = changegroup.cg1unpacker(inpart, 'UN')
> +    cg = changegroup.cg2unpacker(inpart, 'UN')
>       ret = changegroup.addchangegroup(op.repo, cg, 'bundle2', 'bundle2')
>       op.records.add('changegroup', {'return': ret})
>       if op.reply is not None:

If you do that, all the people who are nice enough to test the 
experimental version of bundle2 will get a crash on pull and push when 
one of the sides is not aware about "cg2".

Please advertise a new capability with a list of version to let the 
client and the server negociates the cg version to be used.

This should also go into another patch and the cg2 parts. If you do not 
have time to get to the capability stuff, I'm okay with doing it myself 
as long as the cg2 part are done.

The option to use cg1 in bundle2 may be dropped when we makes bundle2 
non-experimental (s/HG2X/HG20/) but we needs ot for now.

> diff -r 6e8fe07ad948 -r 67ef070167ad mercurial/changegroup.py
> --- a/mercurial/changegroup.py	Tue Sep 02 12:11:36 2014 +0200
> +++ b/mercurial/changegroup.py	Tue Sep 02 12:40:05 2014 +0200
> @@ -13,6 +13,7 @@
>   import discovery, error, phases, branchmap
>
>   _CHANGEGROUPV1_DELTA_HEADER = "20s20s20s20s"
> +_CHANGEGROUPV2_DELTA_HEADER = "20s20s20s20s20s"
>
>   def readexactly(stream, n):
>       '''read n bytes from stream.read and abort if less was available'''
> @@ -215,6 +216,15 @@
>                       pos = next
>               yield closechunk()
>
> +class cg2unpacker(cg1unpacker):
> +    deltaheader = _CHANGEGROUPV2_DELTA_HEADER
> +    deltaheadersize = struct.calcsize(deltaheader)
> +
> +    def _deltaheader(self, headertuple, prevnode):
> +        node, p1, p2, deltabase, cs = headertuple
> +        return node, p1, p2, deltabase, cs
> +
> +
>   class headerlessfixup(object):
>       def __init__(self, fh, h):
>           self._h = h
> @@ -410,10 +420,13 @@
>                                           reorder=reorder):
>                       yield chunk
>
> +    def deltaparent(self, revlog, rev, p1, p2, prev):
> +        return prev
> +
>       def revchunk(self, revlog, rev, prev, linknode):
>           node = revlog.node(rev)
>           p1, p2 = revlog.parentrevs(rev)
> -        base = prev
> +        base = self.deltaparent(revlog, rev, p1, p2, prev)
>
>           prefix = ''
>           if base == nullrev:
> @@ -433,6 +446,28 @@
>           # do nothing with basenode, it is implicitly the previous one in HG10
>           return struct.pack(self.deltaheader, node, p1n, p2n, linknode)
>
> +class cg2packer(cg1packer):
> +
> +    deltaheader = _CHANGEGROUPV2_DELTA_HEADER
> +
> +    def group(self, nodelist, revlog, lookup, units=None, reorder=None):
> +        if (revlog._generaldelta and reorder is not True):
> +            reorder = False
> +        return cg1packer.group(self, nodelist, revlog, lookup,
> +                               units=units, reorder=reorder)
> +
> +    def deltaparent(self, revlog, rev, p1, p2, prev):
> +        dp = revlog.deltaparent(rev)
> +        #print 'rev %d dp %d p1 %d p2 %d prev %d' % (rev, dp, p1, p2, prev)

boo, spurious print

> +        # avoid storing full revisions; pick prev in those cases
> +        # also pick prev when we can't be sure remote has dp

You can maybe expand the comment to says that picking "prev" when we 
can't be sure remote has dp is corrent but may be suboptimal. So that 
some else looking at improving the code feels empowered to do so.

> +        if dp == nullrev or (dp != p1 and dp != p2 and dp != prev):
> +            return prev
> +        return dp
> +
> +    def builddeltaheader(self, node, p1n, p2n, basenode, linknode):
> +        return struct.pack(self.deltaheader, node, p1n, p2n, basenode, linknode)
> +
>   def _changegroupinfo(repo, nodes, source):
>       if repo.ui.verbose or source == 'bundle':
>           repo.ui.status(_("%d changesets found\n") % len(nodes))
> @@ -524,6 +559,24 @@
>       outgoing = _computeoutgoing(repo, heads, common)
>       return getlocalchangegroup(repo, source, outgoing, bundlecaps=bundlecaps)
>
> +def getlocalchangegroup2(repo, source, outgoing, bundlecaps=None):
> +    if not outgoing.missing:
> +        return None
> +    bundler = cg2packer(repo, bundlecaps)
> +    repo = repo.unfiltered()
> +    commonrevs = outgoing.common
> +    csets = outgoing.missing
> +    heads = outgoing.missingheads
> +    heads.sort()
> +    fastpathlinkrev = repo.filtername is None and heads == sorted(repo.heads())
> +    repo.hook('preoutgoing', throw=True, source=source)
> +    _changegroupinfo(repo, csets, source)
> +    return bundler.generate(commonrevs, csets, fastpathlinkrev, source)
> +
> +def getchangegroup2(repo, source, heads=None, common=None, bundlecaps=None):
> +    outgoing = _computeoutgoing(repo, heads, common)
> +    return getlocalchangegroup2(repo, source, outgoing, bundlecaps=bundlecaps)
> +
>   def changegroup(repo, basenodes, source):
>       # to avoid a race we use changegroupsubset() (issue1320)
>       return changegroupsubset(repo, basenodes, repo.heads(), source)
> diff -r 6e8fe07ad948 -r 67ef070167ad mercurial/exchange.py
> --- a/mercurial/exchange.py	Tue Sep 02 12:11:36 2014 +0200
> +++ b/mercurial/exchange.py	Tue Sep 02 12:40:05 2014 +0200
> @@ -401,8 +401,8 @@
>                                        pushop.outgoing)
>       if not pushop.force:
>           bundler.newpart('B2X:CHECK:HEADS', data=iter(pushop.remoteheads))
> -    cg = changegroup.getlocalchangegroup(pushop.repo, 'push', pushop.outgoing)
> -    cgpart = bundler.newpart('B2X:CHANGEGROUP', data=cg.getchunks())
> +    cg = changegroup.getlocalchangegroup2(pushop.repo, 'push', pushop.outgoing)
> +    cgpart = bundler.newpart('B2X:CHANGEGROUP', data=cg)

Same that for getbundle, please extract this in another patches and 
makes it possible to keep using cg1

>       def handlereply(op):
>           """extract addchangroup returns from server reply"""
>           cgreplies = op.records.getreplies(cgpart.id)
> @@ -976,28 +976,27 @@
>       The implementation is at a very early stage and will get massive rework
>       when the API of bundle is refined.
>       """
> -    cg = None
> -    if kwargs.get('cg', True):
> -        # build changegroup bundle here.
> -        cg = changegroup.getchangegroup(repo, source, heads=heads,
> -                                         common=common, bundlecaps=bundlecaps)
> -    elif 'HG2X' not in bundlecaps:
> -        raise ValueError(_('request for bundle10 must include changegroup'))
>       if bundlecaps is None or 'HG2X' not in bundlecaps:
>           if kwargs:
>               raise ValueError(_('unsupported getbundle arguments: %s')
>                                % ', '.join(sorted(kwargs.keys())))
> -        return cg
> +        return changegroup.getchangegroup(repo, source, heads=heads,
> +                                   common=common, bundlecaps=bundlecaps)
> +
>       # very crude first implementation,
>       # the bundle API will change and the generation will be done lazily.
> +    cg = None
>       b2caps = {}
>       for bcaps in bundlecaps:
>           if bcaps.startswith('bundle2='):
>               blob = urllib.unquote(bcaps[len('bundle2='):])
>               b2caps.update(bundle2.decodecaps(blob))
>       bundler = bundle2.bundle20(repo.ui, b2caps)
> -    if cg:
> -        bundler.newpart('b2x:changegroup', data=cg.getchunks())
> +    if kwargs.get('cg', True):
> +        cg = changegroup.getchangegroup2(repo, source, heads=heads,
> +                                   common=common, bundlecaps=bundlecaps)
> +        if cg:
> +            bundler.newpart('b2x:changegroup', data=cg)
>       listkeys = kwargs.get('listkeys', ())
>       for namespace in listkeys:
>           part = bundler.newpart('b2x:listkeys')

Please do the reordering//refactor in another changeset so that the 
actual changes (that should also be in another patches) are easier to 
review.

Also install capability negotiation here as discussed before.


We should probably consider to move the code in a _getbundlecgpart 
function to help extension to wrap it.

> diff -r 6e8fe07ad948 -r 67ef070167ad tests/test-bundle2.t
> --- a/tests/test-bundle2.t	Tue Sep 02 12:11:36 2014 +0200
> +++ b/tests/test-bundle2.t	Tue Sep 02 12:40:05 2014 +0200

Please to not touch the test-bundle2.t file to tests bundle2 -part- 
behavior. either introduce a new test or tests the packer//unpacker in a 
changegroup related tests.

> @@ -106,8 +106,8 @@
>     >             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.getlocalchangegroup(repo, 'test:bundle2', outgoing, None)
> -  >             bundler.newpart('b2x:changegroup', data=cg.getchunks())
> +  >             cg = changegroup.getlocalchangegroup2(repo, 'test:bundle2', outgoing, None)
> +  >             bundler.newpart('b2x:changegroup', data=cg)
>     >
>     >     if opts['parts']:
>     >        bundler.newpart('test:empty')
> @@ -719,26 +719,26 @@
>     end of bundle
>
>     $ cat ../rev.hg2
> -  HG2X\x00\x00\x00\x16\x0fb2x:changegroup\x00\x00\x00\x00\x00\x00\x00\x00\x06\x13\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)
> +  HG2X\x00\x00\x00\x16\x0fb2x:changegroup\x00\x00\x00\x00\x00\x00\x00\x00\x06\xef\x00\x00\x00\xb82\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\x00_\xdd\xd9\x89W\xc8\xa5JMCm\xfe\x1d\xa9\xd8\x7f!\xa1\xb9{2\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\x00i\x00\x00\x00j\x00\x00\x00\x01D\x00\x00\x00\xb8\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\x002\xafv\x86\xd4\x03\xcfE\xb5\xd9_-p\xce\xbe\xa5\x87\xac\x80j\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)
> +  \x00\x00\x00i\x00\x00\x00j\x00\x00\x00\x01E\x00\x00\x00\xb6\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$\xb68|\x8c\x8c\xae7\x17\x88\x80\xf3\xfa\x95\xde\xd3\xcb\x1c\xf7\x85\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\xb8\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\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\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)
> +  \x00\x00\x00g\x00\x00\x00h\x00\x00\x00\x01H\x00\x00\x00\x00\x00\x00\x00\x9fn\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\x00f\xa5\xa0\x18\x17\xfd\xf5#\x9c'8\x02\xb5\xb7a\x8d\x05\x1c\x89\xe42\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\x9fM\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\x00n\x1fLG\xec\xb53\xff\xd0\xc8\xe5,\xdc\x88\xaf\xb6\xcd9\xe2\x0c\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\x9f6[\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}(\xa5\x84\xc6^\xf1!\xf8\x9e\xb6j\xb7\xd0\xbc\x15=\x80\x99\xe7\xce\xee\xa17Fy\x9a\x9e\x0b\xfd\x88\xf2\x9d<.\x9d\xc98\x9fRO\x00\x00\x00+\x00\x00\x00+\x00\x00\x00+E\x009c6fd0350a6c0d0c49d4a9c5017cf07043f54e58 (esc)
> +  \x00\x00\x00\xab\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\x006[\x93\xd5\x7f\xdfH\x14\xe2\xb5\x91\x1dk\xac\xff+\x12\x01DA\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)
> +  \x00\x00\x00\x00\x00\x00\x00\x05D\x00\x00\x00v\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\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\x00v\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)
> +  \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\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\x00v\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\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)
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list