farmdev

Try out the Mercurial Subversion extension (hg svn) on Mac OS X

As a Subversion user, I am hesitant to get excited about distributed version control systems (DVCS). What I like about Subversion is that there is a central line of development. This is great for teams because it forces them to integrate their code often. This is great for open source projects because the users have one place to go to get the source; there is one version of the truth.

However, I usually hack on code during my train commute to work and one thing Subversion does not [yet] do is let you commit offline. This is all I want and this is what a DVCS can provide. Everything else is nice to have. It's nice to have an experimental work space where I can create private branches all day and all night but you can do this in Subversion too. Experimental work branches are dangerous if they do not get integrated with mainline development often. Using a DVCS makes it easier to be lazy about integration.

DCVS lets you maintain mirrors of projects, potentially with your own patches to the project. While this is convenient, I also put this in the dangerous category because the last thing I want is for someone to say, yeah my Django patch wasn't accepted and probably never will be, so just use my clone of the repository! This is an integration nightmare.

Anyway, Subversion is a long way from supporting offline commits so I've been experimenting with Mercurial. This was instigated by the work a colleague of mine, Augie Fackler, is doing on the hg subversion extension. It allows you to drive a Subversion repository from Mercurial. You clone the repository locally and work within it as a Mercurial repository. You can commit and branch all you want. When you are ready, you push your changes back up to the central Subversion server.

Try it out! It is in very early development so the best feedback will be from users who are trying to do real work.

Since it took a bit of monkey work to get it working on Mac OS X, here are my notes.

UPDATE: Since I wrote this, things got a bit easier. You don't need a dev version of Mercurial and the easiest way to do everything is just through ports:

$ sudo port install mercurial
$ sudo port install subversion-python25bindings

Then you can skip all the way down to the section about Activating hgsubversion.

Buidling From Source

(See above, you probably don't need to do this.)

I prefer the official Framework build of Python and I had used easy_install Mercurial to get my hg command. To use hg subversion, you have to build the Subversion bindings and a ton of crap and you have to use the development version of hg. The README file in hg subversion has more general instructions and there are also some useful instructions here. Even though I use the Framework build of Python, the path of least resistance for me was to let macports do all the compiling:

sudo port install xmlto asciidoc subversion subversion-python25bindings \
    py25-zlib py25-bz2 py25-hashlib

This will install loads of stuff, including python2.4 (for asciidoc), and python2.5. If you had subversion 1.4 installed from ports you will need to deactivate that before installing the 1.5 port.

The macport Pythons will not conflict with the Framework build as long as you don't run python_select like it tells you to. Don't do that. Next, I double checked that everything went smoothly. Note that I had to set the PYTHONPATH for subversion bindings.

$ export PYTHONPATH=/opt/local/lib/svn-python2.5/
$ /opt/local/bin/python2.5 -c "import svn.core; print svn.core.SVN_VER_MINOR"
5

Next, I cloned the hg dev repository (I used crew) and moved my 1.0.2 version of hg out of the way:

$ sudo mv /Library/Frameworks/Python.framework/Versions/2.5/bin/hg \
    /Library/Frameworks/Python.framework/Versions/2.5/bin/hg1.0

Note that if you had used easy_install then this will continue to work since it's a script that loads a specific egg. Next I went into the hg source and edited the Makefile, changing the vars at the top so that they pointed to my macport python install (I got prefix by running /opt/local/bin/python2.5 -c "import sys; print sys.prefix"):

PREFIX=/opt/local/Library/Frameworks/Python.framework/Versions/2.5
export PREFIX
PYTHON=/opt/local/bin/python2.5

Built it:

make local && make tests

... and waited a lonnnnnng time, wondering how often the hg developers actually run the entire test suite.

I got two errors, one with test-hgweb and one relating to bz2 archival. Ah, well, living dangerously I continued.

sudo make install

Activating hgsubversion

Next, I cloned hg subversion and ran the hg subversion tests. Note again that I had to set the PYTHONPATH for subversion bindings:


$ cd hgsubversion
$ export PYTHONPATH=/opt/local/lib/svn-python2.5/
$ /opt/local/bin/python2.5 tests/run.py

If everything passes you are good to go. I also added the svn-python2.5 path to my $PYTHONPATH in ~/.bash_profile. And added /opt/local/Library/Frameworks/Python.framework/Versions/2.5/bin (or /opt/local/bin if you install hg from ports) to my $PATH so that the new hg is available. Be careful to put this at the end of PATH if like me you prefer the official Framework.

I edited my .hgrc file per instructions on adding new extensions.


[extensions]
svn=/path/to/hgsubversion-clone
rebase=

Also added the rebase extension because that will come in handy. Next I ran:

hg help

... and saw svn listed as an extension. Woo! Now, when I figure out some good ways to accomplish my offline-commit workflow, I'll let you know ;)