Home » Best strategy to write hooks for subversion in Windows [closed]

Best strategy to write hooks for subversion in Windows [closed]


I’ve just spent several days procrastinating about exactly this question. There are third party products available and plenty of PERL and Python scripts but I wanted something simple and a language I was familiar with so ended up just writing hooks in a C# console app. It’s very straight forward:

public void Main(string[] args)
  string repositories = args[0];
  string transaction = args[1];

  var processStartInfo = new ProcessStartInfo
                             FileName = "svnlook.exe",
                             UseShellExecute = false,
                             CreateNoWindow = true,
                             RedirectStandardOutput = true,
                             RedirectStandardError = true,
                             Arguments = String.Format("log -t "{0}" "{1}"", transaction, repositories)

  var p = Process.Start(processStartInfo);
  var s = p.StandardOutput.ReadToEnd();

  if (s == string.Empty)
    Console.Error.WriteLine("Message must be provided");


You can then invoke this on pre commit by adding a pre-commit.cmd file to the hooks folder of the repo with the following line:

[path]PreCommit.exe %1 %2

You may consider this overkill but ultimately it’s only a few minutes of coding. What’s more, you get the advantage of the .NET language suite which IMHO is far preferable to the alternatives. I’ll expand my hooks out significantly and write appropriate tests against them as well – bit hard to do this with a DOS batch file!

BTW, the code has been adapted from this post.

We’ve got complex requirements like:

  1. Only certain users can create folders in parts of the SVN tree, but everyone can edit files there
  2. Certain file extensions cannot contain certain text in the file
  3. Certain file extensions can only be stored in a subset of directories
  4. As well as several simpler ones like, Must have a commit comment
  5. Regression testable by running new hook against all previous SVN commits

#5 is huge for us, there’s no better way to know you’re not gonna break commits moving forward than to be able to push all previous commits through your new hook. Making the hook understand that 1234 was a revision and 1234-1 was a transaction and making the appropriate argument changes when calling svnlook, etc. was the best decision we made during the process.

For us the nut got big enough that a fully unit testable, regression testable, C# console exe made the most sense. We have config files that feed the directory restrictions, parse the existing httpd_authz file to get “privileged” users, etc. Had we not been running on Windows with a .NET development work force, I would have probably written it all in Python, but since others might need to support it in the future I went .NET over .BAT, .VBS, Powershell silliness.

Personally I think Powershell is different enough from .NET to be mostly useless as a “scripting” language. It’s good if the only cmd line support for a product comes via PS (Exchange, Windows 2k8), etc. but if all you want to do is parse some text or access regular .NET objects PS just adds a crazy syntax and stupid Security Iron Curtain to what could be a quick and easy little .NET app.

Check CaptainHook, “a simple plugin framework for writing Subversion hooks using .NET”.

Related Solutions

Is a composite index also good for queries on the first field?

It certainly is. We discussed that in great detail under this related question: Working of indexes in PostgreSQL Space is allocated in multiples of MAXALIGN, which is typically 8 bytes on a 64-bit OS or (much less common) 4 bytes on a 32-bit OS. If you are not...

Explaining computational complexity theory

Hoooo, doctoral comp flashback. Okay, here goes. We start with the idea of a decision problem, a problem for which an algorithm can always answer "yes" or "no." We also need the idea of two models of computer (Turing machine, really): deterministic and...

Building a multi-level menu for umbraco

First off, no need pass the a parent parameter around. The context will transport this information. Here is the XSL stylesheet that should solve your problem: <!-- update this variable on how deep your menu should be --> <xsl:variable...

How to generate a random string?

My favorite way to do it is by using /dev/urandom together with tr to delete unwanted characters. For instance, to get only digits and letters: tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo '' Alternatively, to include more characters from the OWASP...

How to copy a file from a remote server to a local machine?

The syntax for scp is: If you are on the computer from which you want to send file to a remote computer: scp /file/to/send username@remote:/where/to/put Here the remote can be a FQDN or an IP address. On the other hand if you are on the computer wanting to...

What is the difference between curl and wget?

The main differences are: wget's major strong side compared to curl is its ability to download recursively. wget is command line only. There's no lib or anything, but curl's features are powered by libcurl. curl supports FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP,...

Using ‘sed’ to find and replace [duplicate]

sed is the stream editor, in that you can use | (pipe) to send standard streams (STDIN and STDOUT specifically) through sed and alter them programmatically on the fly, making it a handy tool in the Unix philosophy tradition; but can edit files directly, too,...

How do I loop through only directories in bash?

You can specify a slash at the end to match only directories: for d in */ ; do echo "$d" done If you want to exclude symlinks, use a test to continue the loop if the current entry is a link. You need to remove the trailing slash from the name in order for -L to...

How to clear journalctl

The self maintenance method is to vacuum the logs by size or time. Retain only the past two days: journalctl --vacuum-time=2d Retain only the past 500 MB: journalctl --vacuum-size=500M man journalctl for more information. You don't typically clear the journal...

How can I run a command which will survive terminal close?

One of the following 2 should work: $ nohup redshift & or $ redshift & $ disown See the following for a bit more information on how this works: man nohup help disown Difference between nohup, disown and & (be sure to read the comments too) If your...

Get exit status of process that’s piped to another

bash and zsh have an array variable that holds the exit status of each element (command) of the last pipeline executed by the shell. If you are using bash, the array is called PIPESTATUS (case matters!) and the array indicies start at zero: $ false | true $...

Execute vs Read bit. How do directory permissions in Linux work?

When applying permissions to directories on Linux, the permission bits have different meanings than on regular files. The read bit (r) allows the affected user to list the files within the directory The write bit (w) allows the affected user to create, rename,...

What are the pros and cons of Vim and Emacs? [closed]

I use both, although if I had to choose one, I know which one I would pick. Still, I'll try to make an objective comparison on a few issues. Available everywhere? If you're a professional system administrator who works with Unix systems, or a power user on...

How do I use pushd and popd commands?

pushd, popd, and dirs are shell builtins which allow you manipulate the directory stack. This can be used to change directories but return to the directory from which you came. For example start up with the following directories: $ pwd /home/saml/somedir $ ls...

How to forward X over SSH to run graphics applications remotely?

X11 forwarding needs to be enabled on both the client side and the server side. On the client side, the -X (capital X) option to ssh enables X11 forwarding, and you can make this the default (for all connections or for a specific connection) with ForwardX11 yes...

What does “LC_ALL=C” do?

LC_ALL is the environment variable that overrides all the other localisation settings (except $LANGUAGE under some circumstances). Different aspects of localisations (like the thousand separator or decimal point character, character set, sorting order, month,...

What is a bind mount?

What is a bind mount? A bind mount is an alternate view of a directory tree. Classically, mounting creates a view of a storage device as a directory tree. A bind mount instead takes an existing directory tree and replicates it under a different point. The...