Writing a Plugin for Bazaar DVCS

In setting up this blog using Pelican, one of the ideas I had been toying with was storing the blog in version control. My personal preference when it comes to version control is Bazaar.

Setting up Bazaar Hosting

Bazaar is not as widespread as other DVCSes, and so it has limited third party hosting. In particular, there's nowhere for personal, private hosting. For me, however, this is not a problem as I have my own server where I can do my own hosting. And in order to set up Bazaar hosting you just install the command line bzr application on your server.

Once you've installed bzr on your server, all you need to do it start using it is push your code up via SSH using the following URL:

$ bzr push bzr+ssh://bzr.example.com/home/user/repo

This is a bit of a long-winded URL though, and not that easy to remember. On the other hand, Launchpad seems to have their own "protocol" in Bazaar. I figured that if Launchpad can have their own protocol, then so can I.

Directory Structure and Shared Repositories

On my server I prepped my repositories by adding shared repositories and any subdirectories I needed. So I ended up with the following:

/home/raoul/Projects/ChristianOSS/blog

The ChristianOSS directory is a Bazaar shared repository so that if I want to create more branches, I can share the history between all of the branches. This means that in general my pushes and pulls will be shorter because most of the information is shared between the branches.

The blog directory is where my blog actually lives.

Writing the Plugin

I scratched around inside the Launchpad plugin for Bazaar, and tried to look in the Bazaar documentation for more on how to achieve what I wanted, but it wasn't until I came across another plugin that I figured out what I needed to do.

Sadly, that other plugin doesn't seem to work, so I had to write my own (I don't know enough about bzr's internals to fix the other plugin). This was not a big problem because I had very little to actually do.

At the end of the day, your plugin has to register a new directory service, and then tell Bazaar which class is going to process that directory service and return a proper URL. This means that your plugin needs to be a directory with an __init__.py file and another file which contains your directory service handler class.

Plugin Implementation

Your __init__.py file registers the directory service.

"""
ChristianOSS integration plugin for Bazaar.
"""

from bzrlib.directory_service import directories

def _register_directory():
    directories.register_lazy('ch:', 'bzrlib.plugins.christianoss.ch_directory',
                            'ChristianOSSDirectory',
                            'ChristianOSS directory service',)

_register_directory()

And your other file (which I've called ch_directory.py) contains the class to handle the directory service.

from bzrlib import transport

# As bzrlib.transport.remote may not be loaded yet, make sure bzr+ssh
# is counted as a netloc protocol.
transport.register_urlparse_netloc_protocol('bzr+ssh')
transport.register_urlparse_netloc_protocol('ch')

class ChristianOSSDirectory(object):

    def look_up(self, name, url):
        """
        Convert a ch: style URL to a real one
        """
        return 'bzr+ssh://bzr.example.com/home/raoul/Projects/' + url[3:]

The directory service class contains a method called "look_up" which takes two parameters, the name and the url. You take the URL and convert it into a real URL and then return the real URL to Bazaar.

Installing and Using the Plugin

To install the plugin, simply drop the whole directory into ~/.bazaar/plugins (create it if it doesn't exist) and Bazaar will pick it up normally.

To use it, instead of using your log bzr+ssh URL mentioned earlier, use your new shortcut:

$ bzr branch ch:ChristianOSS/blog

[ Image Credit: Osh Bazaar Bishkek, Kyrgyzstan by Thomas Depenbusch ]


Comments

comments powered by Disqus