#!/bin/sh
# commit hooks can see env vars
hg init a
cd a
echo "[hooks]" > .hg/hgrc
echo 'commit = echo commit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
echo 'commit.b = echo commit hook b' >> .hg/hgrc
echo 'precommit = echo precommit hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
echo 'pretxncommit = echo pretxncommit hook: n=$HG_NODE p1=$HG_PARENT1 p2=$HG_PARENT2; hg -q tip' >> .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 = echo prechangegroup hook: u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
echo 'changegroup = echo changegroup hook: n=$HG_NODE u=`echo $HG_URL | sed s,file:.*,file:,`' >> .hg/hgrc
echo 'incoming = echo incoming hook: n=$HG_NODE u=`echo $HG_URL | sed s,file:.*,file:,`' >> .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'
cd ../b
hg pull ../a
# tag hooks can see env vars
cd ../a
echo 'pretag = echo pretag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc
echo 'tag = echo tag hook: t=$HG_TAG n=$HG_NODE l=$HG_LOCAL' >> .hg/hgrc
hg tag -d '3 0' a
hg tag -l la
# pretag hook can forbid tagging
echo 'pretag.forbid = echo pretag.forbid hook; exit 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.forbid = echo pretxncommit.forbid hook: tip=`hg -q tip`; exit 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 = echo precommit.forbid hook; exit 1' >> .hg/hgrc
hg commit -m 'fail' -d '4 0'
hg -q tip
# preupdate hook can prevent update
echo 'preupdate = echo preupdate hook: p1=$HG_PARENT1 p2=$HG_PARENT2' >> .hg/hgrc
hg update 1
# update hook
echo 'update = echo update hook: p1=$HG_PARENT1 p2=$HG_PARENT2 err=$HG_ERROR' >> .hg/hgrc
hg update
# prechangegroup hook can prevent incoming changes
cd ../b
hg -q tip
echo '[hooks]' > .hg/hgrc
echo 'prechangegroup.forbid = echo prechangegroup.forbid hook; exit 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.forbid = echo pretxnchangegroup.forbid hook: tip=`hg -q tip`; exit 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 = echo preoutgoing hook: s=$HG_SOURCE' >> ../a/.hg/hgrc
echo 'outgoing = echo outgoing hook: n=$HG_NODE s=$HG_SOURCE' >> ../a/.hg/hgrc
hg pull ../a
hg rollback
# preoutgoing hook can prevent outgoing changes
echo 'preoutgoing.forbid = echo preoutgoing.forbid hook; exit 1' >> ../a/.hg/hgrc
hg pull ../a
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 a >> a
hg --traceback commit -A -m a 2>&1 | grep '^Traceback'
exit 0