Saturday, March 03, 2007

subversion hooks: notify

For anyone who knows me really well, no I'm not finally mentioning a club. It's a boring geeky techy post about the subversion revision control system, aka svn. We recently moved over to svn from cvs at work, and I'm loving it. In some areas it's missing a couple of features that were handy about cvs, but the overall design and implementation is much cleaner, not based on an old system that's been kludged to make it work in a multi-user environment. If you're still on cvs, seriously consider moving. There are other potential replacements round without moving to Windows, but I'm not sure how many are ready for the same level of stability yet. Plus subversion's command-line interface is almost exactly the same, except where it's been clarified and improved (eg. merging changes is done with svn merge not the update command with unusual options). It also has things like "svn switch" when you'd have been rather stuck before, or left hacking CVS/Root files in your working-copy or performing complex diff/patch commands; and easier offline working.

I was pretty much an expert on cvs, down to everything but the source code level (I've hacked repository ",v" files before to fix revisions, clearing lock files wasn't a problem back in the earlier versions of 1.9 or so when it was needed every now and then, and got to know rcs before we used cvs). So moving to svn made me feel a little like I was flying without a licence. I still don't know lots about the internals but I have an idea and I've read a tonne of stuff about it from their tech docs.

At previous companies we've used the cvs hook scripts to do things like send out email on commits, and keep an up-to-date central checkout of the modules. Svn also has a way of running scripts when things change the repository and it was becoming worthwhile to at least parse-check our files to avoid any stupid commits (yes, it's happened a couple of times and caused problems before we had a better release protocol).

So I looked into it and wrote a parse-checker for php file commits. That didn't take much, there's the rather useful svnlook command to examine the changes made. I just needed to process all the files in the list, and remember to ignore files that were being deleted, and any directory or non-content changes. Oh, it also enforced the non-empty log message rules that are disliked by subversion but not prohibited.

The next topic that came up in a casual conversation was certain developers wanting to know when files they cared about, or core parts of the system, were updated; so other related code can be checked. Of course you find out when you run svn update, but wouldn't it be nice to know the instant it happens (when it's fresh in the author's head), and not be scrolling back to the update command and checking every file you care about's log/diffs, a rather time-consuming and laborious task?

So the idea of a notify script arrived; I had a look round the web and subversion already has a contributed script for sending commit emails, but you'd quickly lose the wheat among the chaff if you saw every single commit (email filters are handy, but still).
Existing scripts all use a server-managed list of files/changes to notify on and to who, but subversion has these great things called properties that you can use to set arbitrary version-controlled properties on any file or directory; they're used to implement the equivalent of cvs's .ignore files and with revision-specific properties to store the log message and author etc.

What a great idea to use a property on each file you want to be notified on! That way it gets moved if the file is moved, can be edited by users (and any existing authentication scheme), could be checked by a pre-commit script for validity, and it already knows the file to be checked is the right file if it's a property of that file! Rather than regex match on filenames. Groups of files can be done with the same property on their common parent directory or individually.