changeset 21186:9f3652e851f8 stable

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.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Mon, 21 Apr 2014 17:51:58 -0700
parents 5b3717e1a3ea
children bcfd44abad93
files mercurial/bundle2.py mercurial/localrepo.py mercurial/wireproto.py tests/test-bundle2.t
diffstat 4 files changed, 46 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/bundle2.py	Mon Apr 21 20:04:54 2014 -0700
+++ b/mercurial/bundle2.py	Mon Apr 21 17:51:58 2014 -0700
@@ -760,3 +760,9 @@
     """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'])
--- a/mercurial/localrepo.py	Mon Apr 21 20:04:54 2014 -0700
+++ b/mercurial/localrepo.py	Mon Apr 21 17:51:58 2014 -0700
@@ -134,7 +134,7 @@
                 ret = bundle2.unbundle20(self.ui, stream)
             return ret
         except error.PushRaced, exc:
-            raise error.ResponseError(_('push failed:'), exc.message)
+            raise error.ResponseError(_('push failed:'), str(exc))
 
     def lock(self):
         return self._repo.lock()
--- a/mercurial/wireproto.py	Mon Apr 21 20:04:54 2014 -0700
+++ b/mercurial/wireproto.py	Mon Apr 21 17:51:58 2014 -0700
@@ -827,4 +827,11 @@
             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))
--- a/tests/test-bundle2.t	Mon Apr 21 20:04:54 2014 -0700
+++ b/tests/test-bundle2.t	Mon Apr 21 17:51:58 2014 -0700
@@ -927,6 +927,9 @@
   >         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
@@ -1012,3 +1015,31 @@
   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]