bundle2: add some distinction between mandatory and advisory part
Mandatory part cannot be ignored when unknown. We raise a simple KeyError
exception when this happen.
This is very early version of this logic, see inline comment for future
improvement lead.
--- a/mercurial/bundle2.py Mon Mar 24 15:51:00 2014 -0700
+++ b/mercurial/bundle2.py Mon Mar 24 13:02:02 2014 -0700
@@ -119,6 +119,19 @@
The current implementation always produces either zero or one chunk.
This is an implementation limitation that will ultimatly be lifted.
+
+Bundle processing
+============================
+
+Each part is processed in order using a "part handler". Handler are registered
+for a certain part type.
+
+The matching of a part to its handler is case insensitive. The case of the
+part type is used to know if a part is mandatory or advisory. If the Part type
+contains any uppercase char it is considered mandatory. When no handler is
+known for a Mandatory part, the process is aborted and an exception is raised.
+If the part is advisory and no handler is known, the part is ignored.
+
"""
import util
@@ -161,8 +174,9 @@
...
"""
def _decorator(func):
- assert parttype not in parthandlermapping
- parthandlermapping[parttype] = func
+ lparttype = parttype.lower() # enforce lower case matching.
+ assert lparttype not in parthandlermapping
+ parthandlermapping[lparttype] = func
return func
return _decorator
@@ -179,8 +193,7 @@
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).
+ Unknown Mandatory part will abort the process.
"""
ui = repo.ui
# Extraction of the unbundler object will most likely change. It may be
@@ -200,6 +213,11 @@
handler = parthandlermapping[key]
ui.debug('found an handler for part %r\n' % parttype)
except KeyError:
+ if key != parttype: # mandatory parts
+ # todo:
+ # - use a more precise exception
+ # - consume the bundle2 stream anyway.
+ raise
ui.debug('ignoring unknown advisory part %r\n' % key)
# todo: consume the part (once we use streamed parts)
continue
--- a/tests/test-bundle2.t Mon Mar 24 15:51:00 2014 -0700
+++ b/tests/test-bundle2.t Mon Mar 24 13:02:02 2014 -0700
@@ -29,6 +29,7 @@
>
> @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'),],
> '[OUTPUTFILE]')
> def cmdbundle2(ui, repo, path=None, **opts):
@@ -54,6 +55,10 @@
> [('cooking', 'raw')],
> '42')
> bundler.addpart(part)
+ > if opts['unknown']:
+ > part = bundle2.part('test:UNKNOWN',
+ > data='some random content')
+ > bundler.addpart(part)
>
> if path is None:
> file = sys.stdout
@@ -66,7 +71,10 @@
> @command('unbundle2', [], '')
> def cmdunbundle2(ui, repo):
> """process a bundle2 stream from stdin on the current repo"""
- > bundle2.processbundle(repo, sys.stdin)
+ > try:
+ > bundle2.processbundle(repo, sys.stdin)
+ > except KeyError, exc:
+ > raise util.Abort('missing support for %s' % exc)
>
> @command('statbundle2', [], '')
> def cmdstatbundle2(ui, repo):
@@ -377,3 +385,14 @@
ignoring unknown advisory part 'test:math'
part header size: 0
end of bundle2 stream
+
+
+ $ hg bundle2 --parts --unknown ../unknown.hg2
+
+ $ hg unbundle2 < ../unknown.hg2
+ 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.
+ abort: missing support for 'test:unknown'
+ [255]