Comments
Patch
@@ -741,5 +741,11 @@ def handlereplycaps(op, inpart):
The payload contains the capabilities information for the reply"""
caps = decodecaps(inpart.read())
if op.reply is None:
op.reply = bundle20(op.ui, caps)
+@parthandler('b2x:error:abort')
+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'))
@@ -806,9 +806,19 @@ def unbundle(repo, proto, heads):
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.
- sys.stderr.write("abort: %s\n" % inst)
- return pushres(0)
+ if getattr(inst, 'duringunbundle2', False):
+ bundler = bundle2.bundle20(repo.ui)
+ manargs = [('message', str(inst))]
+ advargs = []
+ if inst.hint is not None:
+ advargs.append(('hint', inst.hint))
+ bundler.addpart(bundle2.bundlepart('B2X:ERROR:ABORT',
+ manargs, advargs))
+ return streamres(bundler.getchunks())
+ else:
+ sys.stderr.write("abort: %s\n" % inst)
+ return pushres(0)
except exchange.PushRaced, exc:
return pusherr(str(exc))
@@ -881,5 +881,82 @@ Check final content.
o changeset: 0:cd010b8cd998
user: Nicolas Dumazet <nicdumz.commits@gmail.com>
date: Sat Apr 30 15:24:48 2011 +0200
summary: A
+
+Error Handling
+==============
+
+Checks that errors are properly returned to the client during push.
+
+Setting up
+
+ $ cat > failpush.py << EOF
+ > """A small extension that makes push fails when using bundle2
+ >
+ > used to test error handling in bundle2
+ > """
+ >
+ > from mercurial import util
+ > from mercurial import bundle2
+ > from mercurial import exchange
+ > from mercurial import extensions
+ >
+ > def _pushbundle2failpart(orig, pushop, bundler):
+ > extradata = orig(pushop, bundler)
+ > part = bundle2.bundlepart('test:abort')
+ > bundler.addpart(part)
+ > return extradata
+ >
+ > @bundle2.parthandler("test:abort")
+ > def handleabort(op, part):
+ > raise util.Abort('Abandon ship!', hint="don't panic")
+ >
+ > def uisetup(ui):
+ > extensions.wrapfunction(exchange, '_pushbundle2extraparts', _pushbundle2failpart)
+ >
+ > EOF
+
+ $ cd main
+ $ hg up tip
+ 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ echo 'I' > I
+ $ hg add I
+ $ hg ci -m 'I'
+ $ hg id
+ e7ec4e813ba6 tip
+ $ cd ..
+
+ $ cat << EOF >> $HGRCPATH
+ > [extensions]
+ > failpush=$TESTTMP/failpush.py
+ > EOF
+
+ $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
+ $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
+ $ cat other.pid >> $DAEMON_PIDS
+
+Doing the actual push: Abort error
+
+ $ hg -R main push other -r e7ec4e813ba6
+ pushing to other
+ searching for changes
+ abort: Abandon ship!
+ (don't panic)
+ [255]
+
+ $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
+ pushing to ssh://user@dummy/other
+ searching for changes
+ abort: Abandon ship!
+ (don't panic)
+ [255]
+
+ $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
+ pushing to http://localhost:$HGPORT2/
+ searching for changes
+ abort: Abandon ship!
+ (don't panic)
+ [255]
+
+