using python to access subversion repositories

I’m experimenting with a simple source code browser for jerakeen.org. Right now it’s trivial – just a list of folders and links to files, but what I’m aiming for is pages showing the check-in history of various folders, when they were last changed, etc – essentially, the sort of boring stuff I’d get for free were I to use svnweb or trac or something.

As usual, though, that’s not the point. I’d hate to have a web site that consisted of several different apps, written in different languages, needing hundreds of different apache modules, and all looking different – or needing different templates if I wanted to give them similar appearances. I’m not very good at design and building templates, so as a crazy insane developer, it’s easier for me to write a subversion browser than it would be to bully trac into looking the way I want it.

So, the pysvn bindings – Python bindings to the subversion client library. They’re lovely.

import pysvn
client = pysvn.Client()
projects = client.ls("https://jerakeen.org/svn/tomi/Projects")
for project in projects:
    print " * %s"%project.name

The logic behind the pages under /source isn’t much more complex than that. There’s no caching, I don’t have to have a local checkout, and it’s easily fast enough for a little website like this. The (fairly sparse) docs don’t make it sufficiently clear, to my mind, that you can point the client at a remote repository instead of a local checkout, but you can.

Another trick (hack) I use is providing a ‘short name’ method to the directory entry objects. I pass the objects returned from the ls call directly to the django template, but you’re not allowed to do anything clever in template space (the templates are touched by those designer people – can’t trust ‘em). To make it easier to print a human-readable name for the entries, I poke a short method into their namespace:

def short_name(self):
    offset = self.name.rfind('/') + 1
    return self.name[offset:]

PysvnDirent.short = short_name

Then the template needs a simple

<h2>files here</h2>
{% for file in files %}
  <p><a href="{{ file.name }}">{{ file.short }}</a></p>
{% endfor %}

Evil. I’m clearly still too much of a perl programmer…

Ignoring resource fork files files with subversion

If you’ve ever edited files over samba, or on a fat partition, using a mac, you’ll know that it scatters annoying ._foo.txt files all over the place when you save things. These files are the system’s way of compensating for these filesystems not supporting ‘real’ resource forks, and they’re a complete pain. I feel this pain especially when I’m trying to see what’s changed in a subversion checkout using svn st, and it produces 30 lines of ? ._foo.pl complaints.

Fortunately, subversion allows you to ignore this stuff. Edit the file ~/.subversion/config (which is created the first time you use the subversion client), and search for the ‘miscellany’ section. Uncomment the line [miscellany] if it’s not already, and also uncomment the line beginning global-ignores. This line is a list of glob patterns for files that should be ignored when doing a svn st, or svn add (if you svn add on a folder, it won’t add any backup files in the folder, for instance). Add the pattern ._* to the end of it, and your resource fork woes are over…

oops

ok, keeping your apache config files in subversion is a Good Idea. But keeping the config files that CONTROL THE SUBVERSION REPOSITORY in the SAME SUBVERSION SERVER probably isn’t.

CVS vs Subversion

Tagging things in CVS

cvs -d user@server:/root co Something
..wait..
cd Something
cvs tag Tag_Name
..wait..

Tagging things in Subversion

svn cp http://server/root/Something http://server/root/tags/Tag_Name

The svn tag returns practically instantly. I’m still waiting for the CVS tag to finish. Of course, it’s all software. But svn sucks slightly less.