Sunday, April 26, 2009

svn-upgrade on a Bazaar Loom

I maintain modifications of Trac, a Subversion project, as a Bazaar Loom. The bottom thread mirrors the 0.11-stable branch using bzr-svn, with features built purely in Bazaar revisions on top.

When I upgraded bzr-svn once, the Subversion storage format changed incompatibly, meaning I could no longer track Subversion without rebasing my Loom. Here is how I did it:

  1. Make sure the loom is fully forward-merged so that every thread's head is a parent of the top thread. Revisions you miss won't be converted correctly.

  2. Make sure you are on the top thread. svn-upgrade only converts the HEAD and its parents, so if you aren't, the conversion will miss higher threads.

  3. bzr record the loom if there are changes.

  4. Copy or branch the loom to a backup, in case you mess up.

  5. In the Loom directory, run bzr svn-upgrade --idmap-file=../myproj.idmap http://svn.edgewall.org/repos/trac/. The idmap is for your later reference so you can fix up the loom head references, and you can choose where you want to save it. Unless you have parent_location set in .bzr/branch/branch.conf to the actual Subversion branch, you must specify the URL to the repository. This should be some parent directory of the Subversion branch URL, and is usually the one that contains the branches, tags, and trunk subdirectories.

  6. That should spend a bunch of time accessing the network.

  7. Now you need to fix up the .bzr/branch/last-loom file. This is a plain text file, and opening it you'll immediately see why we saved an idmap.

    The first line is very obviously the Loom file format, which should be "Loom current 1". The second points to the recorded loom, which you can leave alone, because we'll just be fixing where the threads point.

    Each line following is info about a thread, bottom-thread-first (completely counterintuitively, but there you are). The last revision at time of loom-record comes before " : ", the current revision after, and of course the thread name.

    Note that the top (bottom-of-file) thread is a little different. Unlike every other line, the revision ID after " : " is slightly different from the one before. That's because svn-upgrade successfully communicated to loom that the HEAD revision is now the rebased one. It should give you a hint as to how to fix the others.


  8. Looking at the idmap file, you'll quickly see a pattern. Revisions that come from Subversion have their prefixes changed, from "svn-v3-trunk0:" to "svn-v4:", and "%2F" changed to "/" in my case. Non-Subversion revisions simply have "-svn4-upgrade" appended. The whole point is for the svn-upgrade to be trivially repeatable by multiple branch owners, so either memorize the pattern, or keep this file handy.

  9. Back in last-loom, change the revids after the " : " according to the map. If your loom is like mine, with a Subversion revision as the basis and the rest in pure Bazaar, this means changing "svn-v3-trunk0" to "svn-v4" and any instances of "%2F" to "/" for the bottom thread (first in last-loom file), and adding the "-svn4-upgrade" to the rest. Do not change the revid before the " : ". Do not change line 2. Do not change the last line, because it was fixed already.

  10. Move down through the loom looking for failures of bzr log --show-ids -l1, which should print out the revids you just wrote into the loom. If there are failures, you probably messed up a replacement revision; check your idmap file again.

  11. Once you've verified everything, move back to the top thread with bzr switch and record the loom.


What about inter-Loom activity?


The whole point of repeatability in svn-upgrade is to allow independent upgrades to be shared between. So if you have people with divergent looms, simply using svn-upgrade on all of them will make the threads compatible.

This says nothing about whole-loom merging, though. Loom-recording, even between two equal looms, will create divergent loom records. I've never tried loom merging, so you may have to rough it by doing thread-only merging until everyone is synced up again.