Promoting a Subversion Path to Standalone Repository

One of my jobs today required creating a Subversion repository out of a subset of a larger repository. There are many reasons why this might be useful. In my case, it was to prepare a clean repository for conversion to another version control system. The original repository contained useful checkins in one particular directory, and useless checkins elsewhere. Since a quick Googling doesn’t bring up anything useful, I figured I’d document what I did. Most of this information can be found scattered through The Subversion Book, provided you know where to look.

We’ll suppose that ORIG is a directory containing the original repository, and
NEW is the smaller repository containing only the directory DESIRED/DIR from the original repository. The goal is to have the repository NEW contain only the portion of the repository originally under (not including) DESIRED/DIR/.

Step 1 is to dump the original repository, preserving only the desired commits. This results in a dump file called NEW.svnrepo:

svnadmin dump ORIG | svndumpfilter include DESIRED/DIR --drop-empty-revs --renumber-revs > NEW.svnrepo

Step 2 is to back up the dump file in case the editing in step 3 goes wrong:

cp NEW.svnrepo NEW.svnrepo.copy

Step 3 is to edit the NEW.svnrepo file. This is the tricky step!
You should see something like this at the start of the dumpfile:

PROPS-END

Node-path: calc
Node-action: add
Node-kind: dir
Content-length: 0

PROPS-END

You want to delete the part in bold red font.
See also the section from the Subversion Book about repository filtering.

But you’re not done yet! You also want to remove the DESIRED/DIR/ prefix when it appears after Node-path: or Node-copyfrom-path:. What you do NOT want to do is a simple search and replace, because this will corrupt any files that contain that path, and corrupted files cause the repository import script to abort.

A sequence of vim substitution lines like the following should do the trick. The first two handle references to children of the desired directory. The last one handles property changes made on the desired directory itself.

:%s/Node-path: DESIRED\/DIR\//Node-path: /
:%s/Node-copyfrom-path: DESIRED\/DIR\//Node-copyfrom-path: /
:%s/Node-path: DESIRED\/DIR/Node-path: /

Step 4 is to create a new, empty repository:

svnadmin create NEW

Step 5 is to load the new repository from your edited dump file:

svnadmin load NEW < NEW.svnrepo

Step 6 is to import the repository from svn to bzr, using one of:

  • bzr svn-import NEW bzr-NEW
  • bzr2svn.py NEW.svnrepo bzr-NEW

Step 7 is to remove the dump files:

rm NEW.svnrepo*

In my particular case, getting the new repository was a means to an end. Since I was moving to Bazaar, using specialized conversion tools was an option. My findings:

  • svnadmin verify on the new repository from above works.
  • bzr svn-import on the new repository fails on Windows with shiny new bzr (1.12) and bzr-svn (0.5.2)
  • bzr svn-import on the new repository works on Ubuntu with old and rusty bzr (1.6.1) and bzr-svn (0.4.13)
  • bzr2svn on the new repository fails on Fedora with even older bzr (1.3.1)
  • bzr2svn on the ORIGINAL repository works on Fedora with even older bzr (1.3.1)

There’s not much rhyme or reason to what works and what doesn’t, so far as I can tell. With 20/20 hindsight, the easiest thing to do would have been to use bzr2svn on Linux from the get-go, and avoid svn-import on Windows. bzr2svn is especially nice because it has a --prefix option to import only a portion of a repository. That eliminates the need to muck around with svnadmin and svndumpfilter in the first place.

But what’s done is done, and my pain is your gain!

Advertisements

3 thoughts on “Promoting a Subversion Path to Standalone Repository

  1. I have the “desired directory” to be removed (denoted as DIR) as part of some mergeinfo. I’ve tried removing the DIR/ prefix along with everything else suggested in this article. My dumpfile ended up corrupt, even though I used a hex editor and was careful about what I removed. Do you think it has anything to do with the mergeinfo section?

    (I tried vim but it’s still too slow with my 5GB+ dumpfile. I also tried to load the “largefile” module but could not get past loading the vimball. Hex Fiend opens the file instantly on Mac OS X).

    PROPS-END
    
    
    Node-path: DIR/trunk
    Node-action: add
    Node-kind: dir
    Prop-content-length: 89
    Content-length: 89
    
    K 10
    svn:ignore
    V 6
    build
    
    K 13
    svn:mergeinfo
    V 27
    /DIR/branches/v2:1444-1635
    PROPS-END
    
  2. HZC: Hmm, good question! My original repository didn’t contain any merges. At this point I no longer remember what the reason was for removing the last props entry. Best of luck figuring it out, though!

    If you want to remove a directory (rather than isolate it), one thing you might try doing would be to copy the original repository, make a new commit that removes the bad directory, and use that copy as the source of the svndump. Something to try, at least.

  3. If you don’t feel like dumping the entire repo you can do something like this instead:

    #!/bin/bash

    project=$1
    rm -fr $project*
    svn log file:///repo $project | grep -e “.*r[0-9].*|.*” | awk ‘{ print substr($1,2) }’ | sort -g | while read rev; do svnadmin dump /root/svn-copy/wp-plugins -r $rev –incremental –quiet >> $project.bak; done

    perl -pi -e “s/Node-path: $project\//Node-path: /;” $project.bak
    perl -pi -e “s/Node-copyfrom-path: $project\//Node-copyfrom-path: /;” $project.bak
    sed -i ‘/Node-path: addthis/,/PROPS-END/d’ $project.bak

    svnadmin create $project
    svnadmin load –ignore-uuid $project < $project.bak
    svnadmin setuuid $project

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s