我需要在人们可以推送的存储库上设置一个 Hook ,这将运行一些验证(目标是在验证失败时拒绝推送)。我已经设置了一些 Hook ,以便在成功推送后自动更新,并防止出现多个 head。
我编写验证脚本(例如运行单元测试的 shell 脚本)没有问题,但它需要在完整的工作副本上运行。
我的问题是,如果我只是将它放在 pretxnchangegroup Hook 中,它不会对更新的文件进行操作。如果我尝试在 Hook 内进行 hg 更新,每当验证失败并且推送被回滚时,这会导致存储库损坏。
我目前的解决方案是将存储库克隆到某个临时文件夹并在那里运行实际验证。但我觉得这有点难看,而且就地验证只进行更新效率较低。是否可以设置这种 Hook ?
最佳答案
有很多方法可以做到这一点,但在我开始之前,您确定要这样做吗?在钩子(Hook)中进行阻塞、缓慢、拒绝推送的更改会惹恼人们,并且它一直持有存储库写锁,因此在验证脚本运行时没有其他人可以推送。人们可以很容易地将 DVCS 一半的生产力优势抛到窗外,以试图获得一点控制权。
您可以使用两层存储库设置来避免这些缺点中的大部分。像 project-push
这样的东西,人们可以在没有通过验证的情况下推送,而 project-pull
只有通过一些验证的变更集。然后,您有一个带外(cron 或 hook 触发)脚本,仅在确认验证后才将变更集从 project-push
移动到 project-pull
。因为该测试是在带外完成的,所以推送不会被阻止,但非验证变更集永远不会进入 project-pull
。当作者的推送使 project-pull
进入非验证状态时,您可以让它通过电子邮件发送给作者。具有这样配置的 .hg/hgrc
的用户根本不必考虑它们是两个存储库:
[paths]
default=http://host//path/to/project-pull
default-push=http://host//path/to/project-push
他们可以只使用 hg push
和 hg pull
一切都会“正常工作”。
也就是说,如果您的验证不需要同时访问所有更新的文件,您可以在外部 pretxnchangegroup
Hook 中使用类似的东西进行测试:
for thefile in $(hg manifest -r tip) ; do
if ! hg cat -r tip $thefile | ./validate_on_file.sh ; then
exit
fi
done
如果您确实需要一次对所有文件进行操作(编译等)并且您不愿意做一个可以让人们快速推送的双 repo 结构,那么您确实需要一个单独的 repo 来进行测试,但您不必每次都克隆/创建它。 pretxnchangegroup
Hook 中的类似内容应该这样做:
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
关于Mercurial pre-push hook 扫描工作副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9308658/