Saturday, May 14, 2011

SVN Branch Copy

I was recently in the position of needing a particular SVN branch copied including history. However I didn't have administrator access on the SVN machine, and using the SVNSYNC command was going to copy all eighteen thousand revisions, mine were about fifty scattered within the last thousand. That was less than ideal.

I devised a way to do it though, and in a few hours came up with a handy script (yeah yeah, a few hours isn't exactly a one hour hack, but downloading the SVN branch you want should be).


Essentially the script does this:
  1. INIT a new repo at the desired location.
  2. Check out the most current branch of the old repo.
  3. Check the history of the old repo to check which revisions to sync (the changed ones).
  4. For each changed one, check it out, rsync it to the checked out new repo, and commit it to the new repo with the old log message.
  5. Finish some time later after you have made yourself a cup of tea and watched the most recent Doctor Who.

#!/bin/bash

# Check for proper args
if [ -z "$1" ];
then
echo -e "Usage:\n$0 URL_TO_COPY_FROM URL_TO_COPY_TO" && exit 1
fi;

SVNFROM=$1
SVNTO=$2

echo "Fetching branch from: $SVNFROM"
echo "Copying branch to: $SVNTO"

# Set up environment.
if [ -e tempsvn ];
then
rm -rf tempsvn
fi;

mkdir tempsvn tempsvn/download tempsvn/upload tempsvn/current
cd tempsvn

echo "Checking out current..."
svn co $SVNFROM current
HISTORY=`svn log current | grep \| | cut -d\ -f1 | sed 's/r\([0-9]*\).*/\1/' | sort -k1,1n`

# Init the new repo at the given location.
svn import upload $SVNTO -m ""
svn co $SVNTO upload

num=`echo $HISTORY | wc -w`
echo "There are $num revisions in this branch."


for REVNO in $HISTORY; do
rm -rf download
echo "-----------------------------------------------------------------------"
echo "Revision: $REVNO"
echo "Fetching..."
ENTRIES=`svn co $SVNFROM@$REVNO download`
CHANGES=`echo $ENTRIES | wc -l`
echo "Found $CHANGES change(s)."

echo "Change Log:"
cd download
LOG=`svn log -r $REVNO | grep \- -v`
echo $LOG
echo ""
cd ..

echo "Exporting..."
rsync -a --exclude='.svn' download/ upload/

cd upload

IFS_BAK=$IFS
IFS=$'\n'
for E in $ENTRIES; do
BEGIN=`echo $E | cut -d\ -f1`
END=`echo $E | cut -d\ -f5- | cut -d/ -f2-`

case "$BEGIN" in
'A') svn add -q $END ;;
'D') svn del $END ;;
esac
done
IFS=$IFS_BAK

if [ -e log.log ]; then rm log.log; fi;

echo $LOG > log.log
echo "Commiting new..."
svn commit -F log.log
cd ..
done
# Tear down environment.
cd ..
rm -rf tempsvn

One slight problem though, it removes and re-checks out the branch it is copying from every time because I was getting strange errors about branches being out of date, if anyone could fix that, it would increase the speed greatly.

No comments:

Post a Comment