SVN挂钩不起作用 [英] SVN hooks not working
问题描述
我有一个分支和主干的服务器存储库。分支是所有团队成员的资料库。我试图仅在分支下的回购中使用 svn钩子
,但这似乎无法正常工作。以下是我尝试执行的步骤:
I have a server repository of branch and trunk. The branch is all team members' repositories. I'm trying to use svn hooks
only in my repo under branch, but it doesn't seem to work fine. In the following are the steps I tried to approach:
-
已签出
my_repo
来自远程服务器的branch / my_repo
,因为本地存储库 my_repo
没有任何内容,我在本地创建了一个新的svn存储库,并将包括 / hooks
文件夹在内的所有内容复制到 my_repo
。
since the local repo my_repo
doesn't have any content, I created a new svn repo locally and copied over everything including the /hooks
folder to my_repo
.
我在 my_repo
中创建了一个空文件,并添加了一行文字。然后 svn添加
此文件。
I created an empty file in my_repo
and added a line of text. Then svn add
this file.
修改了 my_repo / hooks / pre -commit.tmpl
文件,并使其始终不以错误代码1传递。现在看起来像这样:
modified the my_repo/hooks/pre-commit.tmpl
file and make it always not pass with error code 1. Now it looks like:
#!/bin/sh
exit 1
-
复制
pre-commit.tmpl
进行预提交,并向自己添加预提交的执行许可
copy the
pre-commit.tmpl
to pre-commit and add execute permit of pre-commit to myself
服务器包含其他人,现在服务器的结构类似于:
The server contains other people's now the server's structure is like:
- server
- branch
- my_repo
- myfile
- hooks
- pre-commit
- Tom's repo
- other team member's repo
- trunk
- 在已签出的仓库中,我使用以下命令提交了更改:
svn commit -m傻瓜更改
- in the checked out repo I committed the changes using:
svn commit -m "dumb change"
现在从这里我不应该能够提交,它应该给我一个错误,代码1正确?但我在任何地方都看不到。
Now from here I should not be able to commit and it should give me an error with code 1 right? But I don't see it anywhere.
- 然后我尝试将hooks文件夹放在顶层,并与分支和主干位于同一级别。即结构看起来像:
-server
- branches
- my_repo
- myfile
- Tom's repo
- other team member's repo
- trunk
- hooks
- pre-commit
但是,仍然无法正常工作。感叹……
But, still not working. sigh...
但是,在David的帮助下,我弄清楚了该怎么做和出了什么问题:
1.强调:钩子的所有权文件夹应与创建存储库的人相同。因此,我不得不要求所有者将挂钩文件添加到服务器。我没有在服务器上创建存储库,因此文件在我的工作目录中不可见。
2.现在,这是我尝试的方法:
HOWEVER, with David's help, I figured out what to do and what was wrong: 1. To highlight: the ownership of the hooks folder should be the same as who created to repository. Thus I had to ask the owner to add the hooks files to the server. I didn't create the repository on the server, thus the files are invisible in my working directory. 2. now here's what I tried:
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.
非常感谢David和任何人早些发表评论!
Thank you so much David and anyone put comments earlier!
推荐答案
运行钩子时,STDOUT(通常由 echo
语句产生的)被禁用。这意味着即使将脚本重定向到文件,您的脚本也无法使用STDOUT打印任何内容。
When you run a hook, the STDOUT (what normally is produced by an echo
statement) is disabled. This means your script cannot use STDOUT to print out anything, even if it has been redirected to a file.
相反,您需要打开另一个文件描述符而不是使用 1
(STDOUT)。您可以使用 exec
命令打开另一个文件描述符,然后将其通过管道传输到文件中:
Instead, you need to open another file descriptor instead of using 1
(STDOUT). You can use the exec
command to open another file descriptor, and then pipe that into a file:
exec 4> $my_file #Opening my_file for writing
echo "This is going to $my_file" >&4
STDERR也被重定向。收集STDERR的输出,并将其发送回调用方客户端,但是仅当挂钩返回非零退出代码时才如此。这样,您就可以与客户端进行通信,说明挂钩失败的原因。
STDERR is also redirected. The output of STDERR is collected and sent back to the calling client, but only when a hook returns a non-zero exit code. This gives you a way to communicate with the client why a hook failed.
您还必须小心,因为清理了挂钩运行所在的环境。甚至 $ PATH
也为空。
You also must be careful because the environment that the hook runs in is scrubbed. Even $PATH
is null.
这些是从命令行运行钩子脚本的一些原因,但不是
These are some of the reasons why a hook script will run fine from the command line, but not when it is executed as a hook.
如果您不相信钩子在起作用,只需对其进行设置,使其以非零的退出代码退出。如果您从Subversion收到一条消息,说明事务失败,那么您就知道该钩子脚本已执行。
If you don't believe a hook is working, just set it so it exits with a non-zero exit code. If you get a message back from Subversion that the transaction failed, you know the hook script executed.
我还建议您至少使用 svnserve
充当Subversion服务器-即使您是唯一使用存储库的服务器。即使我是使用存储库的唯一人,我也从不使用 file://
。 svnserve
的过程非常简单,而且非常轻巧。
I also recommend that you use, at a minimum, svnserve
to act as a Subversion server -- even if you're the only one using the repository. I never use file://
even if I'm the only one using the repository. The svnserve
process is pretty simple to use and it's fairly lightweight.
此外,请不要使用 svn
在挂钩脚本中。改用 svnlook
。
Also, never use svn
in hook scripts. Use svnlook
instead.
我要要对此非常非常清楚。我们需要同意一些定义:
I want to be very, very clear on this. We need to agree with some definitions:
- SERVER是运行Subversion存储库的机器。您使用命令
svnadmin create foo
创建一个将用作存储库本身的foo
目录。 - 存储库目录是由
svnadmin create
命令在服务器上创建的目录。这是资源库的SERVER SIDE。您将 不 在此处看到您已签入Subversion的任何文件。相反,您将看到一个hooks
目录和一个db
目录。这就是服务器用来跟踪其更改的内容。 - 工作目录是您执行
svn结帐
进行结帐的目录 - 存储库是使用各种
svn
命令时获得的存储库目录的虚拟视图。例如svn ls
或svn日志
或svn co </ code>。这不是存储库目录,而是存储库的视图。
- The SERVER is the machine which is running the Subversion repository. You used the command
svnadmin create foo
to create afoo
directory that will act as the repository itself. - The REPOSITORY DIRECTORY is the directory on the server created by the
svnadmin create
command. This is the SERVER SIDE of the repository. You will not see any files you've checked into Subversion here. Instead, you will see ahooks
directory and adb
directory. This is what the server uses to track its changes. - The WORKING DIRECTORY is the directory you've done a
svn checkout
to checkout a particular revision of your project. - The REPOSITORY is the VIRTUAL view of the REPOSITORY DIRECTORY you get when you use the various
svn
commands likesvn ls
orsvn log
orsvn co
. This is NOT the REPOSITORY DIRECTORY but a view of the repository.
好的,现在我们解决了:
Okay, now we have this settled:
挂钩脚本存储在钩子
目录下的存储库目录中。创建存储库目录时,将已经有一个名为 hooks
的子目录,其中包含一些用于挂钩脚本的模板。这些将具有 *。tmpl
后缀。要创建一个钩子,您需要用钩子脚本替换其中一个脚本,并删除后缀 *。tmpl
。挂钩脚本必须具有可执行权限,并且必须由运行Subversion SERVER进程的用户拥有。 (用户在服务器上运行 httpd
或 svnserve
命令)。
Hook scripts are stored in the REPOSITORY DIRECTORY under the hooks
directory. When you create the REPOSITORY DIRECTORY, there will already be a sub-directory called hooks
with some templates for hook scripts. These will have a *.tmpl
suffix. To make a hook, you need to replace one of these scripts with your hook script, and remove that *.tmpl
suffix. The hook script has to have executable permission and be owned by the user that is running the Subversion SERVER process. (The user running httpd
or the svnserve
command on the server).
挂钩适用于整个存储库。您不能告诉钩子仅在特定分支受到影响时才触发。但是,您的挂钩脚本可以查看文件的位置,并据此采取措施。我有一个预提交钩子就是这样做的。它使用控制文件来根据文件的位置确定需要执行的操作。但是,每次执行提交时,即使不需要执行任何操作,该钩子也会触发。
Hooks are for the entire repository. You can't tell a hook not to fire only when a particular branch is affected. However, your hook script can see where a file is located and take action based upon that. I have a pre-commit hook that does just that. It uses a control file to determine the action it needs to take based upon the location of a file. However, every time a commit happens, this hook will fire even if it doesn't have to do anything.
我希望这能回答您的问题。
I hope this answers your questions.
这篇关于SVN挂钩不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!