May 09

SVN Syncing

So I just spent a good half of the day today trying to figure out how to sync two repositories together. We’re moving repositories, and so we had to import data from one repository to the other. However, this process took a while, so once we had imported the data into the new repository it was several revisions out of date. There didn’t seem to be a way to use SVN tools to do this. So, I went and wrote a script which would take all the changes from one repo and commit them to the other one with all the data. This was needed because we didn’t have shell access to the new SVN repo, and because of how that repo has to be set-up it would be somewhat infeasible to do another SVN dump.

There are a few limitations with this; there’s no way to add new files to the repo(though you could probably do an svn add right before you commit). There’s also no way to delete any files. In our case, this is not a problem, as there have been only file modifications.

Before you do this, you must checkout both repositories into different directories.

So, without further ado, here’s the code:

#!/bin/bash

ORIG_DIR=<original directory>
NEW_DIR=<new SVN directory>
START_REV=<start revision of original SVN>
END_REV=<end revision of original SVN>
CURRENT_DIR=`pwd`

while [ $START_REV -ne $END_REV ]
do
cd $CURRENT_DIR
cd $ORIG_DIR
svn update -r "$START_REV" #update to next revision of old directry
let "START_REV += 1"

cd $CURRENT_DIR
echo "About to diff, this may take a while..."
diff -qr --exclude=".svn" $ORIG_DIR $NEW_DIR > /tmp/svn_out_orig #figure out what files changed
cat /tmp/svn_out_orig | grep Only > /tmp/svn_diff_files
cat /tmp/svn_out_orig | grep Files > /tmp/svn_out
LINES=`wc -l /tmp/svn_out | cut -d' ' -f1` #how many files changed?
cat /tmp/svn_out | cut -d' ' -f2 > /tmp/sources
cat /tmp/svn_out | cut -d' ' -f4 > /tmp/dests
echo "LINES = $LINES"
while [ $LINES -gt 0 ]
do
    SOURCE=`sed -n "$LINES"p /tmp/sources`
    DEST=`sed -n "$LINES"p /tmp/dests`
    cp $SOURCE $DEST #copy each file that changed to the new directory
    let "LINES -= 1"
done
cd $ORIG_DIR
LOG=`svn log --xml -l 1 | grep msg | sed 's/<msg>//p' | sed 's/<\/msg>//p'` #get the log message for  that commit
cd $CURRENT_DIR
cd $NEW_DIR
echo "ABOUT TO COMMIT"
svn commit -m "$LOG" #commit with message

done