Merge SVN directories

One of the applications of my customer in being maintained by an external vendor. The vendor delivers code to a separated SVN repository, by importing it every time as a new tag. This causes a few difficulties:

  • SVN is not able to report code differences between two versions
  • all available at the company tooling has to be configured to scan additional SVN repository

To resolve this problem I wrote a script, which extracts newly delivered code from “external” SVN repository and commits it as a single change to a trunk in another repository.

svn_merge.sh http://external.svn/project/tags/D2014001 http://main.svn/project/trunk

The script uses SVN CLI and has been tested with both 1.6 and 1.7 versions. The following limitations are known… and any improvement suggestions are very welcome:

  • it behaves like CVS, renaming of a file or directory is seen as deletion of the old file and adding a new one. The fact of renaming is lost to importing of the code by vendor

The script is also available inĀ Bitbucket

#!/bin/sh -e

# Extract code from source SVN URL and merges it with an existing code in target URL
# See complete description on http://jv-ration.com/2014/01/merge-svn-directories/

die () {
    local error_code="$?"
    echo >&2 "$@"
    test $error_code == 0 && exit 1;
    exit $error_code
}

usage=$"This script extracts code from source SVN URL and merges it with an existing code in target URL.\n\
Two parameters:\n\
1) source_svn_url,\n\
2) target_svn_url,\n\
\n\
$0 source_svn_url target_svn_url\n\
"

[ "$#" -ge 1 ] || die "Wrong parameters. $usage"
source_uri=$1
target_uri=$2

# Testing is svn CLI is present
svnRun=`which svn 2> /dev/null`
if [ ! $svnRun ]
then
  die "svn CLI is not found on PATH"
fi

SCRDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# 1. Export source folder
echo "Exporting source code from $source_uri"
svn export $source_uri source

# 2. Check-out target folder
echo "Checking out target code from $target_uri"
svn checkout $target_uri target

# 3. Delete all target file, but keep .svn and pom.xml
echo "Deleting targer files, keeping SVN metadata"
find target -type f -mindepth 1  \! -iwholename "*/.svn/*" \! -iwholename "*/.svn" -exec rm -f {} \;
find target -empty -mindepth 1  \! -iwholename "*/.svn/*" \! -iwholename "*/.svn" -exec rm -rf {} \;

# 4. Copy source files over target .svn
echo "Copying source over target SVN metadata"
cp -R source/* target/

# 5. Delete empty folders and folders with .svn only
find target -depth -mindepth 1 -type d \! -iwholename "*/.svn/*" \! -iwholename "*/.svn" -exec perl $SCRDIR/rm_empty_dir.pl {} \;

cd target

# 6. Add new files to SVN
added=`svn status | grep "? " | wc -l`;
echo "$added files are added"
if [ $added -gt 0 ]
then
  svn status | grep "? " | awk '{print $2}' | xargs svn add
fi

# 7. Delete missing files from SVN
deleted=`svn status | grep "! " | wc -l`;
echo "$deleted files are deleted"
if [ $deleted -gt 0 ]
then
  svn status | grep "! " | awk '{print $2}' | xargs svn delete
fi

# 8. Commit results of the merger
echo "Commiting changes back to target SVN"
svn -m "merging with code from $source_uri" commit

# End of the file

Leave a Reply

Your email address will not be published. Required fields are marked *

Please, enter correct number below to prevent spam (required)