Subversion – Building a Complex Release Structure Using Externals

I was thinking about how to structure a Subversion repository to cope with multiple internal components which have to be associated with a release as intermediate components (for example plugins).

The Problem

Let’s say you have a project which has multiple libraries which are developed by teams on individual release schedules. Normally you would go about this with the usual repository structure with each component having its own trunk, tags & branches combinations as shown below.

my-app-repo----+-> component_1
               |        +-> trunk
               |        +-> tags
               |        +-> branches
               |
               +-> component_2
               |        +-> trunk
               |        +-> tags
               |        +-> branches
               |
               +-> ...

For example you might have an application which is made up of individual sub-applications which are being worked upon by separate development teams:

  • Central Core Component
  • User Interface Component
  • Database Interface Component
  • etc.

Now each team has sat down and designed the interfaces which they’re going to expose to the other groups and have agreed with them that the API’s are suitable for the other groups to use. So each team now goes away and carries out the development of their subsystem within their part of the repository and merrily releases these periodically on their own determined release cycle. Each time they carry out one of these releases, like all good developers they *tag* the release within their application’s tags directory. You might end up with something like:

my-app-repo ----+-> core_app
	       |	+-> branches
	       |	+-> tags
	       |	|     +-> release_1.0
	       |	|     +-> release_1.0.1
	       |	|     +-> release_1.0.2
	       |	+-> trunk
	       |
	       +-> DB_app
	       |	+-> branches
	       |	+-> tags
	       |	|     +-> REL-0.1
	       |	|     +-> REL-0.2
	       |	+-> trunk
	       |
               +-> user_app
	        	+-> branches
	        	+-> tags
	        	|     +-> R1
	        	|     +-> R2
	        	+-> trunk

A problem arises when you need to perform some kind of release of a bundle of the applications together as a bundled release. How do you identify which releases of each of the components is part of the bundle?

A Potential Solution

ell one way of resolving this could be to have a separate bundled-releases tag directory at the top level of the repository and then to copy each of the separate tags into this directly. The obvious problem with this is that each copy operation would then be another revision within the repository and could result in changes being introduced to the tags as they get copied across.

A Better Solution

Another solution to the problem would be to make use of {{svn:externals}} properties within a top level directory to identify the revisions and paths of each of the tags which make up the bundled release.

    1. First of all we need to create the directory in which the tags will exist:

svn mkdir -m "Tag directory for bundled releases" $REPO_ROOT/bundled-tags
Committed revision 15.

    1. Now update our working copy with the new directory:

$ cd my-working-copy
$ svn update
A bundled-tags
Updated to revision 15.

    1. We need to create a directory which will contain the tags and add an svn:externals property upon it:

$ cd bundled-tags
$ svn mkdir bundled-1.0
A bundled-1.0

    1. The property should look something like:
core_app        $REPO_ROOT/core_app/tags/release_1.0
DB_app          $REPO_ROOT/DB_app/tags/REL-0.1
user_app        $REPO_ROOT/user_app/tags/R1
    1. Then finally of course commit the change back to the repository.

$ svn commit -m "Added bundled-tag for release 1.0"
Adding bundled-tags\bundled-1.0
Committed revision 16.

So now if someone checks out the tag which corresponds to the bundled release 1.0 they will get the following:

$ svn co $REPO_ROOT/bundled-tags/bundled-1.0
 U bundled-1.0

Fetching external item into 'bundled-1.0/core_app'
 A bundled-1.0\core_app\core-app.c
 ... core_app files ...
 Checked out external at revision 16.

Fetching external item into 'bundled-1.0\DB_app'
 A bundled-1.0\DB_app\db-app.pl
 ... DB_app files ...
 Checked out external at revision 16.

Fetching external item into 'bundled-1.0\user_app'
 A bundled-1.0\user_app\user-app.c
 ... user_app files ...
 Checked out external at revision 16.
Checked out revision 16.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s