8

这应该是一件非常简单的事情,但由于某种原因,它不适用于我的 Mercurial 存储库。我想要的只是让远程仓库hg update在有人推送时自动运行。所以我在 .hg/hgrc 文件中有这个:

[hook]
changegroup = hg update

很简单,对吧?但由于某种原因,这永远不会执行。我还尝试编写一个执行此操作的 shell 脚本。.hg/hgrc 看起来像这样:

[hooks]
changegroup = /home/marc/bin/hg-update

hg-update 看起来像这样:

#!/bin/sh
hg help >> /home/marc/works.txt;
hg update >> /home/marc/works.txt;
exit 0;

但同样,这不会更新。的内容hg help被写入works.txt,但没有任何内容被写入hg update。我在这里有什么明显的遗漏吗?这已经困扰我好几天了,我似乎无法让它发挥作用。

更新

好的,再次使用-v从我的工作站推送到远程仓库的命令行上的开关不会打印任何详细消息,即使我echo.hg/hgrc. 但是,当我从同一文件系统上的 repo 克隆进行推送时(我通过 SSH 登录),这就是我得到的:

bash-3.00$ hg -v push ../test-repo/
推送到 ../test-repo/
寻找变化
找到 1 个变更集
运行钩子 prechangegroup: echo "远程仓库位于 `hg tip -q`"
echo "远程仓库 wdir 位于 `hg parents -q`"
远程仓库位于 821:1f2656753c98
远程仓库 wdir 位于 821:1f2656753c98
添加变更集
添加清单
添加文件更改
添加了 1 个变更集,对 1 个文件进行了 1 次更改
运行钩子更改组:回声“正在更新....`hg update -v`”
echo "远程仓库位于`hg tip -q`"
echo "远程仓库 wdir 位于 `hg parents -q`"
更新....解决清单
获取 license.txt
1 个文件已更新,0 个文件已合并,0 个文件已删除,0 个文件未解决
远程仓库位于 822:389a6c7276c6
远程仓库 wdir 位于 822:389a6c7276c6

所以它有效,但只有当我从同一个文件系统推送时。如果我尝试通过网络从另一个工作站推送到 repo,它就不起作用。

4

9 回答 9

11

好吧,在经历了与 Marc W 前一段时间相同的挫折步骤之后,我终于找到了问题的解决方案,至少在使用 hgwebdir WSGI 脚本完成远程服务时。

我发现当通过 HTTP 或 HTTPS 使用这种远程推送时,Mercurial 只会忽略您写入 .hg/hgrc 文件或存储库的所有内容。但是,在 hgwebdir 配置中输入钩子就可以了。

因此,如果您的hgwebdir.wsgi脚本中的底线类似于

application = hgwebdir('hgweb.config')

[hooks] 配置部分需要进入提到的hgweb.config

一个缺点是这些钩子是针对该配置的 [paths] 部分中列出的每个存储库执行的。尽管 HG 提供了另一个支持 WSGI 的函数(hgweb 而不是 hgwebdir)来仅服务于单个存储库,但该函数似乎不支持任何钩子(它也没有任何配置)。然而,这可以通过使用如上所述的 hgwebdir 并让一些 Apache RewriteRule 将所有内容映射到所需的子目录来规避。这个对我有用:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/reponame
RewriteRule ^(.*)$ reponame/$2 [QSA]

通过 HTTP 使用远程挂钩玩得开心:D

于 2010-02-02T12:37:52.353 回答
10

我自己花了一些时间研究这个。我认为问题的答案在这里简明扼要地描述了:

输出必须重定向到 stderr(或 /dev/null),因为 stdout 用于数据流。

基本上,您不会重定向到标准错误,因此会污染标准输出。

于 2010-09-03T10:01:15.647 回答
3

首先,我想更正上面的一些评论。

  • 推送文件系统时也会调用挂钩。
  • 没有必要将钩子保留在您希望它们操作的 repo 中。您也可以在用户端编写与您的问题相同的钩子。您必须将事件从更改组更改为传出,并且还必须使用 -R 开关指定远程仓库的 URL。然后如果推送用户对远程仓库有足够的权限,钩子就会成功执行。

.hg/hgrc

[hooks]
outgoing = hg update -R $HG_URL

现在解决你的问题......我建议创建 prechangegroup 和 changegroup 挂钩并打印一些调试输出。

.hg/hgrc

[hooks]
prechangegroup = echo "Remote repo is at `hg tip -q`"
                 echo "Remote repo wdir is at `hg parents -q`"
changegroup    = echo "Updating.... `hg update -v`"
                 echo "Remote repo is at `hg tip -q`"
                 echo "Remote repo wdir is at `hg parents -q`"

