Mercurial > hg-stable
changeset 26751:520defbc0335
hook: centralize passing HG_PENDING to external hook process
This patch centralizes passing HG_PENDING to external hook process
into '_exthook()'. To make in-memory changes visible to external hook
process, this patch does:
- write (or schedule to write) in-memory dirstate changes, and
- set HG_PENDING environment variable, if:
- a transaction is running, and
- there are in-memory changes to be visible
This patch tests some commands with some hooks, because transaction
activity of a same hook differs from each other ("---": "not tested").
======== ========= ========= ============
command preupdate precommit pretxncommit
======== ========= ========= ============
unshelve o --- ---
backout x --- ---
import --- o o
qrefresh --- x o
======== ========= ========= ============
Each hooks are examined separately to prevent in-memory changes from
being visible to external process accidentally by side effect of hooks
previously invoked.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Sat, 17 Oct 2015 01:15:34 +0900 |
parents | 9f9ec4abe700 |
children | 949e8c626d19 |
files | mercurial/changegroup.py mercurial/hook.py mercurial/localrepo.py tests/test-backout.t tests/test-import.t tests/test-mq-qrefresh-replace-log-message.t tests/test-shelve.t |
diffstat | 7 files changed, 328 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/changegroup.py Sat Oct 17 01:15:34 2015 +0900 +++ b/mercurial/changegroup.py Sat Oct 17 01:15:34 2015 +0900 @@ -407,15 +407,13 @@ repo.invalidatevolatilesets() if changesets > 0: - p = lambda: tr.writepending() and repo.root or "" if 'node' not in tr.hookargs: tr.hookargs['node'] = hex(cl.node(clstart)) hookargs = dict(tr.hookargs) else: hookargs = dict(tr.hookargs) hookargs['node'] = hex(cl.node(clstart)) - repo.hook('pretxnchangegroup', throw=True, pending=p, - **hookargs) + repo.hook('pretxnchangegroup', throw=True, **hookargs) added = [cl.node(r) for r in xrange(clstart, clend)] publishing = repo.publishing()
--- a/mercurial/hook.py Sat Oct 17 01:15:34 2015 +0900 +++ b/mercurial/hook.py Sat Oct 17 01:15:34 2015 +0900 @@ -118,6 +118,13 @@ starttime = time.time() env = {} + + # make in-memory changes visible to external process + tr = repo.currenttransaction() + repo.dirstate.write(tr) + if tr and tr.writepending(): + env['HG_PENDING'] = repo.root + for k, v in args.iteritems(): if callable(v): v = v()
--- a/mercurial/localrepo.py Sat Oct 17 01:15:34 2015 +0900 +++ b/mercurial/localrepo.py Sat Oct 17 01:15:34 2015 +0900 @@ -994,8 +994,7 @@ reporef = weakref.ref(self) def validate(tr): """will run pre-closing hooks""" - pending = lambda: tr.writepending() and self.root or "" - reporef().hook('pretxnclose', throw=True, pending=pending, + reporef().hook('pretxnclose', throw=True, txnname=desc, **tr.hookargs) def releasefn(tr, success): repo = reporef() @@ -1682,10 +1681,9 @@ n = self.changelog.add(mn, files, ctx.description(), trp, p1.node(), p2.node(), user, ctx.date(), ctx.extra().copy()) - p = lambda: tr.writepending() and self.root or "" xp1, xp2 = p1.hex(), p2 and p2.hex() or '' self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, - parent2=xp2, pending=p) + parent2=xp2) # set the new commit is proper phase targetphase = subrepo.newcommitphase(self.ui, ctx) if targetphase: @@ -1865,8 +1863,6 @@ hookargs = {} if tr is not None: hookargs.update(tr.hookargs) - pending = lambda: tr.writepending() and self.root or "" - hookargs['pending'] = pending hookargs['namespace'] = namespace hookargs['key'] = key hookargs['old'] = old
--- a/tests/test-backout.t Sat Oct 17 01:15:34 2015 +0900 +++ b/tests/test-backout.t Sat Oct 17 01:15:34 2015 +0900 @@ -259,6 +259,60 @@ line 2 line 3 +Test visibility of in-memory dirstate changes outside transaction to +external hook process + + $ cat > $TESTTMP/checkvisibility.sh <<EOF + > echo "==== \$1:" + > hg parents --template "{rev}:{node|short}\n" + > echo "====" + > EOF + +"hg backout --merge REV1" at REV2 below implies steps below: + +(1) update to REV1 (REV2 => REV1) +(2) revert by REV1^1 +(3) commit backnig out revision (REV3) +(4) update to REV2 (REV3 => REV2) +(5) merge with REV3 (REV2 => REV2, REV3) + +== test visibility to external preupdate hook + + $ hg update -q -C 2 + $ hg --config extensions.strip= strip 3 + saved backup bundle to * (glob) + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate + > EOF + +("-m" is needed to avoid writing dirstte changes out at other than +invocation of the hook to be examined) + + $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment' + ==== preupdate: + 2:6ea3f2a197a2 + ==== + reverting a + created new head + changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182 + ==== preupdate: + 3:d92a3f57f067 + ==== + merging with changeset 3:d92a3f57f067 + ==== preupdate: + 2:6ea3f2a197a2 + ==== + merging a + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > preupdate.visibility = + > EOF + $ cd .. backout should not back out subsequent changesets
--- a/tests/test-import.t Sat Oct 17 01:15:34 2015 +0900 +++ b/tests/test-import.t Sat Oct 17 01:15:34 2015 +0900 @@ -533,6 +533,110 @@ $ hg --cwd b revert --no-backup a $ rm -f b/foo +== test visibility to precommit external hook + + $ cat >> b/.hg/hgrc <<EOF + > [hooks] + > precommit.visibility = sh $TESTTMP/checkvisibility.sh + > EOF + + $ (cd b && sh "$TESTTMP/checkvisibility.sh") + ==== + VISIBLE 0:80971e65b431 + ACTUAL 0:80971e65b431 + ==== + + $ hg --cwd b import ../patch1 ../patch2 ../patch3 + applying ../patch1 + ==== + VISIBLE 0:80971e65b431 + M a + ACTUAL 0:80971e65b431 + M a + ==== + applying ../patch2 + ==== + VISIBLE 1:1d4bd90af0e4 + M a + ACTUAL 0:80971e65b431 + M a + ==== + applying ../patch3 + ==== + VISIBLE 2:6d019af21222 + A foo + ACTUAL 0:80971e65b431 + M a + ==== + + $ hg --cwd b rollback -q + $ (cd b && sh "$TESTTMP/checkvisibility.sh") + ==== + VISIBLE 0:80971e65b431 + M a + ACTUAL 0:80971e65b431 + M a + ==== + $ hg --cwd b revert --no-backup a + $ rm -f b/foo + + $ cat >> b/.hg/hgrc <<EOF + > [hooks] + > precommit.visibility = + > EOF + +== test visibility to pretxncommit external hook + + $ cat >> b/.hg/hgrc <<EOF + > [hooks] + > pretxncommit.visibility = sh $TESTTMP/checkvisibility.sh + > EOF + + $ (cd b && sh "$TESTTMP/checkvisibility.sh") + ==== + VISIBLE 0:80971e65b431 + ACTUAL 0:80971e65b431 + ==== + + $ hg --cwd b import ../patch1 ../patch2 ../patch3 + applying ../patch1 + ==== + VISIBLE 0:80971e65b431 + M a + ACTUAL 0:80971e65b431 + M a + ==== + applying ../patch2 + ==== + VISIBLE 1:1d4bd90af0e4 + M a + ACTUAL 0:80971e65b431 + M a + ==== + applying ../patch3 + ==== + VISIBLE 2:6d019af21222 + A foo + ACTUAL 0:80971e65b431 + M a + ==== + + $ hg --cwd b rollback -q + $ (cd b && sh "$TESTTMP/checkvisibility.sh") + ==== + VISIBLE 0:80971e65b431 + M a + ACTUAL 0:80971e65b431 + M a + ==== + $ hg --cwd b revert --no-backup a + $ rm -f b/foo + + $ cat >> b/.hg/hgrc <<EOF + > [hooks] + > pretxncommit.visibility = + > EOF + $ rm -r b
--- a/tests/test-mq-qrefresh-replace-log-message.t Sat Oct 17 01:15:34 2015 +0900 +++ b/tests/test-mq-qrefresh-replace-log-message.t Sat Oct 17 01:15:34 2015 +0900 @@ -242,3 +242,85 @@ ==== 0:25e397dabed2 ==== + +== test visibility to precommit external hook + + $ hg update -C -q + $ rm -f file2 + $ hg qpush -q second-patch --config hooks.pretxncommit.unexpectedabort= + now at: second-patch + $ echo bbbb >> file2 + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > precommit.checkvisibility = sh "$TESTTMP/checkvisibility.sh" + > EOF + + $ sh "$TESTTMP/checkvisibility.sh" + ==== + 1:e30108269082 + M file2 + ==== + + $ hg qrefresh + ==== + 0:25e397dabed2 + A file2 + ==== + transaction abort! + rollback completed + refresh interrupted while patch was popped! (revert --all, qpush to recover) + abort: pretxncommit.unexpectedabort hook exited with status 1 + [255] + + $ sh "$TESTTMP/checkvisibility.sh" + ==== + 0:25e397dabed2 + ==== + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > precommit.checkvisibility = + > EOF + +== test visibility to pretxncommit external hook + + $ hg update -C -q + $ rm -f file2 + $ hg qpush -q second-patch --config hooks.pretxncommit.unexpectedabort= + now at: second-patch + $ echo bbbb >> file2 + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > pretxncommit.checkvisibility = sh "$TESTTMP/checkvisibility.sh" + > # make checkvisibility run before unexpectedabort + > priority.pretxncommit.checkvisibility = 10 + > EOF + + $ sh "$TESTTMP/checkvisibility.sh" + ==== + 1:e30108269082 + M file2 + ==== + + $ hg qrefresh + ==== + 0:25e397dabed2 + A file2 + ==== + transaction abort! + rollback completed + refresh interrupted while patch was popped! (revert --all, qpush to recover) + abort: pretxncommit.unexpectedabort hook exited with status 1 + [255] + + $ sh "$TESTTMP/checkvisibility.sh" + ==== + 0:25e397dabed2 + ==== + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > pretxncommit.checkvisibility = + > EOF
--- a/tests/test-shelve.t Sat Oct 17 01:15:34 2015 +0900 +++ b/tests/test-shelve.t Sat Oct 17 01:15:34 2015 +0900 @@ -1011,6 +1011,84 @@ 7e30d8ac6f23cfc84330fd7e698730374615d21a $ cd .. +Test visibility of in-memory changes inside transaction to external hook +------------------------------------------------------------------------ + + $ cd repo + + $ echo xxxx >> x + $ hg commit -m "#5: changes to invoke rebase" + + $ cat > $TESTTMP/checkvisibility.sh <<EOF + > echo "==== \$1:" + > hg parents --template "VISIBLE {rev}:{node|short}\n" + > # test that pending changes are hidden + > unset HG_PENDING + > hg parents --template "ACTUAL {rev}:{node|short}\n" + > echo "====" + > EOF + + $ cat >> .hg/hgrc <<EOF + > [defaults] + > # to fix hash id of temporary revisions + > unshelve = --date '0 0' + > EOF + +"hg unshelve" at REV5 implies steps below: + +(1) commit changes in the working directory (REV6) +(2) unbundle shelved revision (REV7) +(3) rebase: merge REV7 into REV6 (REV6 => REV6, REV7) +(4) rebase: commit merged revision (REV8) +(5) rebase: update to REV6 (REV8 => REV6) +(6) update to REV5 (REV6 => REV5) +(7) abort transaction + +== test visibility to external preupdate hook + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate + > EOF + + $ echo nnnn >> n + + $ sh $TESTTMP/checkvisibility.sh before-unshelving + ==== before-unshelving: + VISIBLE 5:703117a2acfb + ACTUAL 5:703117a2acfb + ==== + + $ hg unshelve --keep default + temporarily committing pending changes (restore with 'hg unshelve --abort') + rebasing shelved changes + rebasing 7:fcbb97608399 "changes to 'create conflict'" (tip) + ==== preupdate: + VISIBLE 6:66b86db80ee4 + ACTUAL 5:703117a2acfb + ==== + ==== preupdate: + VISIBLE 8:cb2a4e59c2d5 + ACTUAL 5:703117a2acfb + ==== + ==== preupdate: + VISIBLE 6:66b86db80ee4 + ACTUAL 5:703117a2acfb + ==== + + $ cat >> .hg/hgrc <<EOF + > [hooks] + > preupdate.visibility = + > EOF + + $ sh $TESTTMP/checkvisibility.sh after-unshelving + ==== after-unshelving: + VISIBLE 5:703117a2acfb + ACTUAL 5:703117a2acfb + ==== + + $ cd .. + test Abort unshelve always gets user out of the unshelved state --------------------------------------------------------------- $ hg init salvage