Home / Subversion Command Line Script to export changed files V2

Subversion Command Line Script to export changed files V2

I recently posted a Subversion Command Line Script to export changed files and in response to a comment on that page have posted a new version here, which writes out the current revision number to a file and only exports from that revision when the script is run again.

The BASH script

As with my previous post, I’m not really going to bother explaining how the script works; there’s some inline comments and if you don’t understand shell scripting or using SVN from the command line then this probably isn’t for you anyway 🙂

Just one quick note: the script writes out the current revision number to a file at the export directory called .revision If you want to call it something else or store it somewhere else then modify the script to suit.

#!/bin/bash

if [ ! $1 ] || [ ! $2 ]; then
    echo "Please enter an SVN repository, target directory and optionally a revision from"
    exit
fi

# set up nice names for the incoming parameters to make the script more readable
repository=$1
target_directory=$2
revision_from=$3

# if revision_from is not already set, get it from the .revision file if it exists
if [ ! $revision_from ] && [ -f $target_directory/.revision ]; then
    revision_from=`cat $target_directory/.revision`
fi

# now either get it from a specific revision, or everything
if [ $revision_from ]; then

    # the grep is needed so we only get added/modified files and not the deleted ones or anything else
    # if it's a modified directory it's " M" so won't show with this command (good)
    # if it's an added directory it's still "A" so will show with this command (not so good)

    for line in `svn diff --summarize -r$revision_from:HEAD $repository | grep "^[AM]"`
    do
        # each line in the above command in the for loop is split into two:
        # 1) the status line (containing A, M, AM, D etc)
        # 2) the full repository and filename string
        # so only export the file when it's not the status line
        if [ $line != "A" ] && [ $line != "AM" ] && [ $line != "M" ]; then
            # use sed to remove the repository from the full repo and filename
            filename=`echo "$line" |sed "s|$repository||g"`
            # don't export if it's a directory we've already created
            if [ ! -d $target_directory$filename ]; then
                directory=`dirname $filename`
                mkdir -p $target_directory$directory
                svn export $line $target_directory$filename
            fi
        fi
    done

    # to summarize any deleted files or directories at the end of the script uncomment the following line
    #svn diff --summarize -r$revision_from:HEAD $repository | grep "^[D]"

else

    svn export --force $repository $target_directory

fi

# get the current revision and write to .revision file
echo `svn info $repository | grep ^Revision | sed 's/Revision: *//'` > $target_directory/.revision

Usage

Save the above script as a file and change the permissions so it’s executable. Then run it like so, where I’ve saved it as svn-export:

./svn-export repository target-directory [optionally revision-from]

where repository and target-directory are the full URL to the SVN repository and local target directory to export the files to. There is a 3rd optional parameter to explicitly set a revision from which will override whatever is in the .revision file.

For example, to export changes from the repository svn://localhost/myrepository to /my/path do this:

./svn-export svn://localhost/myrepository /my/path

If the directory /my/path does not exist or the .revision file does not exist, the whole current HEAD will be exported. When .revision does exist it will export from the revision number it was the last time the command was run.

Note that the script does not delete files or directories. Uncomment the line under "# to summarize any deleted files or directories at the end of the script uncomment the following line" to show the files and directories that have been deleted between revisions.