Patchwork [2,of,5] bundle2: extract processing of part into its own function

login
register
mail settings
Submitter Pierre-Yves David
Date Oct. 15, 2014, 8:18 p.m.
Message ID <0cf98037ae41618dfd56.1413404308@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/6303/
State Accepted
Headers show

Comments

Pierre-Yves David - Oct. 15, 2014, 8:18 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1413279146 25200
#      Tue Oct 14 02:32:26 2014 -0700
# Node ID 0cf98037ae41618dfd569772fddc5a025e8e1cac
# Parent  b4a0127f86b795eca57e183bebb8d19442858f82
bundle2: extract processing of part into its own function

This is code movement only. This will be useful to have it separated for reuse
purposes. We plan to introduce a new feature to the bundle format that allow
inserting a part in the middle of another part payload. This will be useful to
transmit a exception raised during a part generation.

Patch

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -290,54 +290,12 @@  def processbundle(repo, unbundler, trans
     unbundler.params
     iterparts = unbundler.iterparts()
     part = None
     try:
         for part in iterparts:
-            parttype = part.type
-            # part key are matched lower case
-            key = parttype.lower()
-            try:
-                handler = parthandlermapping.get(key)
-                if handler is None:
-                    raise error.BundleValueError(parttype=key)
-                op.ui.debug('found a handler for part %r\n' % parttype)
-                unknownparams = part.mandatorykeys - handler.params
-                if unknownparams:
-                    unknownparams = list(unknownparams)
-                    unknownparams.sort()
-                    raise error.BundleValueError(parttype=key,
-                                                   params=unknownparams)
-            except error.BundleValueError, exc:
-                if key != parttype: # mandatory parts
-                    raise
-                op.ui.debug('ignoring unsupported advisory part %s\n' % exc)
-                # consuming the part
-                part.read()
-                continue
-
-
-            # handler is called outside the above try block so that we don't
-            # risk catching KeyErrors from anything other than the
-            # parthandlermapping lookup (any KeyError raised by handler()
-            # itself represents a defect of a different variety).
-            output = None
-            if op.reply is not None:
-                op.ui.pushbuffer(error=True)
-                output = ''
-            try:
-                handler(op, part)
-            finally:
-                if output is not None:
-                    output = op.ui.popbuffer()
-            if output:
-                outpart = op.reply.newpart('b2x:output', data=output)
-                outpart.addparam('in-reply-to', str(part.id), mandatory=False)
-            part.read()
+            _processpart(op, part)
     except Exception, exc:
-        if part is not None:
-            # consume the bundle content
-            part.read()
         for part in iterparts:
             # consume the bundle content
             part.read()
         # Small hack to let caller code distinguish exceptions from bundle2
         # processing fron the ones from bundle1 processing. This is mostly
@@ -346,10 +304,57 @@  def processbundle(repo, unbundler, trans
         # craziness in a future version.
         exc.duringunbundle2 = True
         raise
     return op
 
+def _processpart(op, part):
+    """process a single part from a bundle
+
+    The part is garanteed to have been fully consumed when the function exit
+    (even if an exception is raised)."""
+    try:
+        parttype = part.type
+        # part key are matched lower case
+        key = parttype.lower()
+        try:
+            handler = parthandlermapping.get(key)
+            if handler is None:
+                raise error.BundleValueError(parttype=key)
+            op.ui.debug('found a handler for part %r\n' % parttype)
+            unknownparams = part.mandatorykeys - handler.params
+            if unknownparams:
+                unknownparams = list(unknownparams)
+                unknownparams.sort()
+                raise error.BundleValueError(parttype=key,
+                                               params=unknownparams)
+        except error.BundleValueError, exc:
+            if key != parttype: # mandatory parts
+                raise
+            op.ui.debug('ignoring unsupported advisory part %s\n' % exc)
+            return # skip to part processing
+
+        # handler is called outside the above try block so that we don't
+        # risk catching KeyErrors from anything other than the
+        # parthandlermapping lookup (any KeyError raised by handler()
+        # itself represents a defect of a different variety).
+        output = None
+        if op.reply is not None:
+            op.ui.pushbuffer(error=True)
+            output = ''
+        try:
+            handler(op, part)
+        finally:
+            if output is not None:
+                output = op.ui.popbuffer()
+        if output:
+            outpart = op.reply.newpart('b2x:output', data=output)
+            outpart.addparam('in-reply-to', str(part.id), mandatory=False)
+    finally:
+        # consume the part content to not corrupt the stream.
+        part.read()
+
+
 def decodecaps(blob):
     """decode a bundle2 caps bytes blob into a dictionnary
 
     The blob is a list of capabilities (one per line)
     Capabilities may have values using a line of the form::