diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -148,6 +148,48 @@ def _makefpartparamsizes(nbparams): """ return '>'+('BB'*nbparams) + +parthandlermapping = {} + +def processbundle(repo, stream): + """This function process a bundle, apply effect to/from a repo + + Currently it: + - parse a stream into an unbundle20 object + - iterate over each parts then search and use the proper handling code to + process the part. + + Parts are processes in order. + + This is very early version of this function that will be strongly reworked + before final usage. + + All unknown parts are currently ignored (Mandatory parts logic will comes + later). + """ + ui = repo.ui + # Extraction of the unbundler object will most likely change. It may be + # done outside of this function, the unbundler would be passed as argument. + # in all case the unbundler will eventually be created by a + # `changegroup.readbundle` style function. + unbundler = unbundle20(ui, stream) + # todo: + # - replace this is a init function soon. + # - exception catching + unbundler.params + for part in unbundler: + parttype = part.type + # part key are matched lower case + key = parttype.lower() + try: + handler = parthandlermapping[key] + ui.debug('found an handler for part %r\n' % parttype) + except KeyError: + ui.debug('ignoring unknown advisory part %r\n' % key) + # todo: consume the part (once we use streamed parts) + continue + handler(repo, part) + class bundle20(object): """represent an outgoing bundle2 container diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t --- a/tests/test-bundle2.t +++ b/tests/test-bundle2.t @@ -20,6 +20,14 @@ Create an extension to test bundle2 API > Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.""" > assert len(ELEPHANTSSONG) == 178 # future test say 178 bytes, trust it. > + > def songhandler(repo, part): + > """handle a "test:song" bundle2 part, printing the lyrics on stdin""" + > repo.ui.write('The choir start singing:\n') + > for line in part.data.split('\n'): + > repo.ui.write(' %s\n' % line) + > + > bundle2.parthandlermapping['test:song'] = songhandler + > > @command('bundle2', > [('', 'param', [], 'stream level parameter'), > ('', 'parts', False, 'include some arbitrary parts to the bundle'),], @@ -56,6 +64,11 @@ Create an extension to test bundle2 API > for chunk in bundler.getchunks(): > file.write(chunk) > + > @command('unbundle2', [], '') + > def cmdunbundle2(ui, repo): + > """process a bundle2 stream from stdin on the current repo""" + > bundle2.processbundle(repo, sys.stdin) + > > @command('statbundle2', [], '') > def cmdstatbundle2(ui, repo): > """print statistic on the bundle2 container read from stdin""" @@ -327,3 +340,41 @@ Test part mandatory: 2 advisory: 1 payload: 2 bytes + +Test actual unbundling +======================== + +Process the bundle + + $ hg unbundle2 --debug < ../parts.hg2 + start processing of HG20 stream + reading bundle2 stream parameters + start extraction of bundle2 parts + part header size: 13 + part type: "test:empty" + part parameters: 0 + payload chunk size: 0 + ignoring unknown advisory part 'test:empty' + part header size: 13 + part type: "test:empty" + part parameters: 0 + payload chunk size: 0 + ignoring unknown advisory part 'test:empty' + part header size: 12 + part type: "test:song" + part parameters: 0 + payload chunk size: 178 + payload chunk size: 0 + found an handler for part 'test:song' + The choir start singing: + Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko + Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko + Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko. + part header size: 39 + part type: "test:math" + part parameters: 3 + payload chunk size: 2 + payload chunk size: 0 + ignoring unknown advisory part 'test:math' + part header size: 0 + end of bundle2 stream