Creating a post-commit hook for Subversion

Creating a post-commit hook for Subversion

Posted by Brad Wood
Sep 15, 2008 21:30:00 UTC
I am doing some work with Subversion now so I got a chance to play with some hook functionality. Unfortunately, 99.99993% of all information out there for Subversion seems to be directed towards Linux, but after an appropriate amount of head-banging I got it working. Our dev server has Subversion installed with a repository holding our code. Each developer has installed TortoiseSVN (which is a Windows GUI client for the server) and checked out the code for local development. Then, on the server we also checked out the trunk folder into our wwwroot for IIS. The problem was, ever time we committed code from our local machine and wanted to run it on the dev server, we needed to remote into the server to update the code checked out to the wwwroot folder.To automate that process, you can use one of the several hooks for subversion. In your repository folder, you will find a directory called "hooks". Here are the possible hooks you can implement:
  • start-commit - Notification of the beginning of a commit.
  • pre-commit - Notification just prior to commit completion.
  • post-commit - Notification of a successful commit.
  • pre-revprop-change - Notification of a revision property change attempt.
  • post-revprop-change - Notification of a successful revision property change.
  • pre-lock - Notification of a path lock attempt.
  • post-lock - Notification of a successful path lock.
  • pre-unlock - Notification of a path unlock attempt.
  • post-unlock - Notification of a successful path unlock.
In Linux you need to place an executable file in the hooks directory with the same name as the hook. In Windows, file extensions are required, so your file will need to have the appropriate executable extension on the end of it. (.exe, .bat, .com, etc.) The file can be ANY executable from a batch file/shell script to a compiled executable. There are certain argument the files should expect. Number one big gotcha: For security, SVN runs the hooks in an empty environment, meaning any environment variables like PATH will not be available to your hook. Therefore, the code in them needs to be fully self-sufficient. This means fully qualified paths. Otherwise your commands won't be found. Second gotcha: If you are on Windows, your SVN service is probably running under the System account. This means it may have limited permissions and none of the network drives mapped for your user. If needed, create a new user for the SVN service and run as that user. In my example, I used a simple .bat file to call Subversion from the command line and update my wwwroot directory. It looks like this:
[code]D:\Subversion\bin\svn.exe update D:\wwwroot\ --quiet --non-interactive --username brad --password mypass --config-dir D:\svnrepos\myrepo\conf\[/code]
I am calling the SVN.exe executable (with a full path) and passing in the update switch. The second argument is the path to the checked out code in the wwwroot I want updated. --quiet suppresses any output since it won't be seen anyway, and --non-interactive tells it that there is no user to interact with. --username, --password, and -config-dir should be fairly self-explanatory. I originally created the batch file without the username, password, and config-dir arguments and it wouldn't run. After much fiddling (and the addition of those arguments) it began working. I removed the arguments one at a time to see which one was the magical fix, but to my amazement, the hook continued to run even after I restored it to its previously non-working state. Finally I got tired of trying to figure out why I couldn't get it to NOT work and gave up-- putting the batch file back. I figured more arguments would be safer than fewer. I will say, it is very frustrating to figure out why a hook isn't running. There are no visible errors or log entries (that I know of). It just does nothing and you sit and scratch your head. Also, I believe there is a program in Linux called "env" that will allow you to run something in an empty environment, but I was unable to find an equivalent way to test the file in Windows.

Dan G. Switzer, II

@Brad:

I went through the same pains you're going through when I first started writing SVN hooks for Windows. Fortunately, I found a few really good debugging tips that should save you a bunch of time:

http://blog.pengoworks.com/index.cfm/2008/2/5/Debugging-Subversion-Repository-Hooks-in-Windows

You already figured out #1, but I think you'll find tip #3 invaluable. By saving the output log of my SVNs, it now takes me no time to figure out where my script is failing. This was the biggest obstacle I kept running into. Before I started using this technique, I never knew why the scripts weren't working correctly.

Brad Wood

Awesome, Dan. That was just was I was looking for last night. Thanks.

todd

Real Names in Log messages for Subversion, using a post-commit hook for subversion combined with a rev-propset

We had these problems: Does anyone have a way to use "real names" in log messages? We've got our new SVN server authenticating against active directory, but my company uses employee IDs for usernames. see http://svn.haxx.se/users/archive-2007-08/0347.shtml

Here's our proof of concept that might be use to someone. I hope this might be userful

Basic call order:

  1. SVN client checks in
  2. post-commit.bat a. calls actual hook and logs
  3. post-commit-run.bat a. post-commit does NOT appear to be given the user – go and get it from the repository b. svnlook for actual commit <user> and <revision>: svnlook author . && svnlook history . [you will then need to grep the information out of these commands] c. ldap lookup for human readable name d. update author to <name> rather than <user>: svn propset svn:author --revprop –r <rev> <name>
  4. pre-revprop-change.bat a. calls actual hook and log
  5. pre-revprop-change-run.bat a. any filtering here – at this stage empty file will suffice but this file MUST exist for svn:author to be set

Tips: • chain files for logging (see reference 2 below) • pre-revprop-change.bat MUST exist (this is well documented in SVN literature) • look at caching ldap lookups (eg Ruby ActiveLDAP library) • remember that .bat files must not have shell commands in it. I forgot that is a remark for sh rather than REM for batch files. The logging will display error easily though

References:

• Good list of the hooks: http://www.codersrevolution.com/index.cfm/2008/9/15/Creating-a-postcommit-hook-for-Subversion • 3 strategies: including how to debug: http://blog.pengoworks.com/index.cfm/2008/2/5/Debugging-Subversion-Repository-Hooks-in-Windows • Good example of a windows hook script: http://svn.haxx.se/users/archive-2006-03/0107.shtml

Scripts:

post-commit.bat

call %~dp0post-commit-run.bat %* > %1/hooks/post-commit.log 2>&1

post-commit-run.bat

set repos=%1 set rev=%2 set user=%3 set propname=%4 set action=%5

REM this is where the svnlook and ldap look up must occurs REM then do a svn propset svn:author --revprop –r <rev> <name>

pre-revprop-change.bat

call %~dp0pre-revprop-change-run.bat %* > %1/hooks/pre-revprop-change.log 2>&1

pre-rev-prop-change-run.bat

set repos=%1 set rev=%2 set user=%3 set propname=%4 set action=%5 REM does nothing but must exist

TODO: • Write a batch file parser of svnlook results • Write an LDAP look up

syful

How can i update remote working copy, means working copy not in the same machine as repository, but under LAN.

BuggedTech

Hi,

One of the things that I couldn't do when I started creating a post-commit hook was on how to display something on the committer's screen (whether) command line or GUI after every commit.

I found out a solution, redirecting file descriptor 1(standard output) to 2 (standard input) and sending an exit 1. It's not a very elegant solution but it works. Check out my <a href="http://www.buggedtech.com/2011/01/15/subversion-post-commit-hook-basic/">very basic subversion post-commit post</a>

Thanks, Ismael Casimpan