I'm splitting an SVN repository into two: project1, and common. This way, I can also make project2 which also depends on common.
project1 will contain an svn:external
link to common. I'd like people to constantly develop against the HEAD
of common, but literally pegging an svn:external
to HEAD
causes problems (e.g. tags will reference the current HEAD
instead of the HEAD
at the time of tagging). Manually pegging a static revision is annoying because if we don't update project1 for a while, then it's manager's will be more reluctant to take all of the changes from common as untested changes become a risk. That leads to forking which we want to avoid.
How can one work around this?
Run this script as a cron-job or systemd.timer from a linux server (using an account with write access to the repository).
This solves the problem where reverting to an older revision of project1 will also revert to the version of common used at that time by constantly updating the pegged svn revision.
As an added bonus, if someone updates common, all projects running this script will automatically commit an external property update which can trigger CI (using something like Jenkins). That means a commit to common will immediately be tested on all dependent projects.
#!/bin/bash
# Updates all svn externals in a remote repository
# argument 1 is the server
# argument 2 is the path to the externals directory relative to the server root
#
# Note: all externals in the repository must be relative to the server root.
# See `svn help pset`
#
# Example:
# If you have externals in https://example.com/svn/project1/trunk, then:
#
# this-script https://example.com /svn/project1/trunk
#
server=$1
repo=$2
# Get the commited properties
svn checkout $server$repo wc --depth=empty
svn pget svn:externals wc > wc.externals
# Remove empty lines
sed -i '/^$/d' wc.externals
# for each external in existing properties:
while read line; do
# tokenize
IFS='@ ' tokens=( $line )
# extract interesting stuff from the tokens
extrepo=${tokens[0]}
rev=${tokens[1]}
dir=${tokens[2]}
# Query the external repository for the last change
latest=$(svn info $server$extrepo | sed -ne 's/^Last Changed Rev: //p')
# Write a new set of externals based on latest info
echo "$extrepo@$latest $dir" >> wc.newexternals
done <wc.externals
# Get the differences between the new and old externals
details=$(diff -y --suppress-common-lines wc.externals wc.newexternals)
# If differences exist (and the diff was valid)
retval=$?
if [ $retval -eq 1 ]; then
# Set the new properties
svn pset svn:externals -F wc.newexternals wc
# Generate the SVN log
echo "Automatic externals update" > wc.log
echo $details >> wc.log
# Commit the changes
svn ci -F wc.log wc
fi
# Cleanup
rm -rf wc wc.externals wc.newexternals wc.log
The limitation is that it only supports externals configured relative to the same server's root.