Using externals? Best practices?
That's easy! Don't do it!
The svn:externals
is one of those things that seemed like such a good idea, but ended up causing all sorts of issues. I have found there are better ways to do this than using svn:externals
. For example, you can use Maven or Ivy to do dependency management for you.
However, if I do have to use svn:externals
, I will use tags instead of absolute revisions. This works better in newer versions of Subversion, and I don't usually have to worry about using a particular revision, but then the files' URLs all change as files get renamed and moved around. To me, tags are immutable, and once created, they never change.
This also encourages you to think of your svn:externals
as completely separate projects. For example, you can talk about Release 4.3 of Foundation. Your svn:externals
command would look something like this:
$ svn propset svn:externals `^/tags/4.3/foundation foundation` .
Note I don't put the URL scheme in the tag, or the server name. I almost always use relative paths if the externals is in the same repository as the project. Imagine if you use to use http://
, and you move over to using https://
, or the name of your Subversion repository machine changes. The externals would still work with this scheme, but break if I had done this:
$ svn propset svn:externals "http://server.com/svn//tags/foundation foundation" .
I am a Pathetic Liar
I am currently working in a project where I did not do what I mentioned above. I don't use tags for my svn:externals
, and all of our projects must have them.
In this company, they had a terrible problem with jar dependency management. They produce about a dozen base jars that are used in multiple projects. Each of these projects had different ways of specifying these jars
To get around this, I set up a special Ivy project called ivy.dir
. Developers were told to incorporate this project into their current project by using the following command:
$ svn propset svn:externals "../ivy.dir ivy.dir" .
Inside ivy.dir
was a complete setup for integrating your project into Ivy. Ivy was preconfigured to use our new corporate Maven repository. All of our various build tools are here.
This approach made incorporating Ivy and good dependency management into our projects a breeze. You merely <import>
the ivy.dir/ivy.tasks.xml
file into your current build.xml
, and use <ivy:cachepath>
to create your classpath. A good, well formed build.xml
only needs minor modifications to run.
I even created a special <jar.macro>
macro definition. It is almost 100% compatible with the <jar>
macro, but it will automatically create a pom.xml
file from the ivy.xml
and embed it into the built Jar (and will also include the Jenkins project name, build date, and build number.)
By using relative URLs, I make it easy to branch everything or to tag it (and the ivy.dir project also gets tagged).
It's a strange way of using svn:externals
, but it allows us to get away from the awful use they had before where many of the projects used svn:externals
to pull in jars stored inside the repository.