SVN hooks not working

最后都变了- 提交于 2019-12-10 21:37:38

问题


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:

  1. checked out my_repo from the remote server's branch/my_repo

  2. 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.

  3. I created an empty file in my_repo and added a line of text. Then svn add this file.

  4. 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
  1. copy the pre-commit.tmpl to pre-commit and add execute permit of pre-commit to myself

  2. 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
  1. in the checked out repo I committed the changes using: svn commit -m "dumb change"

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.

  1. Then I tried putting the hooks folder at the top level and at same level as branch and trunk. i.e. the structure looks like:
-server
    - branches
        - my_repo
            - myfile
        - Tom's repo
        - other team member's repo
    - trunk
    - hooks
        - pre-commit

But, still not working. sigh...

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. 

Thank you so much David and anyone put comments earlier!


回答1:


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.

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 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.

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.

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.

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.

Also, never use svn in hook scripts. Use svnlook instead.


Addendum

I want to be very, very clear on this. We need to agree with some definitions:

  • The SERVER is the machine which is running the Subversion repository. You used the command svnadmin create foo to create a foo 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 a hooks directory and a db 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 like svn ls or svn log or svn co. This is NOT the REPOSITORY DIRECTORY but a view of the repository.

Okay, now we have this settled:

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 svnservecommand 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.




回答2:


Have you tried using an output file somewhere else, like /tmp? It sounds like you're trying to write back to your working copy directory, so maybe the hook script doesn't have access there?

Note that the hook will run as whatever user the SVN server process is running under, not the SVN client. So if you're using Apache WebDAV type access, it will be the user of Apache (I think); if using SSH access, it is the user listed in the svn+ssh://user@path syntax;




回答3:


modified the hooks/pre-commit.tmpl file and now it looks like

The pre-commit hook needs to be named just pre-commit. The pre-commit.tmpl is just an example file and will never be run.




回答4:


After reading your question, I am feeling a bit confusing. I was here just to make sure your understanding is correct:

There is no such thing as "checked out repo" in Subversion. We have repo (normally in a remote server), and after we checked out from that repo, we have a local working copy. Hooks is something happening in the repository, not local working copy.

From your descriptions of steps, this is what I get:

  1. checked out from a remote repository: remote server

  2. Since the checked out working copy doesn't have any content, I created a new svn repo locally and copied over everything including the /hooks folder to my checked out working copy.

  3. I created an empty file in the checked out working copy and added a line of text. Then svn add this file.

  4. modified the hooks/pre-commit.tmpl file in the working copy and now it looks like: (removed)

  5. add execute permit to all users and copy the pre-commit.tmpl to pre-commit (these are all happening in the working copy)

  6. in the checked out working copy I committed the changes using: svn commit -m "dumb change"

If my understanding is correct, you have simply misunderstood the use of hook. Hook is something put in the repository, not working copy. Hook runs on the repository machine when you are committing (or doing other actions), not on your local machine.




回答5:


copy from the tmpl and add exec to the hooks script, just like below

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


来源:https://stackoverflow.com/questions/14966807/svn-hooks-not-working

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!