SVN 钩子(Hook)不起作用

标签 svn hook commit

我有一个分支和主干的服务器存储库。分支是所有团队成员的存储库。我正在尝试使用 svn hooks仅在我的分支下的 repo 中,但它似乎无法正常工作。以下是我尝试采取的步骤:

  • checkout my_repo来自远程服务器的branch/my_repo
  • 自本地 repo my_repo没有任何内容,我在本地创建了一个新的 svn 存储库并复制了所有内容,包括 /hooks文件夹到 my_repo .
  • 我在 my_repo 中创建了一个空文件并添加了一行文字。然后svn add这个文件。
  • 修改了my_repo/hooks/pre-commit.tmpl文件并使其始终不通过,错误代码为 1。现在它看起来像:

  • #!/bin/sh
    1号导出
  • 复制pre-commit.tmpl预先提交并为自己添加预先提交的执行许可
  • 服务器包含其他人的现在服务器的结构是这样的:

  • - 服务器
    - 分支
    - my_repo
    - 我的文件
    - Hook
    - 预提交
    - 汤姆的 repo
    - 其他团队成员的 repo
    - 树干
  • 在 checkout 的仓库中,我使用以下代码提交了更改:svn commit -m "dumb change"

  • 现在从这里我应该无法提交,它应该给我一个代码 1 的错误,对吗?但我在任何地方都看不到它。
  • 然后我尝试将 hooks 文件夹放在顶层,并与分支和树干处于同一水平。即结构看起来像:

  • -服务器
    - 分支机构
    - my_repo
    - 我的文件
    - 汤姆的 repo
    - 其他团队成员的 repo
    - 树干
    - Hook
    - 预提交

    但是,仍然无法正常工作。叹...

    然而,在大卫的帮助下,我弄清楚了该怎么做以及出了什么问题:
    1. 强调一下:hooks 文件夹的所有权应该和仓库的创建者相同。因此,我不得不要求所有者将 Hook 文件添加到服务器。我没有在服务器上创建存储库,因此这些文件在我的工作目录中是不可见的。
    2.现在这是我尝试过的:

    1)在我自己的Linux系统上,我`svnadmin create`一个新的存储库,可能称为test_server:其中有文件夹:confs,db,hooks,locks;文件:格式,readme.txt
    2)在同一级别上,mkdir 一个新文件夹(称为working_dir)作为您的本地工作目录并从test_server checkout 。现在 working_dir 包含一个名为 test_server 的文件夹,它是空的。您在步骤 1 中看不到任何文件夹或文件
    3) 如上所述修改 test_server 的 hooks 文件。
    4)尝试添加一个文件并在working_dir/test_server文件夹中的文件中添加一个新行并提交。
    5)现在您应该看到提交失败并显示消息:svn:提交被预提交 Hook (退出代码 1)阻止,没有输出。

    非常感谢大卫和任何人早些时候发表评论!

    最佳答案

    运行 Hook 时,STDOUT(通常由 echo 语句生成)被禁用。这意味着您的脚本不能使用 STDOUT 打印出任何内容,即使它已被重定向到文件。
    相反,您需要打开另一个文件描述符而不是使用 1 (标准输出)。您可以使用 exec命令打开另一个文件描述符,然后将其通过管道传输到文件中:

    exec 4> $my_file  #Opening my_file for writing
    echo "This is going to $my_file" >&4
    
    STDERR 也被重定向。收集 STDERR 的输出并将其发送回调用客户端,但前提是 Hook 返回非零退出代码。这为您提供了一种与客户端沟通 Hook 失败原因的方法。
    您还必须小心,因为 Hook 运行的环境已被清除。偶$PATH一片空白。
    这些是钩子(Hook)脚本可以在命令行中正常运行的一些原因,但当它作为钩子(Hook)执行时则不行。
    如果您不相信钩子(Hook)正在工作,只需将其设置为以非零退出代码退出。如果您从 Subversion 收到交易失败的消息,您就知道钩子(Hook)脚本已执行。
    我还建议您至少使用 svnserve充当 Subversion 服务器 - 即使您是唯一使用存储库的人。我从不使用 file://即使我是唯一一个使用存储库的人。 svnserve过程使用起来非常简单,而且相当轻量级。
    此外,切勿使用 svn在钩子(Hook)脚本中。使用svnlook反而。

    附录
    我想非常非常清楚地说明这一点。我们需要同意一些定义:
  • SERVER 是运行 Subversion 存储库的机器。您使用了命令 svnadmin create foo创建 foo将充当存储库本身的目录。
  • REPOSITORY DIRECTORY 是服务器上由 svnadmin create 创建的目录。命令。这是存储库的服务器端。你会 不是 在此处查看您已 checkin Subversion 的所有文件。相反,您将看到 hooks目录和 db目录。这是服务器用来跟踪其更改的内容。
  • WORKING DIRECTORY 是您创建的目录 svn checkout checkout 项目的特定版本。
  • REPOSITORY 是您在使用各种 svn 时获得的 REPOSITORY DIRECTORY 的虚拟 View 。像 svn ls 这样的命令或 svn logsvn co .这不是存储库目录,而是存储库的 View 。

  • 好的,现在我们解决了这个问题:
    Hook 脚本存储在 hooks 下的 REPOSITORY DIRECTORY 中目录。创建存储目录时,已经有一个名为 hooks 的子目录。带有一些用于钩子(Hook)脚本的模板。这些将有 *.tmpl后缀。要制作一个钩子(Hook),您需要用您的钩子(Hook)脚本替换其中一个脚本,然后删除它 *.tmpl后缀。钩子(Hook)脚本必须具有可执行权限并且归运行 Subversion SERVER 进程的用户所有。 (用户在服务器上运行 httpdsvnserve 命令)。
    Hook 适用于整个存储库。您不能仅在特定分支受到影响时才告诉钩子(Hook)不要触发。但是,您的钩子(Hook)脚本可以查看文件所在的位置并据此采取行动。我有一个 pre-commit hook就是这样做的。它使用控制文件根据文件的位置确定需要采取的操作。然而,每次提交发生时,即使它不需要做任何事情,这个钩子(Hook)也会触发。
    我希望这回答了你的问题。

    关于SVN 钩子(Hook)不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14966807/

    相关文章:

    git - 将远程 SVN 存储库 fork 到 git

    eclipse - 无法在 Eclipse 中添加 SVN 存储库

    iphone - Hook 到 C 函数

    java - 在游戏中用java检测鼠标点击

    Git 回顾性提交

    svn - 无法使用 TortoiseSVN 连接到存储库

    javascript - js hook 在浏览器中的 html 加载过程

    git - 用 Git 重命名 : Using git mv vs deleting a file and adding another

    SVN 在服务器端恢复

    svn - Windows 7中没有TortoiseSVN的上下文菜单