Patchwork [4,of,6,V2] unbundle20: allow registering handlers for stream level parameters

login
register
mail settings
Submitter Pierre-Yves David
Date Sept. 25, 2015, 10:08 p.m.
Message ID <aade7f779b4347031996.1443218908@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/10648/
State Accepted
Headers show

Comments

Pierre-Yves David - Sept. 25, 2015, 10:08 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1443042016 25200
#      Wed Sep 23 14:00:16 2015 -0700
# Node ID aade7f779b43470319969ee00dc072e8e4fcbcc0
# Parent  a13c84d18821eb5c247a18c8c79ad49d0b79879b
unbundle20: allow registering handlers for stream level parameters

As a comment in the code have been asking for, it is now possible to register
piece of code that handle parameters for the stream. I've been wondering is such
function should be class methods or not. I eventually went for externally
decorated methods to stick with the culture of extensibility from an extensions
that apply to bundle2.

Patch

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -659,17 +659,19 @@  class unbundle20(unpackermixin):
         """
         if not name:
             raise ValueError('empty parameter name')
         if name[0] not in string.letters:
             raise ValueError('non letter first character: %r' % name)
-        # Some logic will be later added here to try to process the option for
-        # a dict of known parameter.
-        if name[0].islower():
-            indebug(self.ui, "ignoring unknown parameter %r" % name)
+        try:
+            handler = b2streamparamsmap[name.lower()]
+        except KeyError:
+            if name[0].islower():
+                indebug(self.ui, "ignoring unknown parameter %r" % name)
+            else:
+                raise error.BundleUnknownFeatureError(params=(name,))
         else:
-            raise error.BundleUnknownFeatureError(params=(name,))
-
+            handler(self, name, value)
 
     def iterparts(self):
         """yield all parts contained in the stream"""
         # make sure param have been loaded
         self.params
@@ -698,10 +700,20 @@  class unbundle20(unpackermixin):
     def compressed(self):
         return False
 
 formatmap = {'20': unbundle20}
 
+b2streamparamsmap = {}
+
+def b2streamparamhandler(name):
+    """register a handler for a stream level parameter"""
+    def decorator(func):
+        assert name not in formatmap
+        b2streamparamsmap[name] = func
+        return func
+    return decorator
+
 class bundlepart(object):
     """A bundle2 part contains application level payload
 
     The part `type` is used to route the part to the application level
     handler.