Patchwork [4,of,7] push: rework the bundle2partsgenerators logic

login
register
mail settings
Submitter Pierre-Yves David
Date Aug. 4, 2014, 10:32 p.m.
Message ID <ef23af55a08a21a47925.1407191526@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/5252/
State Accepted
Headers show

Comments

Pierre-Yves David - Aug. 4, 2014, 10:32 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1406772290 25200
#      Wed Jul 30 19:04:50 2014 -0700
# Node ID ef23af55a08a21a479254a769dd0ccc94075be71
# Parent  757e2729b231c008ac4657d57f98a0eca6c4617b
push: rework the bundle2partsgenerators logic

Instead of a single list with function, we now have a list of name and a
mapping of name to function. This aims at easing wrapping of step from
extension. In the same move, declaration becomes decorator based (Syntax sugar,
nom nom nom!)

Patch

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -241,10 +241,35 @@  def _pushcheckoutgoing(pushop):
                              pushop.newbranch,
                              bool(pushop.incoming),
                              newbm)
     return True
 
+# List of name of steps to perform for an outgoing bundle2, order matters.
+b2partsgenorder = []
+
+# Mapping between step name and function
+#
+# This exists to help extension to wrap step if necessary
+b2partsgenmapping = {}
+
+def b2partsgenerator(stepname):
+    """decorator for function generating bundle2 part
+
+    The function is added to the step -> function mapping and append to the
+    list of steps.  Beware that decorated function will be added in order This
+    may matters.
+
+    You can only use this decorator for new step, if you want to wrap a step
+    from an extension, attack the b2partsgenmapping dictionnary directly."""
+    def dec(func):
+        assert stepname not in b2partsgenmapping
+        b2partsgenmapping[stepname] = func
+        b2partsgenorder.append(stepname)
+        return func
+    return dec
+
+@b2partsgenerator('changeset')
 def _pushb2ctx(pushop, bundler):
     """handle changegroup push through bundle2
 
     addchangegroup result is stored in the ``pushop.ret`` attribute.
     """
@@ -267,12 +292,10 @@  def _pushb2ctx(pushop, bundler):
         cgreplies = op.records.getreplies(cgpart.id)
         assert len(cgreplies['changegroup']) == 1
         pushop.ret = cgreplies['changegroup'][0]['return']
     return handlereply
 
-# list of function that may decide to add parts to an outgoing bundle2
-bundle2partsgenerators = [_pushb2ctx]
 
 def _pushbundle2(pushop):
     """push data to the remote using bundle2
 
     The only currently supported type of data is changegroup but this will
@@ -280,11 +303,12 @@  def _pushbundle2(pushop):
     bundler = bundle2.bundle20(pushop.ui, bundle2.bundle2caps(pushop.remote))
     # create reply capability
     capsblob = bundle2.encodecaps(pushop.repo.bundle2caps)
     bundler.newpart('b2x:replycaps', data=capsblob)
     replyhandlers = []
-    for partgen in bundle2partsgenerators:
+    for partgenname in b2partsgenorder:
+        partgen = b2partsgenmapping[partgenname]
         ret = partgen(pushop, bundler)
         if callable(ret):
             replyhandlers.append(ret)
     # do not push if nothing to push
     if bundler.nbparts <= 1:
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -962,11 +962,12 @@  Setting up
   > @bundle2.parthandler("test:abort")
   > def handleabort(op, part):
   >     raise util.Abort('Abandon ship!', hint="don't panic")
   > 
   > def uisetup(ui):
-  >     exchange.bundle2partsgenerators.insert(0, _pushbundle2failpart)
+  >     exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart
+  >     exchange.b2partsgenorder.insert(0, 'failpart')
   > 
   > EOF
 
   $ cd main
   $ hg up tip