Patchwork [08,of,12,stable] bundle2: gracefully handle UnknownPartError during unbundle

login
register
mail settings
Submitter Pierre-Yves David
Date April 22, 2014, 8:10 p.m.
Message ID <db91dd50bd02279afe60.1398197452@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/4427/
State Accepted
Commit 4345274adc4b17c129ab1eeba427bba03b1dab29
Headers show

Comments

Pierre-Yves David - April 22, 2014, 8:10 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1398121323 25200
#      Mon Apr 21 16:02:03 2014 -0700
# Branch stable
# Node ID db91dd50bd02279afe60da8dd3a33b299ff517da
# Parent  6ab6a29964dbf3113ba85f1d8755610eb03e283f
bundle2: gracefully handle UnknownPartError during unbundle

Same as for Abort error, we catch the error, encode it into a bundle2 reply
(expected by the client) and stream this reply. The client processing of the
error will raise the exception again.

Patch

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -751,5 +751,11 @@  def handlereplycaps(op, inpart):
 def handlereplycaps(op, inpart):
     """Used to transmit abort error over the wire"""
     manargs = dict(inpart.mandatoryparams)
     advargs = dict(inpart.advisoryparams)
     raise util.Abort(manargs['message'], hint=advargs.get('hint'))
+
+@parthandler('b2x:error:unknownpart')
+def handlereplycaps(op, inpart):
+    """Used to transmit unknown part error over the wire"""
+    manargs = dict(inpart.mandatoryparams)
+    raise UnknownPartError(manargs['parttype'])
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -801,10 +801,16 @@  def unbundle(repo, proto, heads):
             return pushres(r)
 
         finally:
             fp.close()
             os.unlink(tempname)
+    except bundle2.UnknownPartError, exc:
+            bundler = bundle2.bundle20(repo.ui)
+            part = bundle2.bundlepart('B2X:ERROR:UNKNOWNPART',
+                                      [('parttype', str(exc))])
+            bundler.addpart(part)
+            return streamres(bundler.getchunks())
     except util.Abort, inst:
         # The old code we moved used sys.stderr directly.
         # We did not change it to minimise code change.
         # This need to be moved to something proper.
         # Feel free to do it.
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -906,10 +906,12 @@  Setting up
   >     extradata = orig(pushop, bundler)
   >     reason = pushop.ui.config('failpush', 'reason', None)
   >     part = None
   >     if reason == 'abort':
   >         part = bundle2.bundlepart('test:abort')
+  >     if reason == 'unknown':
+  >         part = bundle2.bundlepart('TEST:UNKNOWN')
   >     if part is not None:
   >         bundler.addpart(part)
   >     return extradata
   > 
   > @bundle2.parthandler("test:abort")
@@ -967,5 +969,29 @@  Doing the actual push: Abort error
   abort: Abandon ship!
   (don't panic)
   [255]
 
 
+Doing the actual push: unknown mandatory parts
+
+  $ cat << EOF >> $HGRCPATH
+  > [failpush]
+  > reason = unknown
+  > EOF
+
+  $ hg -R main push other -r e7ec4e813ba6
+  pushing to other
+  searching for changes
+  abort: missing support for 'test:unknown'
+  [255]
+
+  $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
+  pushing to ssh://user@dummy/other
+  searching for changes
+  abort: missing support for "'test:unknown'"
+  [255]
+
+  $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
+  pushing to http://localhost:$HGPORT2/
+  searching for changes
+  abort: missing support for "'test:unknown'"
+  [255]