Question

I want my SVN server execute a specific command mycommand whenever a commit to an SVN subdirectory svn-rep/myfolder is done.

How would I do that? I know that there is the hook directory with preinstalled hooks. But how would I make a custom hook from that? How does SVN know when to call which hook - is it based on the file names? And how would I restrict the hook to be executed only if a commit changes some files in svn-rep/myfolder?

Just to be clear: The command never changes, it just references another script that is located somewhere on the server.

EDIT: I just implemented post-commit and for testing purposes it should append the revision number of an SVN directory to an already existing (and for everybody writeable):

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
from subprocess import Popen, PIPE

dirRevisionCmd  = 'svn info /var/www/main | grep -i "Letzte geänderte Rev"

process = Popen(headRevisionCmd, shell=True, stdout=PIPE, stderr=PIPE)
out, err = process.communicate()

with open("/var/lib/svn/rep/hooks/testfile", "a") as testfile:
    testfile.write("err:" + err.strip() + "\n")
    testfile.write("out:" + out.strip() + "\n")

This results in empty standard output after each commit:

www-data
err:
out:

If I execute post-commit by hand the 'out' lines contain some text. So why does it not work with SVN?

Was it helpful?

Solution

Inside of your Subversion repository on the server is a directory called hooks. Inside are sample hook scripts. They all end with the .tmpl suffix. They're placeholders really. Nothing more than that.

If a program or script is there called post-commit, Subversion will execute it after someone does a commit. It doesn't matter if this is an executable, Windows Batch program, or a Unix shell script. Subversion will execute it after a commit happens. It doesn't matter what the script does. It's really that simple.

What if there's already a program called post-commit? You'll have to modify it. As I said, there are no hooks in the default repository -- just a bunch of templates that you can use if you want. If there is a post-commit program, then someone must have already added it.

So, simply put your command in the hooks directory, make sure it's executable, and call it post-hook. Subversion will execute it after someone does a commit.


You never specified what this command you want to execute was, so I can't offer any further advice. However there are a few guidelines to hook scripts in general:

  1. Hook scripts should not take more than a few milliseconds to execute. When a hook script executes, it ties up the committer's machine until the hook script finishes. For example, a common question is how to do a deployment via a post-commit script. This is a bad idea because it will tie up the committer's computer for a long time. There are better ways of doing this.
  2. Hook scripts run on the server, and the commit took place on a client machine. This means:
    1. The hook script has no access to the client's environment.
    2. The hook script can't query the client.
    3. The hook script can't modify the commit.
    4. The hook script can't search the client's working directory.
      • It also means that pre-commit hooks cannot do anything except accept or reject the commit.
    5. Hook scripts should not cause a new commit. First there's a problem of the commit hook causing a commit causing itself to run again in a loop. Second of all, it makes the person who just did the commit have an out of date working directory. Plus, it means that 50% of your log history is just your commit hook babbling to itself.
  3. Finally, Hook scripts have a very simple way they do talk to the client:
    1. Hook scripts don't have access to the client's STDIN or STDOUT. In fact, hook scripts don't have access to STDIN or STDOUT.
    2. Hook scripts show success by doing an exit value of zero. They show failure by doing an exit value other than zero.
    3. If a hook exits with a non-zero value, the STDERR produced by the hook script will be sent to the client, but not to the sub process. This way, you can explain to the client why the hook script failed.

As others have said: Read the fine manual that is on line. It goes through things step by step. Create a test repository and play around with hook scripts. They're really fairly simple. You can take a look at a post-commit hook I wrote. It comes with installation directions. Maybe that will help.


Response

If I execute post-commit by hand the 'out' lines contain some text. So why does it not work with SVN?

I'v renumbered by list to make it a numeric list. Take a look at point 3.1: Hook scripts don't have access to STDOUT. I'm not a Python programmer, but it looks like you're attempting to use STDOUT to pipe the output to another process. Hook scripts eat STDOUT, and that output can't be sent to another process. Also, STDERR is captured, but not sent via a pipe. Instead, STDERR is collected and sent to the client that did the commit. This way, you can send the client a description of the error.

You can open a subprocess and send it text, but not via a pipe.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top