SVN钩子无法正常工作

时间:2013-02-19 20:31:12

标签: svn hook commit

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

  1. 从远程服务器的my_repo

  2. 检出branch/my_repo
  3. 由于本地回购my_repo没有任何内容,我在本地创建了一个新的svn repo并复制了包括/hooks文件夹在内的所有内容my_repo

  4. 我在my_repo中创建了一个空文件,并添加了一行文字。然后svn add此文件。

  5. 修改了my_repo/hooks/pre-commit.tmpl文件并使其始终未通过错误代码1.现在看起来像:

  6. #!/bin/sh
    exit 1
    
    1. pre-commit.tmpl复制到预先提交并添加预先提交的执行许可

    2. 服务器现在包含其他人的服务器结构如下:

    3. - server
          - branch
              - my_repo
                  - myfile
                  - hooks
                      - pre-commit
              - Tom's repo
              - other team member's repo
          - trunk
      
        在已签出的回购邮件中
      1. ,我使用以下内容提交了更改:svn commit -m "dumb change"
      2. 现在从这里我不能提交它应该给我一个错误代码1对吗?但我在任何地方都看不到它。

        1. 然后我尝试将hooks文件夹放在顶层和分支和主干的同一级别。即结构如下:
        2. -server
              - branches
                  - my_repo
                      - myfile
                  - Tom's repo
                  - other team member's repo
              - trunk
              - hooks
                  - pre-commit
          

          但是,仍然没有工作。叹息...

          然而,在David的帮助下,我想出了该怎么做以及出了什么问题: 1.要突出显示:hooks文件夹的所有权应与创建到存储库的人员相同。因此,我不得不要求所有者将钩子文件添加到服务器。我没有在服务器上创建存储库,因此文件在我的工作目录中是不可见的。 2.现在这就是我的尝试:

            1) on my own Linux system, I `svnadmin create` a new repository, maybe called test_server: in that there is folders: confs, db, hooks, locks; files: format, readme.txt
            2) on the same level, mkdir a new folder (called working_dir) as your local working directory and checkout from the test_server. Now the working_dir contains a folder called test_server and it's empty. You can't see any of the folders or files in step 1
            3) modify the test_server's hooks file as described above. 
            4) try to add a file and add a new line to the file in the working_dir/test_server folder and commit. 
            5) now you should see commit failed with message: svn: Commit blocked by pre-commit hook(exit code 1) with no output. 
          

          非常感谢大卫和任何人提前发表评论!

5 个答案:

答案 0 :(得分:6)

当你运行一个钩子时,STDOUT(通常由echo语句产生的东西)被禁用。这意味着您的脚本无法使用STDOUT打印任何内容,即使它已被重定向到文件。

相反,您需要打开另一个文件描述符,而不是使用1(STDOUT)。您可以使用exec命令打开另一个文件描述符,然后将其传递到文件中:

exec 4> $my_file  #Opening my_file for writing
echo "This is going to $my_file" >&4

STDERR也重定向。收集STDERR的输出并将其发送回调用客户端,但仅当挂钩返回非零退出代码时。这为您提供了一种与客户端进行通信的方法,即钩子失败的原因。

你也必须小心,因为钩子运行的环境被擦洗了。即使$PATH为空。

这些是钩子脚本从命令行运行良好的一些原因,但不是当它作为钩子执行时。

如果您不相信某个钩子正在工作,只需将其设置为退出时使用非零退出代码即可。如果从Subversion收到一条消息,说明事务失败,则表示已执行挂钩脚本。

我还建议您至少使用svnserve充当Subversion服务器 - 即使您是唯一使用存储库的人。即使我是唯一一个使用存储库的人,我也从不使用file://svnserve进程非常简单易用,而且非常轻量级。

此外,永远不要在钩子脚本中使用svn。请改用svnlook


附录

我想对此非常非常清楚。我们需要同意一些定义:

  • SERVER是运行Subversion存储库的机器。您使用命令svnadmin create foo创建了一个foo目录,该目录将充当存储库本身。
  • REPOSITORY DIRECTORY是svnadmin create命令创建的服务器上的目录。这是存储库的SERVER SIDE。您将 在此处查看您已检入Subversion的所有文件。相反,您将看到hooks目录和db目录。这是服务器用于跟踪其更改的内容。
  • WORKING DIRECTORY是您完成svn checkout检查项目特定修订版的目录。
  • REPOSITORY是您使用svnsvn lssvn log等各种svn co命令时获得的REPOSITORY DIRECTORY的VIRTUAL视图。这不是REPOSITORY DIRECTORY,而是存储库的视图。

好的,现在我们已经解决了这个问题:

Hook脚本存储在hooks目录下的REPOSITORY DIRECTORY中。当您创建REPOSITORY DIRECTORY时,将会有一个名为hooks的子目录,其中包含一些用于钩子脚本的模板。这些后缀为*.tmpl。要创建一个钩子,您需要用钩子脚本替换其中一个脚本,并删除*.tmpl后缀。钩子脚本必须具有可执行权限,并且由运行Subversion SERVER进程的用户拥有。 (用户在服务器上运行httpdsvnserve命令。)

挂钩适用于整个存储库。只有当特定分支受到影响时,才能告诉挂钩不要触发。但是,您的钩子脚本可以查看文件所在的位置并根据该脚本执行操作。我有一个pre-commit hook就是这么做的。它使用控制文件根据文件的位置确定需要采取的操作。但是,每次提交时,即使它不需要执行任何操作,此挂钩也会触发。

我希望这能回答你的问题。

答案 1 :(得分:1)

您是否尝试过在其他地方使用输出文件,例如/tmp?听起来你正试图回写你的工作副本目录,所以钩子脚本可能没有访问权限吗?

请注意,挂钩将作为SVN 服务器进程运行的任何用户运行,而不是SVN 客户端。因此,如果您正在使用Apache WebDAV类型访问,它将是Apache的用户(我认为);如果使用SSH访问,则是svn+ssh://user@path语法中列出的用户;

答案 2 :(得分:0)

  

修改了hooks / pre-commit.tmpl文件,现在看起来像

预提交钩子只需要预先提交命名。 pre-commit.tmpl只是一个示例文件,永远不会运行。

答案 3 :(得分:0)

看完你的问题后,我感到有些困惑。我来这里只是为了确保你的理解是正确的:

在Subversion中没有“check out repo”这样的东西。我们有回购(通常在远程服务器中),在我们从该回购中签出后,我们有一个本地工作副本。 Hooks是存储库中发生的事情,而不是本地工作副本。

根据您对步骤的描述,这就是我得到的:

  1. 从远程存储库签出:远程服务器

  2. 由于签出的工作副本没有任何内容,我在本地创建了一个新的svn repo并复制了包括/ hooks文件夹在内的所有内容工作复制

  3. 我在签出的工作副本中创建了一个空文件,并添加了一行文字。然后svn添加此文件。

  4. 修改了工作副本中的hooks / pre-commit.tmpl文件,现在看起来像是:(已删除)

  5. 向所有用户添加执行许可,并将pre-commit.tmpl复制到预提交(这些都在工作副本中发生)

  6. 签出工作副本中的
  7. 我使用以下命令提交了更改:svn commit -m“dumb change”

  8. 如果我的理解是正确的,你只是误解了钩的使用。 Hook是放在存储库中的东西,而不是工作副本。当您提交(或执行其他操作)时,Hook在存储库计算机上运行,​​而不是在本地计算机上运行。

答案 4 :(得分:0)

从tmpl复制并将exec添加到hooks脚本中,如下所示

cp post-commit.tmpl post-commit
chmod +x post-commit