Writing Subversion Hooks on Windows with Python

When a developer Commits code changes to the respository, an optional Log Message can be filled out indicating what has changed in the file being committed. Log Messages are handy to have available as they aid the team in figuring out in which version certain changes were made, as well as aiding conflict resolution. But developers don't always fill out a Log Message. So here is how you can force that discipline, by requiring at least 10 characters in the Log Message prior to the Commit.

Before I continue, thanks goes out to Pete Freitag for blogging about Jacques Marneweck's Pre-Commit Hook Code, which was altered to work with Python on Windows in this entry.

Subversion has the ability to add custom code, called a Hook, that runs during certain Subversion operations, such as a Commit. The Hook we used is a Pre-Commit. Unfortunately, most hooks are coded for a UNIX environment, not Windows, so my co-worker Quan Eastin and I spent about 4 hours adapting the Linux version to work on Windows using Python. Through trail and error we figured out how to get the hook working with an executable batch file and Python.

Python runs on all platforms, is Java-based, and is easy to work with. It should be installed on the Windows server running Subversion. Then, we can run our Python code by executing a Windows Batch file (.bat) and using command-line commands to run the Python file, like this:

PATH=C:\Python25
python.exe C:\svnrepos\[RepositoryName]\hooks\pre-commit.py %1 %2

Subversion running on Windows does not set environment variables at all. You can read more about that in the svnbook. So line 1 sets the PATH to where Python was installed.

The next line executes Python, then points to the location of the Python file we created. Notice we are passing two arguments. Those could be called anything, we just happened to use %1 and %2. As long as there are two arguments being passed, everything will work as expected.

Every Subversion Repository has a Hooks folder. And inside it are a bunch of .tmpl files. Those are templates to help you write code for additional custom Subversion behavior. Whichever template you decide to use, it is important to name your batch (.bat) file and Python (.py) file exactly the same. So if you use the pre-commit.tmpl file, name your batch file pre-commit.bat and name your Python file pre-commit.py. Make sure both files are in your Hooks directory with the .tmpl files.

The Python code is too long to put all of it in this blog entry, so download the .zip and open the file in your favorite editor. I'm using CFEclipse. I will include some of the code as I explain, however.

Line 1 (below) declares the file as a shell script, and is mapping to python.exe on our server.

#!C:\Python25\python.exe

Lines 2 thru 14 are comments and some code we used to figure things out.

Line 21 declares the path to where svnlook.exe is on your server. This is required.

SVNLOOK='"C:\Program Files\Subversion\\bin\svnlook.exe"'
NOTE: If there are any spaces in the path, like Program Files, then the entire path should be in double quotes. Notice how the double-quoted path is in single quotes. Also notice the dual slash before bin. That is required too, because one of the slashes escapes the other. \b is a Python command and results in your \bin looking like a square symbol with "in" next to it.

Line 45 is actually running first and if the 2 arguments are passed in from the batch file, then it calls the main method passing the 2 arugments. We go back up to line 23.

Line 23 the two arguments are called repos and txn.

  • repos is the path to your repository
  • txn is the transaction ID that is taking place prior to the Commit.
After the Commit, the Transaction ID becomes a Revision, but prior to the Commit the Revision is a Transaction ID. It is important to understand what is going on here.
def main(repos, txn):
log_cmd = '%s log -t %s %s' % (SVNLOOK, txn, repos)
log_msg = os.popen(log_cmd, 'r').readline().rstrip('\n')
Two properties are being defined, log_cmd and log_msg. In log_cmd, %s is a placeholder for the arguments in parentheses at the end of the line.
  1. SVNLOOK is hard coded in Line 21 of the file(see above).
  2. log -t is a Subversion command and switch/option for SVNLOOK.
  3. txn is the Transaction ID that is being passed into the file from the batch file.
  4. repos is the path to the reposition

log_msg = os.popen(log_cmd, 'r').readline().rstrip('\n')
This property is taking the result of log_cmd which is either the blank log message someone didn't write OR the log message they did write and if some text is entered it strips out a \n that gets put in by Subversion when the SVNLOOKcommand is run. This becomes the log_msg.

Line 27 checks the length of the log message and if it is less than 10 characters (including blank), it throws the error and exits with a 1 which means the Commit didn't happen. The Error messages are viewable in the Tortoise SVN Window. If the log message is more than 10 characters then the else is run, the code Commits because the exit was set to 0.

Lines 29 thru 34 and 37 thru 42 is test code we wrote to output variables and such to see what was happening. If you want to learn more about what is going on feel free use that code.

That's it. If you are using TortoiseSVN to initiate your SVN Commit, you will see either the Error to write a Log Message with 10 or more characters otherwise your Commit will succeed.

Comments
mini storage's Gravatar thanks.
# Posted By mini storage | 9/25/07 3:12 AM
manuel's Gravatar hi
thanks a lot for this.
It realy made my day.

cheers
manuel
# Posted By manuel | 10/4/07 9:06 AM
pete's Gravatar Thank for article about Writing Subversion Hooks on Windows with Python.

-----------------------------------------------------------

http://www.dir-9.com
# Posted By pete | 11/22/07 7:07 PM
Vu Vuong Duy's Gravatar Please, can you share all hook code on window for me ? Thanks
# Posted By Vu Vuong Duy | 1/6/08 2:53 AM
Jim Pickering's Gravatar I don't know which code you are wanting specifically. Download the .zip file in the blog entry to see all of the code for the example.
# Posted By Jim Pickering | 1/6/08 11:40 AM
Vu Vuong Duy's Gravatar I need file pre-lock.bat to run on windows. can You share it for me . Thanks
# Posted By Vu Vuong Duy | 1/6/08 9:46 PM
Vu Vuong Duy's Gravatar I have been modify pre-lock.tmpl to pre-lock.bat on windows.But It's fail :
Error: 'pre-lock' hook failed with error output:
Error: 'C:\Program' is not recognized as an internal or external command,
Error: operable program or batch file.
Error: 'SVNLOOK' is not recognized as an internal or external command,
Error: operable program or batch file.
Error: 'GREP' is not recognized as an internal or external command,
Error: operable program or batch file.
Error: 'LOCK_OWNER' is not recognized as an internal or external command,
Error: operable program or batch file.
Error: ''' is not recognized as an internal or external command,
Error: operable program or batch file.
Can you help me !!!!!
# Posted By Vu Vuong Duy | 1/7/08 2:42 AM
André Duarte's Gravatar Just what I was looking for. Thanks!!!
# Posted By André Duarte | 7/30/08 2:10 PM
Copyright ©2007 JimPickering.com. Some rights reserved. BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.