I need to setup a hook on a repository where people can push, that would run some validation (the goal is to reject the push if validation fails). I already have some hooks setup to auto-update after a successful push, and prevent multiple heads.
I have no problem writing a validation script (for example a shell script that runs unit tests), but it needs to run on the full working copy.
My problem is that, if I just put it in a pretxnchangegroup hook, it does not operate on updated files. If I try to hg update inside the hook, this leads to repository corruption whenever validation fails and the push is rollbacked.
My current solution is to clone the repository to some temporary folder and run the actual validation there. But I find this a bit ugly, and it is less efficient that an in-place validation doing just updates. Is this kind of hook possible to setup ?
There are ways to do this, but before I start, are you sure you want to do this? Doing blocking, maybe-slow, push-rejecting changes in a hook annoys the hell out of people, and it holds the repository writelock the whole time, so no one else can be pushing while the validation script is running. One can pretty easy toss half the productivity advantages of a DVCS out the window in an attempt to gain a little control.
You could avoid most of those disadvantages with a two-tier repository setup. Something like project-push
where people can push w/o passing validation and project-pull
that only has changesets which passed some validation. Then you have an out-of-band (cron or hook triggered) script that moves changesets from project-push
to project-pull
only after validation is confirmed. Because that test is done out of band pushes aren't blocked but non-validating changesets never make it into project-pull
. You can have it email the author when their push threw project-pull
into a non-validating state. Users with their .hg/hgrc
configured like this wouldn't have to think about their being two repositories at all:
[paths]
default=http://host//path/to/project-pull
default-push=http://host//path/to/project-push
They could just use hg push
and hg pull
and things would "just work".
That said if your validation doesn't need access to all the updated files at the same time you can do your test with something like this in an external pretxnchangegroup
hook:
for thefile in $(hg manifest -r tip) ; do
if ! hg cat -r tip $thefile | ./validate_on_file.sh ; then
exit
fi
done
If you do need to operate on all the files at once (compiling, etc.) and you're not willing to do a two-repo structure that frees people to push quickly, then you do need a separate repo for testing, but you don't have to clone/create it each time. Something like this in a pretxnchangegroup
hook should do:
hg push /scratch/long-lived-testrepo ## Warning: may not work,
## if pretxnchangegroup locks the repo and
## blocks this push to testrepo
hg -R /scratch/long-lived-testrepo update
cd /scratch/long-lived-testrepo
./validation.sh
来源:https://stackoverflow.com/questions/9308658/mercurial-pre-push-hook-scanning-the-working-copy