svn:externals

I just love svn:externals. Well, I just love Subversion actually. But I love svn:externals in particular. I can split my life basically into two parts. Life before svn:externals and my life after svn:externals. Nah, thats a bit of nonsense of course, but svn:externals has made a big impact on how I organize my source code or even more important, how I organize my dependencies.

If you’re a programmer, be it with ActionScript, ColdFusion, Java or whatever, then I’m sure you have worked with external libraries, packages or frameworks before. A common practice is to make a copy of your framework, packages or libraries (called dependencies from now on) into your projects source folder and take it from there. Sometimes your development environment allows you to include a certain set of folders in a search path so you don’t have to make an explicit copy of your dependencies but allows you to place these shared dependencies in a single place to be used by many from then on.

Although this works for most of us pretty well most of the time, at some point things will start to fall apart. Imagine you store your dependencies and your projects separate from each other in your Subversion repository and your dependencies are checked out on your drive in a generic location. This saves you from making explicit copies of your decencies and it prevents you from updating the same bug in your framework 25 times because the same dependencies are shared by 25 different projects. So, separating your projects and your dependencies is a good thing you would say.

The problem is, however, that the code base of dependencies usually change over time. Libraries and frameworks are patched and updated with bug fixes that might have an impact on the interface and break the projects that depend on them. A more dangerous situation is when the updates of dependencies have only changes that are invisible. An upgraded framework might still compile. However, if you do not put your product through the same rigorous testing as with the previous version of your framework, you can never be sure it will actually work and that it hasn’t introduced new bugs. When you share dependencies then maybe an update is not what you want for all your projects but just for some. So what do you do? The explicit copy helps in this situation because every project can use its own version of a set of dependencies.

So then, what is it? Sharing or explicit copies?

Neither actually. Unless you are a “serial tagger” and make a tag of every single version of the dependencies trunk for every single project. This is usually not the case and if you’re working in an environment where you’re not involved with every single project you need another strategy. Allow me to introduce: svn:externals.

With svn:externals you actually have a sort of hybrid situation. You make an explicit copy of your dependencies in your project source folder while still having a shared situation at the same time. You still follow? Basically you could compare svn:externals to what they call a symbolic link in a UNIX environment.

Imagine you’re building a website that incorporates a CMS and you want to use this CMS as part of your project. The CMS is located in the Subversion repository in the resources folder and has a number of tagged versions associated with it. Your project is located in the same repository in the projects folder and lives in the trunk folder. This might look something like this:

+repository
  +resources
    +mycms
      +branches
      +tags
        +1.0.0
        +1.0.2
        +1.5.0
      +trunk

  +projects
    +myproject
      +branches
      +tags
      +trunk
        +deploy
        +source

This seems all pretty standard. In the trunk folder of the project you see two other folders, a deploy and a source folder. This is how I personally divide most of my projects. Everything in the deploy folder goes straight onto the server. The source folder contains everything that needs compilation, like Flash files and Word documents that need to be converted into PDF format. Anything compiled or published in this source folder will be automatically placed in the deploy folder. Be it with application publish settings or through Ant or MAKE files.

We want our CMS to be part of our deploy folder because it’s written in PHP and it doesn’t need any special kind of compilation. So, we checkout the trunk folder of our project and place it somewhere convenient on our hard drive. The checked out project folder should now contain both the deploy and the source folders.

Now its time for svn:externals to do its magic. We are going to add a SVN property to the deploy folder of our checked out copy. If you haven’t used SVN properties yet, like svn:keywords, then I suggest you go have a read in the excellent online Subversion book to get up to speed.

By adding the svn:externals property you can create an external link to another location in your repository. As a matter a fact, you can create an external link to a location in a completely different repository on a completely different server that’s somewhere on the other side of the world. The files at the external location will then be included in your project as if they are part of your project through what might be compared to as a symbolic link. In a sense the external files are part of your project since the files that are external will be checked out on your hard drive just as any other files of your project. Now, if someone else would make changes to these external files and would commit those changes, the next time you do an SVN update on your project you will receive those changes as well. As you might understand this is a very powerful feature of Subversion because you can contain all your project dependencies in a single place while still having the ability to update from a single place at the same time.

Back to our repository example from before. If we want to have our project depend on version 1.5.0 of the CMS then all we have to do is create a svn:externals property on the deploy folder of our project pointing to the tagged 1.5.0 version of our CMS. Even if the trunk of the CMS changes with bug fixes and other patches, it has no impact on our project. Unless we explicitly change the svn:externals property to point to a newer version, we’re safe.

Setting the svn:externals property is not much of a issue. Most GUI clients like TortoiseSVN and Subclipse for Eclipse support setting Subversion properties. The svn:externals property consists of a variable name and a URL value. In our example we could set the svn:externals property on the deploy folder to the following value:

mycms svn://svnserver/repos/resources/mycms/tags/1.5.0

After setting the svn:externals property you have to run a SVN update on your checked out project and you should receive the external files as part of your project (If you’re using Subclipse you even get to see an special link symbol on the folders icon). If you need more than one svn:externals property on a single folder then you can add as many values to the svn:externals property as you like.

Hopefully all this make sense and that svn:externals will be useful to your projects. If you need more in depth information on the subject then I can highly recommend the online Subversion book..

Leave a Reply