我有分支机构和主干的服务器存储库。该分支是所有团队成员的存储库。我正在尝试仅在我的分支下的repo中使用svn hooks
,但它似乎没有正常工作。以下是我试图采取的步骤:
从远程服务器的my_repo
branch/my_repo
由于本地回购my_repo
没有任何内容,我在本地创建了一个新的svn repo并复制了包括/hooks
文件夹在内的所有内容my_repo
。
我在my_repo
中创建了一个空文件,并添加了一行文字。然后svn add
此文件。
修改了my_repo/hooks/pre-commit.tmpl
文件并使其始终未通过错误代码1.现在看起来像:
#!/bin/sh exit 1
将pre-commit.tmpl
复制到预先提交并添加预先提交的执行许可
服务器现在包含其他人的服务器结构如下:
- server - branch - my_repo - myfile - hooks - pre-commit - Tom's repo - other team member's repo - trunk
svn commit -m "dumb change"
现在从这里我不能提交它应该给我一个错误代码1对吗?但我在任何地方都看不到它。
-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.
非常感谢大卫和任何人提前发表评论!
答案 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
。
我想对此非常非常清楚。我们需要同意一些定义:
svnadmin create foo
创建了一个foo
目录,该目录将充当存储库本身。svnadmin create
命令创建的服务器上的目录。这是存储库的SERVER SIDE。您将 不 在此处查看您已检入Subversion的所有文件。相反,您将看到hooks
目录和db
目录。这是服务器用于跟踪其更改的内容。svn checkout
检查项目特定修订版的目录。svn
或svn ls
或svn log
等各种svn co
命令时获得的REPOSITORY DIRECTORY的VIRTUAL视图。这不是REPOSITORY DIRECTORY,而是存储库的视图。好的,现在我们已经解决了这个问题:
Hook脚本存储在hooks
目录下的REPOSITORY DIRECTORY中。当您创建REPOSITORY DIRECTORY时,将会有一个名为hooks
的子目录,其中包含一些用于钩子脚本的模板。这些后缀为*.tmpl
。要创建一个钩子,您需要用钩子脚本替换其中一个脚本,并删除*.tmpl
后缀。钩子脚本必须具有可执行权限,并且由运行Subversion SERVER进程的用户拥有。 (用户在服务器上运行httpd
或svnserve
命令。)
挂钩适用于整个存储库。只有当特定分支受到影响时,才能告诉挂钩不要触发。但是,您的钩子脚本可以查看文件所在的位置并根据该脚本执行操作。我有一个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是存储库中发生的事情,而不是本地工作副本。
根据您对步骤的描述,这就是我得到的:
从远程存储库签出:远程服务器
由于签出的工作副本没有任何内容,我在本地创建了一个新的svn repo并复制了包括/ hooks文件夹在内的所有内容工作复制
我在签出的工作副本中创建了一个空文件,并添加了一行文字。然后svn添加此文件。
修改了工作副本中的hooks / pre-commit.tmpl文件,现在看起来像是:(已删除)
向所有用户添加执行许可,并将pre-commit.tmpl复制到预提交(这些都在工作副本中发生)
我使用以下命令提交了更改:svn commit -m“dumb change”
如果我的理解是正确的,你只是误解了钩的使用。 Hook是放在存储库中的东西,而不是工作副本。当您提交(或执行其他操作)时,Hook在存储库计算机上运行,而不是在本地计算机上运行。
答案 4 :(得分:0)
从tmpl复制并将exec添加到hooks脚本中,如下所示
cp post-commit.tmpl post-commit
chmod +x post-commit