svn:externals

Today I came across mention of a subversion property I was not familiar with, svn:externals. After skimming the documentation, svnbook, it seemed like something that could be useful.

What the svn:externals property allows you to do is configure a subdirectory in your project so that it is pulled from a different location in the repository, or a even different repository. Basically setting up a dependency system, albeit a simplistic one, using only subversion.

One possible usage might be to pull Systir into a project. Rather than copying the latest version into the current project, a subdirectory could be configured with an svn:externals property that will pull the latest Systir code from it’s trunk. Every time the project being worked on is updated, the systir directory would also be updated. Or perhaps, the property could be set to a particular tag of the Systir project, insuring a compatible version, but still allowing for an upgrade without having to copy/paste.

Unfortunately you can’t pull specific files, only entire directories. But if there are cases where entire subdirectories of code are being copied from one project to another, this might be a solution that provides a way to keep that code in one location.

The page where I saw the mention of svn:externals ( the { buckblogs :here } ) describes (in a comment) how 37signals uses it to pull plugins into the vendor/plugins directory of their rails projects. They do this to share code between their different products.

I did some playing around to see how it works.

I setup three project directories in subversion: my_app, magic_plugin, hello_world_plugin.

$ svn co http://svnserver/my_app A my_app/branches A my_app/trunk/my_app.rb

$ svn co http://svnserver/magic_plugin A magic_plugin/branches A magic_plugin/trunk/ruby_magic.rb

$ svn co http://svnserver/hello_world_plugin A hello_world_plugin/branches A hello_world_plugin/trunk/hello_world.rb

The idea here is that the my_app program will be able to load and use plugins. The other two projects are plugins that my_app could use.

The locations of the external subversion directories can’t be relative. Because they are full paths, they can point to any accessible subversion repository. To pull the plugin projects into the my_app project I set the svn:externals property.

$ cd my_app/trunk $ svn propedit svn:externals plugins

magic_plugin http://svnserver/magic_plugin/trunk hello_world_plugin http://snvserver/hello_world_plugin/trunk [save and exit editor]

property ‘svn:externals’ set on ‘plugins’

Double check that the properties are set correctly:

$ svn propget svn:externals plugins magic_plugin http://svnserver/magic_plugin/trunk hello_world_plugin http://snvserver/hello_world_plugin/trunk

Setting the property doesn’t change anything in the directory. You have to update to actually get the files.

$svn update

Fetching external item into ‘plugins/magic_plugin’ A plugins/magic_plugin/ruby_magic.rb Updated external to revision 3.

Fetching external item into ‘plugins/hello_world_plugin’ A plugins/hello_world/hello_world.rb Updated external to revision 3.

Updated to revision 3.

Displaying the status now looks like this:

$ svn status X plugins/magic_plugin X plugins/hellow_world_plugin

Performing status on external item at ‘plugins/magic_plugin

Performing status on external item at ‘plugins/hello_world_plugin’

I then made a change to the ruby_magic.rb file in the magic_plugin project and checked it in. Updating the my_app project pulled in the new file automatically:

$ svn update

Fetching external item into ‘plugins/magic_plugin’ U plugins/magic_plugin/ruby_magic.rb Updated external to revision 4.

Fetching external item into ‘plugins/hello_world_plugin’ Updated external to revision 4.

Updated to revision 4.

Filed in: Tips, Tools


Leave a Reply