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
