Subversion branch inheritance by convention: svnMergeChildren
Contents
Introduction
I'm looking for a solution to put configuration files of multiple hosts under version control and so far I've come up with the solution below.
The configuration files share some kind of inheritance: A change in the global configuration file should be propagated to all host configuration files. For example, consider a .bashrc configuration file running on 4 computers on 2 domains:
+--------+ global: | bashrc | +----+---+ /_\ | +------------+-------------+ | | +----+---+ +----+----+ domain: | planet | | country | +----+---+ +----+----+ /_\ /_\ | | +-----+-----+ +-----+------+ | | | | +----+---+ +---+---+ +---+---+ +----+----+ host: | saturn | | pluto | | spain | | england | +--------+ +-------+ +-------+ +---------+
Maintenance would be made easier if I could specify inheritance in subversion, for example:
.bashrc Example setting ----------- ------------------------------------------------- +---------+ | global | # This personal setting should go everywhere | bashrc | set -o vi +----+----+ /_\ | +----+----+ | domain | # This domain has a centralized project directory | planet | CDPATH=/usr/share/proj +----+----+ /_\ | +----+----+ | host | # This host is running the latest Vim | saturn | export VIMRUNTIME=/usr/local/share/vim/vim70 +---------+
I've created a short shell script svnMergeChildren.sh which merges parent changes to all children
Usage
Create a repository with directories for every class (i.e. domain/host), using the convention:
- EACH DIRECTORY MUST BE PREFIXED WITH ITS PARENT NAME
(Note: You can apply this to filenames as well, naming it "File inheritance by convention" :-)
trunk |- bashrc |- bashrc-planet |- bashrc-planet.saturn |- bashrc-planet.pluto |- bashrc-country |- bashrc-country.england |- bashrc-country.spain</nowiki>
On every host, checkout the repository and link to the right branch:
svn checkout .../repos/branches/pluto ./workdir/bashrc-planet.pluto ln -s ./workdir/bashrc-planet.pluto/.bashrc
On the host which is used for development, merge parent changes to all children using svnMergeChildren.sh
:
#!/bin/bash #--- svnMergeChildren.sh -------------------------------------------- # Copyright (C) 2006 Freddy Vulto # Version: 2.0.0 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA # # The latest version of this software can be obtained here: # http://fvue.nl/svnMergeChildren/ set -o errexit # Exit on error set -o nounset # Trigger error when expanding unset variables function svnMergeChildren() { # If no arguments, or -h, or --help, show usage [[ $# == 0 || $1 == -h || $1 == --help ]] && { echo -n Merge children: Apply the difference between echo two sources to multiple working copy paths echo Usage: $(basename $0) ... NAME_PARENT echo echo See \'svn help merge\' for ... arguments. echo echo For more information, see http://fvue.nl/svnMergeChildren/ return $(test $# -gt 0) } # Get last parameter parent=${!#} # Unset last positional parameter args=( "$@" ); unset args[${#args[@]}-1]; set -- "${args[@]}" # Indicate non-verbose if either -q or --quiet specified for i; do [ "$i" = -q -o "$i" = --quiet ] && beVerbose=0; done # Loop through children shopt -s failglob nullglob; for i in "$parent"?*; do (( "${beVerbose-1}" )) && echo svn merge "$@" "$i" svn merge "$@" "$i" done } # svnMergeChildren() svnMergeChildren "$@"
Scenario 1: Merge changes in global .bashrc to all children
Suppose you've made a modification (say revision 2) in the global .bashrc
you'd like to see propagated into all children. Here's the command to do so (leave out --dry-run
for an actual run):
svnMergeChildren.sh -r1:2 --dry-run file:///proj/bash/repos/trunk/bashrc bashrc
Scenario 2: Merge changes in domain .bashrc to domain children
Suppose you've made a modification (say revision 3) in the .bashrc
planet domain you'd like to see propagated into all children of the planet domain. Here's the command to do so (leave out --dry-run
for an actual run):
svnMergeChildren.sh -r2:3 --dry-run file:///proj/bash/repos/trunk/bashrc-planet bashrc-planet
Download
- Single file: svnMergeChildren.sh
- Package with additional test suite (DejaGnu): svnMergeChildren-2.0.0.tar.gz
Test
The download contains an additional test suite. The test suite requires dejagnu, tcl and expect to be installed.
To run the tests:
cd test ./runAll
Example output
WARNING: Couldn't find tool init file Test Run By freddy on Sun Nov 12 10:42:20 2006 Native configuration is i686-suse-linux === all tests === Schedule of variations: unix Running target unix Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target. Using /usr/share/dejagnu/config/unix.exp as generic interface file for target. WARNING: Couldn't find tool config file for unix, using default. Running ./all/all.exp ... === all Summary === # of expected passes 7
Release notes
svnMergeChildren-2.0.0, Nov 12, 2006 * Renamed svnMergeChilds to svnMergeChildren svnMergeChilds-1.0.2, Nov 12, 2006 * Shortened line length. svnMergeChilds-1.0.1, Nov 11, 2006 * Fixed support for parameters with whitespace. * Removed invocation of excess subshells.
Journal
20061007
Ten Ways to Sunday: Source Control Inheritance
20061030
First attempt of a shell script to ease the job.
20061112
- Posted to mailing list gmane.comp.version-control.subversion.user