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…