Mercurial > hg-stable
changeset 25481:6de96cb31176
bundle2: abort when a mandatory pushkey part fails
So far, result of a pushkey operation had no consequence on the transaction
(beside the change). We makes it respect the 'mandatory' flag of part so that
failed pushkey call abort the whole transaction. This will allow rejecting
changes (primary target: changesets) regarding phases or bookmark criteria in
the future (when we will push such data in a mandatory part).
We currently raise an abort error because all clients support it. We'll
introduce a more precise error in the next changesets.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Wed, 27 May 2015 05:28:40 -0700 |
parents | d410336fdb3c |
children | 95f490136e75 |
files | mercurial/bundle2.py tests/test-bundle2-exchange.t |
diffstat | 2 files changed, 145 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/bundle2.py Wed May 27 05:35:00 2015 -0700 +++ b/mercurial/bundle2.py Wed May 27 05:28:40 2015 -0700 @@ -1329,6 +1329,9 @@ rpart = op.reply.newpart('reply:pushkey') rpart.addparam('in-reply-to', str(inpart.id), mandatory=False) rpart.addparam('return', '%i' % ret, mandatory=False) + if inpart.mandatory and not ret: + raise util.Abort(_('failed to update value for "%s/%s"') + % (namespace, key)) @parthandler('reply:pushkey', ('return', 'in-reply-to')) def handlepushkeyreply(op, inpart):
--- a/tests/test-bundle2-exchange.t Wed May 27 05:35:00 2015 -0700 +++ b/tests/test-bundle2-exchange.t Wed May 27 05:28:40 2015 -0700 @@ -717,3 +717,145 @@ remote: rollback completed abort: pretxnchangegroup hook exited with status 1 [255] + +Check abort from mandatory pushkey + + $ cat > mandatorypart.py << EOF + > from mercurial import exchange + > from mercurial import pushkey + > from mercurial import node + > @exchange.b2partsgenerator('failingpuskey') + > def addfailingpushey(pushop, bundler): + > enc = pushkey.encode + > part = bundler.newpart('pushkey') + > part.addparam('namespace', enc('phases')) + > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex())) + > part.addparam('old', enc(str(0))) # successful update + > part.addparam('new', enc(str(0))) + > EOF + $ cat >> $HGRCPATH << EOF + > [hooks] + > pretxnchangegroup= + > pretxnclose.failpush= + > prepushkey.failpush = sh -c "echo 'do not push the key !'; false" + > [extensions] + > mandatorypart=$TESTTMP/mandatorypart.py + > EOF + $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config + $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log + $ cat other.pid >> $DAEMON_PIDS + +(Failure from a hook) + + $ hg -R main push other -r e7ec4e813ba6 + pushing to other + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + do not push the key ! + pushkey-abort: prepushkey.failpush hook exited with status 1 + transaction abort! + Cleaning up the mess... + rollback completed + abort: failed to update value for "phases/cd010b8cd998f3981a5a8115f94f8da4ab506089" + [255] + $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 + pushing to ssh://user@dummy/other + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + remote: do not push the key ! + remote: pushkey-abort: prepushkey.failpush hook exited with status 1 + remote: transaction abort! + remote: Cleaning up the mess... + remote: rollback completed + abort: failed to update value for "phases/cd010b8cd998f3981a5a8115f94f8da4ab506089" + [255] + $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 + pushing to http://localhost:$HGPORT2/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + remote: do not push the key ! + remote: pushkey-abort: prepushkey.failpush hook exited with status 1 + remote: transaction abort! + remote: Cleaning up the mess... + remote: rollback completed + abort: failed to update value for "phases/cd010b8cd998f3981a5a8115f94f8da4ab506089" + [255] + +(Failure from a the pushkey) + + $ cat > mandatorypart.py << EOF + > from mercurial import exchange + > from mercurial import pushkey + > from mercurial import node + > @exchange.b2partsgenerator('failingpuskey') + > def addfailingpushey(pushop, bundler): + > enc = pushkey.encode + > part = bundler.newpart('pushkey') + > part.addparam('namespace', enc('phases')) + > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex())) + > part.addparam('old', enc(str(4))) # will fail + > part.addparam('new', enc(str(3))) + > EOF + $ cat >> $HGRCPATH << EOF + > [hooks] + > prepushkey.failpush = + > EOF + $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config + $ hg -R other serve -p $HGPORT2 -d --pid-file=other.pid -E other-error.log + $ cat other.pid >> $DAEMON_PIDS + + $ hg -R main push other -r e7ec4e813ba6 + pushing to other + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + transaction abort! + Cleaning up the mess... + rollback completed + pushkey: lock state after "phases" + lock: free + wlock: free + abort: failed to update value for "phases/cd010b8cd998f3981a5a8115f94f8da4ab506089" + [255] + $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6 + pushing to ssh://user@dummy/other + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + remote: transaction abort! + remote: Cleaning up the mess... + remote: rollback completed + remote: pushkey: lock state after "phases" + remote: lock: free + remote: wlock: free + abort: failed to update value for "phases/cd010b8cd998f3981a5a8115f94f8da4ab506089" + [255] + $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6 + pushing to http://localhost:$HGPORT2/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + remote: transaction abort! + remote: Cleaning up the mess... + remote: rollback completed + remote: pushkey: lock state after "phases" + remote: lock: free + remote: wlock: free + abort: failed to update value for "phases/cd010b8cd998f3981a5a8115f94f8da4ab506089" + [255] +