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