bundle2: add some distinction between mandatory and advisory part
authorPierre-Yves David <pierre-yves.david@fb.com>
Mon, 24 Mar 2014 13:02:02 -0700
changeset 20891 1c6cd23fc221
parent 20890 ec7fc110faee
child 20892 6fe95448596d
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.
mercurial/bundle2.py
tests/test-bundle2.t
--- 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]