Mercurial pre-push hook scanning the working copy

南楼画角 提交于 2019-12-06 10:48:45

问题


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 ?


回答1:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!