还可以使用 -v 开关推动,这样您就可以知道哪个钩子正在运行。如果您仍然无法弄清楚,请发布输出。我也许能帮上忙。

于 2009-05-17T00:28:05.763 回答
3

我的问题是我的 hgwebdir 应用程序以“hg”用户身份运行,但存储库归我所有,因此我必须将这一配置添加到 hgweb.config 以使其运行挂钩:

[trusted]
users = me
于 2011-08-14T23:54:41.353 回答
2

您需要将它放在远程存储库的 hgrc 中。听起来好像它在您的本地仓库中。

编辑:这也取决于你如何推动。有些方法不会调用右侧的钩子。(ssh 会,我认为 HTTP 会,文件系统不会

Edit2:如果您在远程仓库的计算机上“本地”推送会怎样。您可能在网络服务器和 hgrc 文件之间拥有不同的用户/权限。(参见 [server] 和 hgrc 的可信指令。)

于 2009-05-11T20:17:19.317 回答
2

我在通过 http 从 Windows Eclipse 推送时遇到了同样的问题,但是在捕获 stderr 后,我发现 hg.bat 文件需要完整路径。我的钩子部分现在看起来像:

[hooks]
incoming = c:\Python27\Scripts\hg.bat update > hg_log.txt 2>>hg_err.txt

希望这对其他人有帮助。史蒂夫

于 2010-10-19T20:34:11.917 回答
1

尝试打开钩子调试,看看为什么它没有运行。

可能是权限问题或类似问题。

于 2009-05-11T15:41:40.140 回答
1

花了一段时间,但我得到了它的工作。

我从

[hooks]
tag=set >&2
commit=set >&2

>&2 将其传递给标准错误,以便远程控制台显示它。

当远程时,如果它正在运行,它应该在控制台中输出

hg push https://host/hg   -v

不是。

我使用的是 hgweb.cgi,所以我切换到 hgweb.wsgi 没有任何区别。

我发现有些钩子不会在远程调用。

当我把它切换到

[hooks]
incoming= set >&2

钩子标签和提交似乎没有被调用,但传入和变更集确实被调用。其他的我还没有确认。

现在我让它工作了,我切换回 hgweb.cgi,一切正常。

于 2010-11-08T14:18:27.630 回答
1

我找到的原因与重定向stdoutstderr. 正如您在 wiki 页面中看到的那样,它未在 wiki 的当前版本中指定 https://www.mercurial-scm.org/wiki/FAQ#FAQ.2FCommonProblems.Any_way_to_.27hg_push.27_and_have_an_automatic_.27hg_update.27_on_the_remote_server.3F

我发现的问题是权限

在我最初的设置中,我有一个用户,可以说它hguser的主页上有一个 repo,还有一个/etc/init.d/hg.init要启动的脚本hg serve。问题是hg serve由 运行的root,而 repo 下的大多数文件都与hguser(其中一些在某个时候切换到root,但它不会介意,因为我会用 更正它们chown

解决方案:

  • chown -R hguser:hguser /home/hguser/repo(要更正所有文件,请返回 hguser)
  • 发射su hguser -c "hg serve ..."(在我的情况下从/etc/init.d/hg.init
  • changegroup = hg update -C[hooks]repo/.hg/hgrc往常一样下

现在它应该可以工作了push

PS:在我的情况下,我宁愿更新到特定分支的头部,所以我使用hg update -C -r staging, 使登台服务器仅更新到预期分支的头部,即使tip是来自另一个分支(development例如)

顺便说一句,我的hg.init脚本最终是这样的:(注意su hguser部分)

#!/bin/sh
#
# Startup script for mercurial server.
#
# @see http://jf.blogs.teximus.com/2011/01/running-mercurial-hg-serve-on-linux.html

HG=/usr/bin/hg
CONF=/etc/mercurial/hgweb.config
# Path to PID file of running mercurial process.
PID_FILE=/etc/mercurial/hg.pid

state=$1

case "$state" in
'start')
    echo "Mecurial Server service starting."
    (su hguser -c "${HG} serve -d --webdir-conf ${CONF} -p 8000 --pid-file ${PID_FILE}")
  ;;

'stop')
  if [ -f "${PID_FILE}" ]; then
    PID=`cat "${PID_FILE}"`
    if [ "${PID}" -gt 1 ]; then
      kill -TERM ${PID}
      echo "Stopping the Mercurial service PID=${PID}."
    else
      echo Bad PID for Mercurial -- \"${PID}\"
    fi
  else

    echo No PID file recorded for mercurial
  fi
  ;;

*)
  echo "$0 {start|stop}"
  exit 1
  ;;
esac

PS:归功于http://jf.blogs.teximus.com/2011/01/running-mercurial-hg-serve-on-linux.html

于 2015-05-29T21:06:49.473 回答