Patchwork [11,of,12,stable] bundle2: gracefully handle PushRaced error during unbundle

login
register
mail settings
Submitter Pierre-Yves David
Date April 22, 2014, 8:10 p.m.
Message ID <fbf039ac0e2ea7cfcfdc.1398197455@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/4431/
State Accepted
Commit 9f3652e851f8c53f75358777ae89e0906bd835f3
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 1398127918 25200
#      Mon Apr 21 17:51:58 2014 -0700
# Branch stable
# Node ID fbf039ac0e2ea7cfcfdcd7c06b532c31cdaad60f
# Parent  58b0fd92f3e411f68dbf9c6e129d895df5336902
bundle2: gracefully handle PushRaced error during unbundle

Same drill again. We catch the PushRaced error, check if it cames from a bundle2
processing, if so we turn it into a bundle2 with a part transporting error
information to be reraised client side.

Patch

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -758,5 +758,11 @@  def handlereplycaps(op, inpart):
 @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'])
+
+@parthandler('b2x:error:pushraced')
+def handlereplycaps(op, inpart):
+    """Used to transmit push race error over the wire"""
+    manargs = dict(inpart.mandatoryparams)
+    raise error.ResponseError(_('push failed:'), manargs['message'])
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -825,6 +825,13 @@  def unbundle(repo, proto, heads):
             return streamres(bundler.getchunks())
         else:
             sys.stderr.write("abort: %s\n" % inst)
             return pushres(0)
     except error.PushRaced, exc:
-        return pusherr(str(exc))
+        if getattr(exc, 'duringunbundle2', False):
+            bundler = bundle2.bundle20(repo.ui)
+            part = bundle2.bundlepart('B2X:ERROR:PUSHRACED',
+                                      [('message', str(exc))])
+            bundler.addpart(part)
+            return streamres(bundler.getchunks())
+        else:
+            return pusherr(str(exc))
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -925,10 +925,13 @@  Setting up
   >     part = None
   >     if reason == 'abort':
   >         part = bundle2.bundlepart('test:abort')
   >     if reason == 'unknown':
   >         part = bundle2.bundlepart('TEST:UNKNOWN')
+  >     if reason == 'race':
+  >         # 20 Bytes of crap
+  >         part = bundle2.bundlepart('b2x:check:heads', data='01234567890123456789')
   >     if part is not None:
   >         bundler.addpart(part)
   >     return extradata
   > 
   > @bundle2.parthandler("test:abort")
@@ -1010,5 +1013,33 @@  Doing the actual push: unknown mandatory
   $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
   pushing to http://localhost:$HGPORT2/
   searching for changes
   abort: missing support for "'test:unknown'"
   [255]
+
+Doing the actual push: race
+
+  $ cat << EOF >> $HGRCPATH
+  > [failpush]
+  > reason = race
+  > EOF
+
+  $ hg -R main push other -r e7ec4e813ba6
+  pushing to other
+  searching for changes
+  abort: push failed:
+  'repository changed while pushing - please try again'
+  [255]
+
+  $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
+  pushing to ssh://user@dummy/other
+  searching for changes
+  abort: push failed:
+  'repository changed while pushing - please try again'
+  [255]
+
+  $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
+  pushing to http://localhost:$HGPORT2/
+  searching for changes
+  abort: push failed:
+  'repository changed while pushing - please try again'
+  [255]