【问题标题】:Mercurial hook not executing properlyMercurial 钩子没有正确执行
【发布时间】:2009-05-11 15:25:31
【问题描述】:

这应该是一个非常简单的运行,但由于某种原因,它不适用于我的 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 开关从我的工作站推送到远程仓库不会打印任何详细消息,即使我在.hg/hgrc 中有那些echo 行。但是,当我从同一文件系统上的 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,它不起作用。

【问题讨论】:

  • 我遇到了完全相同的问题。您已经找到解决方案了吗?
  • 从未找到解决方案。我很久以前就放弃了。

标签: version-control mercurial mercurial-hook


【解决方案1】:

好吧,在经历了与 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

【讨论】:

  • 这是奇怪的行为,但我有同样的问题,将钩子部分移动到 hgwe.confog 文件修复了它
  • hgweb 现在确实支持配置文件,方式相同。
  • 你刚刚为我节省了几个小时。谢谢
  • 嗯,这确实很旧,但我遇到了同样的问题,hgrc 现在至少在 mercurial 2.6 中通过 repo 基础工作......记住 hgrc 必须由 www-data 拥有
  • 这对我来说是非常非常有用的信息。谢谢!
【解决方案2】:

我自己花了一些时间研究这个。我认为问题的答案描述得很简洁here

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

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

【讨论】:

  • 哇,我很高兴他们终于在常见问题解答中包含了这个!希望我一年前有这个。谢谢你终于回答了这个问题。 =)
  • 最后?维基历史显示,至少从 2008 年 1 月起就出现在常见问题解答中:mercurial.selenic.com/wiki/FAQ/…
  • 天啊...不敢相信我的眼睛...多么好的软件设计... =/
【解决方案3】:

首先,我想更正上面的几个cmets。

  • 在推送文件系统时也会调用挂钩。
  • 没有必要将钩子保留在您希望它们操作的存储库中。您也可以在用户端编写与您的问题相同的钩子。您必须将事件从更改组更改为传出,并且还必须使用 -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 开关推动,这样您就可以知道哪个钩子正在运行。如果您仍然无法弄清楚,请发布输出。我也许能帮上忙。

【讨论】:

  • 感谢您的回复!我会在这个星期一试试,然后告诉你。
  • 有趣的是,你给我的东西在本地推送时有效,但在远程推送时不起作用。我什至只使用了“changegroup = hg update”,它是一样的;适用于本地,不适用于远程。更奇怪的是,当我上周尝试时,我认为这不起作用。一定有什么不同。是否需要设置某种配置以允许在远程推送期间运行挂钩?
  • 你能解释一下本地推送和远程推送到底是什么意思吗?我再次要求您在使用 -v 开关远程推送时发布调试输出。使用我提供的钩子。我不知道是否有任何钩子执行的配置。您应该检查您的 ~/.hgrc 和 /etc/hgrc 文件是否存在非标准、可疑的配置。 – Aamir 4 秒前 [删除此评论]
  • 本地推送是指从同一个文件系统推送(不涉及网络访问)。所以我将存储库克隆到我的主目录中的另一个位置,并从那里推送回原始存储库。远程推送是指从不同的工作站通过网络推送。当我使用 -v 远程推送时,我实际上没有得到调试输出。只有在本地推送时才会打印任何内容,这正是您所期望的(tip 和 wdir 在更新之前处于不同的转速,在更新之后也是如此)。不过,如果您仍然需要,我可以稍后发布。
  • 阿米尔,我发布了你在我的问题中提出的要求。
【解决方案4】:

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

[trusted]
users = me

【讨论】:

    【解决方案5】:

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

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

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

    【讨论】:

    • 它实际上位于远程 repo 的 .hg/hgrc 中。此外,所有推送都通过 https 进行。
    • 好的。你能推过 ssh 看看你是否得到不同的结果?
    • 好的,我刚刚尝试使用拥有存储库的用户进行本地推送。还是没有骰子。我什至没有任何错误。它似乎只是专门忽略了“hg update”命令。
    • 真的很奇怪。您是否尝试过使用 python 钩子而不是 shell 命令?
    【解决方案6】:

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

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

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

    【讨论】:

      【解决方案7】:

      试试turning on hook debugging 看看为什么它没有运行。

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

      【讨论】:

      • 我也试过了。没有任何有用的报告。没有错误或警告或任何类似的东西。
      【解决方案8】:

      花了一些时间,但我成功了。

      我从

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

      >&2 将其通过管道传输到标准错误,以便远程控制台显示它。

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

      hg push https://host/hg   -v
      

      不是。

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

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

      当我把它切换到

      [hooks]
      incoming= set >&2
      

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

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

      【讨论】:

        【解决方案9】:

        我找到的原因与将stdout 重定向到stderr 无关。正如您在 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,它的主页上有一个回购,还有一个脚本/etc/init.d/hg.init 来启动hg servehg 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-12
          • 1970-01-01
          • 2015-03-30
          • 2020-04-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多