--- a/tests/test-hook Thu Aug 12 19:10:57 2010 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-#!/bin/sh
-
-cp "$TESTDIR"/printenv.py .
-
-# commit hooks can see env vars
-hg init a
-cd a
-echo "[hooks]" > .hg/hgrc
-echo 'commit = unset HG_LOCAL HG_TAG; python ../printenv.py commit' >> .hg/hgrc
-echo 'commit.b = unset HG_LOCAL HG_TAG; python ../printenv.py commit.b' >> .hg/hgrc
-echo 'precommit = unset HG_LOCAL HG_NODE HG_TAG; python ../printenv.py precommit' >> .hg/hgrc
-echo 'pretxncommit = unset HG_LOCAL HG_TAG; python ../printenv.py pretxncommit' >> .hg/hgrc
-echo 'pretxncommit.tip = hg -q tip' >> .hg/hgrc
-echo 'pre-identify = python ../printenv.py pre-identify 1' >> .hg/hgrc
-echo 'pre-cat = python ../printenv.py pre-cat' >> .hg/hgrc
-echo 'post-cat = python ../printenv.py post-cat' >> .hg/hgrc
-echo a > a
-hg add a
-hg commit -m a -d "1000000 0"
-
-hg clone . ../b
-cd ../b
-
-# changegroup hooks can see env vars
-echo '[hooks]' > .hg/hgrc
-echo 'prechangegroup = python ../printenv.py prechangegroup' >> .hg/hgrc
-echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc
-echo 'incoming = python ../printenv.py incoming' >> .hg/hgrc
-
-# pretxncommit and commit hooks can see both parents of merge
-cd ../a
-echo b >> a
-hg commit -m a1 -d "1 0"
-hg update -C 0
-echo b > b
-hg add b
-hg commit -m b -d '1 0'
-hg merge 1
-hg commit -m merge -d '2 0'
-
-# test generic hooks
-hg id
-hg cat b
-
-cd ../b
-hg pull ../a
-
-# tag hooks can see env vars
-cd ../a
-echo 'pretag = python ../printenv.py pretag' >> .hg/hgrc
-echo 'tag = unset HG_PARENT1 HG_PARENT2; python ../printenv.py tag' >> .hg/hgrc
-hg tag -d '3 0' a
-hg tag -l la
-
-# pretag hook can forbid tagging
-echo 'pretag.forbid = python ../printenv.py pretag.forbid 1' >> .hg/hgrc
-hg tag -d '4 0' fa
-hg tag -l fla
-
-# pretxncommit hook can see changeset, can roll back txn, changeset
-# no more there after
-echo 'pretxncommit.forbid0 = hg tip -q' >> .hg/hgrc
-echo 'pretxncommit.forbid1 = python ../printenv.py pretxncommit.forbid 1' >> .hg/hgrc
-echo z > z
-hg add z
-hg -q tip
-hg commit -m 'fail' -d '4 0'
-hg -q tip
-
-# precommit hook can prevent commit
-echo 'precommit.forbid = python ../printenv.py precommit.forbid 1' >> .hg/hgrc
-hg commit -m 'fail' -d '4 0'
-hg -q tip
-
-# preupdate hook can prevent update
-echo 'preupdate = python ../printenv.py preupdate' >> .hg/hgrc
-hg update 1
-
-# update hook
-echo 'update = python ../printenv.py update' >> .hg/hgrc
-hg update
-
-# prechangegroup hook can prevent incoming changes
-cd ../b
-hg -q tip
-echo '[hooks]' > .hg/hgrc
-echo 'prechangegroup.forbid = python ../printenv.py prechangegroup.forbid 1' >> .hg/hgrc
-hg pull ../a
-
-# pretxnchangegroup hook can see incoming changes, can roll back txn,
-# incoming changes no longer there after
-echo '[hooks]' > .hg/hgrc
-echo 'pretxnchangegroup.forbid0 = hg tip -q' >> .hg/hgrc
-echo 'pretxnchangegroup.forbid1 = python ../printenv.py pretxnchangegroup.forbid 1' >> .hg/hgrc
-hg pull ../a
-hg -q tip
-
-# outgoing hooks can see env vars
-rm .hg/hgrc
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing = python ../printenv.py preoutgoing' >> ../a/.hg/hgrc
-echo 'outgoing = python ../printenv.py outgoing' >> ../a/.hg/hgrc
-hg pull ../a
-hg rollback
-
-# preoutgoing hook can prevent outgoing changes
-echo 'preoutgoing.forbid = python ../printenv.py preoutgoing.forbid 1' >> ../a/.hg/hgrc
-hg pull ../a
-
-# outgoing hooks work for local clones
-cd ..
-echo '[hooks]' > a/.hg/hgrc
-echo 'preoutgoing = python ../printenv.py preoutgoing' >> a/.hg/hgrc
-echo 'outgoing = python ../printenv.py outgoing' >> a/.hg/hgrc
-hg clone a c
-rm -rf c
-
-# preoutgoing hook can prevent outgoing changes for local clones
-echo 'preoutgoing.forbid = python ../printenv.py preoutgoing.forbid 1' >> a/.hg/hgrc
-hg clone a zzz
-cd b
-
-cat > hooktests.py <<EOF
-from mercurial import util
-
-uncallable = 0
-
-def printargs(args):
- args.pop('ui', None)
- args.pop('repo', None)
- a = list(args.items())
- a.sort()
- print 'hook args:'
- for k, v in a:
- print ' ', k, v
-
-def passhook(**args):
- printargs(args)
-
-def failhook(**args):
- printargs(args)
- return True
-
-class LocalException(Exception):
- pass
-
-def raisehook(**args):
- raise LocalException('exception from hook')
-
-def aborthook(**args):
- raise util.Abort('raise abort from hook')
-
-def brokenhook(**args):
- return 1 + {}
-
-class container:
- unreachable = 1
-EOF
-
-echo '# test python hooks'
-PYTHONPATH="`pwd`:$PYTHONPATH"
-export PYTHONPATH
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
-hg pull ../a 2>&1 | grep 'raised an exception'
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
-hg pull ../a 2>&1 | grep 'raised an exception'
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '[hooks]' > ../a/.hg/hgrc
-echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
-hg pull ../a
-
-echo '# make sure --traceback works'
-echo '[hooks]' > .hg/hgrc
-echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
-
-echo aa > a
-hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback'
-
-cd ..
-hg init c
-cd c
-
-cat > hookext.py <<EOF
-def autohook(**args):
- print "Automatically installed hook"
-
-def reposetup(ui, repo):
- repo.ui.setconfig("hooks", "commit.auto", autohook)
-EOF
-echo '[extensions]' >> .hg/hgrc
-echo 'hookext = hookext.py' >> .hg/hgrc
-
-touch foo
-hg add foo
-hg ci -d '0 0' -m 'add foo'
-echo >> foo
-hg ci --debug -d '0 0' -m 'change foo' | sed -e 's/ at .*>/>/'
-
-hg showconfig hooks | sed -e 's/ at .*>/>/'
-
-echo '# test python hook configured with python:[file]:[hook] syntax'
-cd ..
-mkdir d
-cd d
-hg init repo
-mkdir hooks
-
-cd hooks
-cat > testhooks.py <<EOF
-def testhook(**args):
- print 'hook works'
-EOF
-echo '[hooks]' > ../repo/.hg/hgrc
-echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
-
-cd ../repo
-hg commit -d '0 0'
-
-cd ../../b
-echo '# make sure --traceback works on hook import failure'
-cat > importfail.py <<EOF
-import somebogusmodule
-# dereference something in the module to force demandimport to load it
-somebogusmodule.whatever
-EOF
-
-echo '[hooks]' > .hg/hgrc
-echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc
-
-echo a >> a
-hg --traceback commit -d '0 0' -ma 2>&1 | egrep '^(exception|Traceback|ImportError)'
-
-echo '# commit and update hooks should run after command completion (issue 1827)'
-echo '[hooks]' > .hg/hgrc
-echo 'commit = hg id' >> .hg/hgrc
-echo 'update = hg id' >> .hg/hgrc
-echo bb > a
-hg ci -d '0 0' -ma
-hg up 0
-
-exit 0
--- a/tests/test-hook.out Thu Aug 12 19:10:57 2010 +0900
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
-pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$HGTMP/test-hook/a
-0:29b62aeb769f
-commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
-commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
-updating to branch default
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
-pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a
-1:b702efe96888
-commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
-commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
-pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook/a
-2:1324a5531bac
-commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
-commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
-created new head
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-(branch merge, don't forget to commit)
-precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
-pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=$HGTMP/test-hook/a
-3:4c52fb2e4022
-commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
-commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
-pre-identify hook: HG_ARGS=id HG_OPTS={'tags': None, 'rev': '', 'num': None, 'branch': None, 'id': None} HG_PATS=[]
-warning: pre-identify hook exited with status 1
-pre-cat hook: HG_ARGS=cat b HG_OPTS={'rev': '', 'decode': None, 'exclude': [], 'output': '', 'include': []} HG_PATS=['b']
-post-cat hook: HG_ARGS=cat b HG_OPTS={'rev': '', 'decode': None, 'exclude': [], 'output': '', 'include': []} HG_PATS=['b'] HG_RESULT=0
-b
-prechangegroup hook: HG_SOURCE=pull HG_URL=file:
-changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
-incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
-incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
-incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
-pulling from ../a
-searching for changes
-adding changesets
-adding manifests
-adding file changes
-added 3 changesets with 2 changes to 2 files
-(run 'hg update' to get a working copy)
-pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
-precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
-pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=$HGTMP/test-hook/a
-4:8ea2ef7ad3e8
-commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
-commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
-tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
-pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
-tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
-pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
-pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
-abort: pretag.forbid hook exited with status 1
-pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
-pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
-abort: pretag.forbid hook exited with status 1
-4:8ea2ef7ad3e8
-precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
-pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a
-5:fad284daf8c0
-5:fad284daf8c0
-pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/a
-transaction abort!
-rollback completed
-abort: pretxncommit.forbid1 hook exited with status 1
-4:8ea2ef7ad3e8
-precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
-precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
-abort: precommit.forbid hook exited with status 1
-4:8ea2ef7ad3e8
-preupdate hook: HG_PARENT1=b702efe96888
-0 files updated, 0 files merged, 2 files removed, 0 files unresolved
-preupdate hook: HG_PARENT1=8ea2ef7ad3e8
-update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
-2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-3:4c52fb2e4022
-prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
-pulling from ../a
-searching for changes
-abort: prechangegroup.forbid hook exited with status 1
-4:8ea2ef7ad3e8
-pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook/b HG_SOURCE=pull HG_URL=file:
-pulling from ../a
-searching for changes
-adding changesets
-adding manifests
-adding file changes
-added 1 changesets with 1 changes to 1 files
-transaction abort!
-rollback completed
-abort: pretxnchangegroup.forbid1 hook exited with status 1
-3:4c52fb2e4022
-preoutgoing hook: HG_SOURCE=pull
-outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
-pulling from ../a
-searching for changes
-adding changesets
-adding manifests
-adding file changes
-added 1 changesets with 1 changes to 1 files
-(run 'hg update' to get a working copy)
-rolling back to revision 3 (undo pull)
-preoutgoing hook: HG_SOURCE=pull
-preoutgoing.forbid hook: HG_SOURCE=pull
-pulling from ../a
-searching for changes
-abort: preoutgoing.forbid hook exited with status 1
-preoutgoing hook: HG_SOURCE=clone
-outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
-updating to branch default
-3 files updated, 0 files merged, 0 files removed, 0 files unresolved
-preoutgoing hook: HG_SOURCE=clone
-preoutgoing.forbid hook: HG_SOURCE=clone
-abort: preoutgoing.forbid hook exited with status 1
-# test python hooks
-error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
-error: preoutgoing.raise hook raised an exception: exception from hook
-pulling from ../a
-searching for changes
-error: preoutgoing.abort hook failed: raise abort from hook
-abort: raise abort from hook
-pulling from ../a
-searching for changes
-hook args:
- hooktype preoutgoing
- source pull
-abort: preoutgoing.fail hook failed
-pulling from ../a
-searching for changes
-abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
-pulling from ../a
-searching for changes
-abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
-pulling from ../a
-searching for changes
-abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
-pulling from ../a
-searching for changes
-abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
-pulling from ../a
-searching for changes
-abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
-pulling from ../a
-searching for changes
-hook args:
- hooktype preoutgoing
- source pull
-adding changesets
-adding manifests
-adding file changes
-added 1 changesets with 1 changes to 1 files
-(run 'hg update' to get a working copy)
-# make sure --traceback works
-Traceback (most recent call last):
-Automatically installed hook
-foo
-calling hook commit.auto: <function autohook>
-Automatically installed hook
-committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
-hooks.commit.auto=<function autohook>
-# test python hook configured with python:[file]:[hook] syntax
-hook works
-nothing changed
-# make sure --traceback works on hook import failure
-exception from first failed import attempt:
-Traceback (most recent call last):
-ImportError: No module named somebogusmodule
-exception from second failed import attempt:
-Traceback (most recent call last):
-ImportError: No module named hgext_importfail
-Traceback (most recent call last):
-# commit and update hooks should run after command completion (issue 1827)
-8da618c33484 tip
-29b62aeb769f
-1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hook.t Thu Aug 12 19:38:31 2010 +0900
@@ -0,0 +1,465 @@
+ $ cp "$TESTDIR"/printenv.py .
+
+# commit hooks can see env vars
+
+ $ hg init a
+ $ cd a
+ $ echo "[hooks]" > .hg/hgrc
+ $ echo 'commit = unset HG_LOCAL HG_TAG; python ../printenv.py commit' >> .hg/hgrc
+ $ echo 'commit.b = unset HG_LOCAL HG_TAG; python ../printenv.py commit.b' >> .hg/hgrc
+ $ echo 'precommit = unset HG_LOCAL HG_NODE HG_TAG; python ../printenv.py precommit' >> .hg/hgrc
+ $ echo 'pretxncommit = unset HG_LOCAL HG_TAG; python ../printenv.py pretxncommit' >> .hg/hgrc
+ $ echo 'pretxncommit.tip = hg -q tip' >> .hg/hgrc
+ $ echo 'pre-identify = python ../printenv.py pre-identify 1' >> .hg/hgrc
+ $ echo 'pre-cat = python ../printenv.py pre-cat' >> .hg/hgrc
+ $ echo 'post-cat = python ../printenv.py post-cat' >> .hg/hgrc
+ $ echo a > a
+ $ hg add a
+ $ hg commit -m a -d "1000000 0"
+ precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
+ pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$HGTMP/test-hook.t/a
+ 0:29b62aeb769f
+ commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
+ commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
+
+ $ hg clone . ../b
+ updating to branch default
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cd ../b
+
+# changegroup hooks can see env vars
+
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo 'prechangegroup = python ../printenv.py prechangegroup' >> .hg/hgrc
+ $ echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc
+ $ echo 'incoming = python ../printenv.py incoming' >> .hg/hgrc
+
+# pretxncommit and commit hooks can see both parents of merge
+
+ $ cd ../a
+ $ echo b >> a
+ $ hg commit -m a1 -d "1 0"
+ precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
+ pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook.t/a
+ 1:b702efe96888
+ commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
+ commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
+ $ hg update -C 0
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo b > b
+ $ hg add b
+ $ hg commit -m b -d '1 0'
+ precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
+ pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PENDING=$HGTMP/test-hook.t/a
+ 2:1324a5531bac
+ commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
+ commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
+ created new head
+ $ hg merge 1
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+ $ hg commit -m merge -d '2 0'
+ precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
+ pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PENDING=$HGTMP/test-hook.t/a
+ 3:4c52fb2e4022
+ commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
+ commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
+
+# test generic hooks
+
+ $ hg id
+ pre-identify hook: HG_ARGS=id HG_OPTS={'tags': None, 'rev': '', 'num': None, 'branch': None, 'id': None} HG_PATS=[]
+ warning: pre-identify hook exited with status 1
+ $ hg cat b
+ pre-cat hook: HG_ARGS=cat b HG_OPTS={'rev': '', 'decode': None, 'exclude': [], 'output': '', 'include': []} HG_PATS=['b']
+ post-cat hook: HG_ARGS=cat b HG_OPTS={'rev': '', 'decode': None, 'exclude': [], 'output': '', 'include': []} HG_PATS=['b'] HG_RESULT=0
+ b
+
+ $ cd ../b
+ $ hg pull ../a
+ prechangegroup hook: HG_SOURCE=pull HG_URL=file:
+ changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
+ incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
+ incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
+ incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
+ pulling from ../a
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 2 changes to 2 files
+ (run 'hg update' to get a working copy)
+
+# tag hooks can see env vars
+
+ $ cd ../a
+ $ echo 'pretag = python ../printenv.py pretag' >> .hg/hgrc
+ $ echo 'tag = unset HG_PARENT1 HG_PARENT2; python ../printenv.py tag' >> .hg/hgrc
+ $ hg tag -d '3 0' a
+ pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
+ precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
+ pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321 HG_PENDING=$HGTMP/test-hook.t/a
+ 4:8ea2ef7ad3e8
+ commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
+ commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
+ tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
+ $ hg tag -l la
+ pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
+ tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
+
+# pretag hook can forbid tagging
+
+ $ echo 'pretag.forbid = python ../printenv.py pretag.forbid 1' >> .hg/hgrc
+ $ hg tag -d '4 0' fa
+ pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
+ pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
+ abort: pretag.forbid hook exited with status 1
+ $ hg tag -l fla
+ pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
+ pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
+ abort: pretag.forbid hook exited with status 1
+
+# pretxncommit hook can see changeset, can roll back txn, changeset
+# no more there after
+
+ $ echo 'pretxncommit.forbid0 = hg tip -q' >> .hg/hgrc
+ $ echo 'pretxncommit.forbid1 = python ../printenv.py pretxncommit.forbid 1' >> .hg/hgrc
+ $ echo z > z
+ $ hg add z
+ $ hg -q tip
+ 4:8ea2ef7ad3e8
+ $ hg commit -m 'fail' -d '4 0'
+ precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
+ pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook.t/a
+ 5:fad284daf8c0
+ 5:fad284daf8c0
+ pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook.t/a
+ transaction abort!
+ rollback completed
+ abort: pretxncommit.forbid1 hook exited with status 1
+ $ hg -q tip
+ 4:8ea2ef7ad3e8
+
+# precommit hook can prevent commit
+
+ $ echo 'precommit.forbid = python ../printenv.py precommit.forbid 1' >> .hg/hgrc
+ $ hg commit -m 'fail' -d '4 0'
+ precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
+ precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
+ abort: precommit.forbid hook exited with status 1
+ $ hg -q tip
+ 4:8ea2ef7ad3e8
+
+# preupdate hook can prevent update
+
+ $ echo 'preupdate = python ../printenv.py preupdate' >> .hg/hgrc
+ $ hg update 1
+ preupdate hook: HG_PARENT1=b702efe96888
+ 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+
+# update hook
+
+ $ echo 'update = python ../printenv.py update' >> .hg/hgrc
+ $ hg update
+ preupdate hook: HG_PARENT1=8ea2ef7ad3e8
+ update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+# prechangegroup hook can prevent incoming changes
+
+ $ cd ../b
+ $ hg -q tip
+ 3:4c52fb2e4022
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo 'prechangegroup.forbid = python ../printenv.py prechangegroup.forbid 1' >> .hg/hgrc
+ $ hg pull ../a
+ prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
+ pulling from ../a
+ searching for changes
+ abort: prechangegroup.forbid hook exited with status 1
+
+# pretxnchangegroup hook can see incoming changes, can roll back txn,
+# incoming changes no longer there after
+
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo 'pretxnchangegroup.forbid0 = hg tip -q' >> .hg/hgrc
+ $ echo 'pretxnchangegroup.forbid1 = python ../printenv.py pretxnchangegroup.forbid 1' >> .hg/hgrc
+ $ hg pull ../a
+ 4:8ea2ef7ad3e8
+ pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PENDING=$HGTMP/test-hook.t/b HG_SOURCE=pull HG_URL=file:
+ pulling from ../a
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+ transaction abort!
+ rollback completed
+ abort: pretxnchangegroup.forbid1 hook exited with status 1
+ $ hg -q tip
+ 3:4c52fb2e4022
+
+# outgoing hooks can see env vars
+
+ $ rm .hg/hgrc
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing = python ../printenv.py preoutgoing' >> ../a/.hg/hgrc
+ $ echo 'outgoing = python ../printenv.py outgoing' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ preoutgoing hook: HG_SOURCE=pull
+ outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
+ pulling from ../a
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+ (run 'hg update' to get a working copy)
+ $ hg rollback
+ rolling back to revision 3 (undo pull)
+
+# preoutgoing hook can prevent outgoing changes
+
+ $ echo 'preoutgoing.forbid = python ../printenv.py preoutgoing.forbid 1' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ preoutgoing hook: HG_SOURCE=pull
+ preoutgoing.forbid hook: HG_SOURCE=pull
+ pulling from ../a
+ searching for changes
+ abort: preoutgoing.forbid hook exited with status 1
+
+# outgoing hooks work for local clones
+
+ $ cd ..
+ $ echo '[hooks]' > a/.hg/hgrc
+ $ echo 'preoutgoing = python ../printenv.py preoutgoing' >> a/.hg/hgrc
+ $ echo 'outgoing = python ../printenv.py outgoing' >> a/.hg/hgrc
+ $ hg clone a c
+ preoutgoing hook: HG_SOURCE=clone
+ outgoing hook: HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
+ updating to branch default
+ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ rm -rf c
+
+# preoutgoing hook can prevent outgoing changes for local clones
+
+ $ echo 'preoutgoing.forbid = python ../printenv.py preoutgoing.forbid 1' >> a/.hg/hgrc
+ $ hg clone a zzz
+ preoutgoing hook: HG_SOURCE=clone
+ preoutgoing.forbid hook: HG_SOURCE=clone
+ abort: preoutgoing.forbid hook exited with status 1
+ $ cd b
+
+ $ cat > hooktests.py <<EOF
+ > from mercurial import util
+ >
+ > uncallable = 0
+ >
+ > def printargs(args):
+ > args.pop('ui', None)
+ > args.pop('repo', None)
+ > a = list(args.items())
+ > a.sort()
+ > print 'hook args:'
+ > for k, v in a:
+ > print ' ', k, v
+ >
+ > def passhook(**args):
+ > printargs(args)
+ >
+ > def failhook(**args):
+ > printargs(args)
+ > return True
+ >
+ > class LocalException(Exception):
+ > pass
+ >
+ > def raisehook(**args):
+ > raise LocalException('exception from hook')
+ >
+ > def aborthook(**args):
+ > raise util.Abort('raise abort from hook')
+ >
+ > def brokenhook(**args):
+ > return 1 + {}
+ >
+ > class container:
+ > unreachable = 1
+ > EOF
+
+# test python hooks
+
+ $ PYTHONPATH="`pwd`:$PYTHONPATH"
+ $ export PYTHONPATH
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
+ $ hg pull ../a 2>&1 | grep 'raised an exception'
+ error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
+ $ hg pull ../a 2>&1 | grep 'raised an exception'
+ error: preoutgoing.raise hook raised an exception: exception from hook
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ error: preoutgoing.abort hook failed: raise abort from hook
+ abort: raise abort from hook
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ hook args:
+ hooktype preoutgoing
+ source pull
+ abort: preoutgoing.fail hook failed
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
+
+ $ echo '[hooks]' > ../a/.hg/hgrc
+ $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
+ $ hg pull ../a
+ pulling from ../a
+ searching for changes
+ hook args:
+ hooktype preoutgoing
+ source pull
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+ (run 'hg update' to get a working copy)
+
+# make sure --traceback works
+
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
+
+ $ echo aa > a
+ $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback'
+ Traceback (most recent call last):
+
+ $ cd ..
+ $ hg init c
+ $ cd c
+
+ $ cat > hookext.py <<EOF
+ > def autohook(**args):
+ > print "Automatically installed hook"
+ >
+ > def reposetup(ui, repo):
+ > repo.ui.setconfig("hooks", "commit.auto", autohook)
+ > EOF
+ $ echo '[extensions]' >> .hg/hgrc
+ $ echo 'hookext = hookext.py' >> .hg/hgrc
+
+ $ touch foo
+ $ hg add foo
+ $ hg ci -d '0 0' -m 'add foo'
+ Automatically installed hook
+ $ echo >> foo
+ $ hg ci --debug -d '0 0' -m 'change foo' | sed -e 's/ at .*>/>/'
+ foo
+ calling hook commit.auto: <function autohook>
+ Automatically installed hook
+ committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
+
+ $ hg showconfig hooks | sed -e 's/ at .*>/>/'
+ hooks.commit.auto=<function autohook>
+
+# test python hook configured with python:[file]:[hook] syntax
+
+ $ cd ..
+ $ mkdir d
+ $ cd d
+ $ hg init repo
+ $ mkdir hooks
+
+ $ cd hooks
+ $ cat > testhooks.py <<EOF
+ > def testhook(**args):
+ > print 'hook works'
+ > EOF
+ $ echo '[hooks]' > ../repo/.hg/hgrc
+ $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
+
+ $ cd ../repo
+ $ hg commit -d '0 0'
+ hook works
+ nothing changed
+
+ $ cd ../../b
+
+# make sure --traceback works on hook import failure
+
+ $ cat > importfail.py <<EOF
+ > import somebogusmodule
+ > # dereference something in the module to force demandimport to load it
+ > somebogusmodule.whatever
+ > EOF
+
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc
+
+ $ echo a >> a
+ $ hg --traceback commit -d '0 0' -ma 2>&1 | egrep '^(exception|Traceback|ImportError)'
+ exception from first failed import attempt:
+ Traceback (most recent call last):
+ ImportError: No module named somebogusmodule
+ exception from second failed import attempt:
+ Traceback (most recent call last):
+ ImportError: No module named hgext_importfail
+ Traceback (most recent call last):
+
+# commit and update hooks should run after command completion (issue 1827)
+
+ $ echo '[hooks]' > .hg/hgrc
+ $ echo 'commit = hg id' >> .hg/hgrc
+ $ echo 'update = hg id' >> .hg/hgrc
+ $ echo bb > a
+ $ hg ci -d '0 0' -ma
+ 8da618c33484 tip
+ $ hg up 0
+ 29b62aeb769f
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+ $ exit 0