Daily SVN Incremental Backup
Lately I’ve had a lot of repositories to deal with, so I wanted to back it up, beside doing the usual, creating a hotcopy I decided to create incremental backups of all the repositories, so we can restore them even if for some reason the hotcopy fails or the repository get’s corrupted, both of them the master and the hotcopy.
So I need to do this on windows, and on linux (ubuntu), but this should work on all the distributions of linux, provided you have the required programs installed, this is mostly for Cygwin, because usually the tools required come pre-installed on the distributions, and you also have to have installed Subversion and have it in your path.
#!/bin/bash
SCRIPT_NAME=`basename $0`
function help() {
echo echo "Incremental dumping for SVN by Ilija Matoski (ilijamt@gmail.com)" echo "No command arguments detected, there need to be as following." echo "Usage: ${SCRIPT_NAME} <path_to_repo> <path_to_dump> <identifier>" echo echo "Parameters:" echo " <path_to_repo> - Where is the repository located" echo " <path_to_dump> - Where should we dump the repository" echo " <identifier> - Used to record the last recorded dump, always stored in the file with the" echo " dumps from the repo, so we can keep a track of where we at with dumping," echo " also identifier is used to generate the dumps names." echo " <compress> - compress the output dump (default: false)" echo echo "Examples:" echo " ${SCRIPT_NAME} test /backup/SVN/test test" echo " ${SCRIPT_NAME} test /backup/SVN/test test true" echo
exit -1
}
if [ ! $# -ge 3 ]; then helpfi
PATH_TO_REPO=$1PATH_TO_DUMP=$2IDENTIFIER=$3COMPRESS=$4
# Check if they are empty and if they are quitif [[ -z "$PATH_TO_REPO" || -z "$PATH_TO_DUMP" || -z "$IDENTIFIER" ]]; then helpfi
if [ "$COMPRESS" == "true" ]; then COMPRESS="true"else COMPRESS="false"fi
# Check if the repo path exists, and if it's a valid SVN repositoryif [ ! -d "$PATH_TO_REPO" ]; then echo "Directory ${PATH_TO_REPO} doesn't exist." echo "Exiting." exit -1fi
# Check if SVN folder is valid, check for format file in the directoryif [ ! -f "${PATH_TO_REPO}/format" ]; then echo "Probably not a valid SVN repository." echo "Exiting." exit -1else echo "Probably a valid SVN repository detected. Continuing."fi
# Check if destination exist and if we have writing permissions# and if it doesn't then create itif [ ! -d "$PATH_TO_DUMP" ]; then echo "Dump directory doesn't exist, creating a new directory: $PATH_TO_DUMP" mkdir -p "$PATH_TO_DUMP"fi
# Check if the directory has writing permissionsif [ ! -w "$PATH_TO_DUMP" ]; then echo "No writing permissions." echo "Exiting." exit -1fi
# Get the full paths if we have relative paths in the command linePATH_TO_REPO=`cd $PATH_TO_REPO; pwd`PATH_TO_DUMP=`cd $PATH_TO_DUMP; pwd`IDENTIFIER_PATH="$PATH_TO_DUMP/$IDENTIFIER"DUMP_FILE_MASK="$IDENTIFIER_PATH"# Check if the identifier existsif [ ! -f "$IDENTIFIER_PATH" ]; then # Doesn't exist, so we create it and set it to revision 0 echo "-1" > "$IDENTIFIER_PATH"fi
CYGWIN=`uname -o`
# Check if we are running cygwin, for windowsif [ "$CYGWIN" == "Cygwin" ]; then CYGWIN="true"else CYGWIN="false"fi
# Set up some stuff for cygwinif [ "$CYGWIN" == "true" ]; then repoDrive="${PATH_TO_REPO:10:1}" REPO_URL=`echo $PATH_TO_REPO | sed "s/\/cygdrive\/${repoDrive}/${repoDrive}:/g"` REPO_DIR="$REPO_URL" REPO_URL="file:///${REPO_URL}"else REPO_URL="file:///$PATH_TO_REPO" REPO_DIR="$PATH_TO_REPO"fi
# Get the last revision from the directory repositoryREPO_LAST_REVISION=`svn info $REPO_URL | grep "^Revision: " | sed "s/Revision: //g"`REPO_DUMPED_REVISION=`cat "$PATH_TO_DUMP/$IDENTIFIER"`
# check if the call succededif [[ $REPO_LAST_REVISION != [0-9]* ]]; then echo "Cannot fetch information from SVN repository" exit -1fi
# Increment it by one number from the last revision# so we don't re dump the last one againREPO_DUMPED_REVISION=$(($REPO_DUMPED_REVISION+1))
echo "Settings"echo " Compress: ${COMPRESS}"echo " Directory: ${REPO_URL}"echo " Dump: ${PATH_TO_DUMP}"echo " Identifier: ${IDENTIFIER}"echo " Cygwin: ${CYGWIN}"echoecho "Repository"echo " Revisions: ${REPO_LAST_REVISION}"echo " Dumping from: ${REPO_DUMPED_REVISION}"echo
if [ $REPO_DUMPED_REVISION -gt $REPO_LAST_REVISION ]; then echo "ERROR: Dumped revision bigger than the revision in the repository" echo "Exiting." exit -1fi
echo "Starting to dump"
list=$(seq "$REPO_DUMPED_REVISION" 1 "$REPO_LAST_REVISION" )
for rev in $listdo
padding_rev=`printf "%08d" $rev` dump_file="$DUMP_FILE_MASK.rev.$padding_rev.svndump"
if [ "$COMPRESS" == "true" ]; then dump_file="${dump_file}.gz" fi
echo " Dumping revision $rev of $REPO_LAST_REVISION"
if [ "$COMPRESS" == "true" ]; then svnadmin dump "$REPO_DIR" --revision "$rev:$rev" --incremental --deltas -q | gzip > $dump_file else svnadmin dump "$REPO_DIR" --revision "$rev:$rev" --incremental --deltas -q > $dump_file fi
# put the new dumped revision in the file echo $rev > "$IDENTIFIER_PATH"
done
echo "Done."It’s really easy to use this to create a incremental backup of your SVN repository. If you need help just write, without any arguments:
./incremental_backup.shAnd it will show you the help/usage screen.