Matt Wizeman

All | General | Java | Ruby | Ant
XML
20070331 Saturday March 31, 2007
SVN Revision Numbers in Ant

Yesterday at work, a coworker called and asked for some ideas on how to read the Subversion revision number of a sandbox from within an Ant build script. Doing this would allow that number to be stamped on files during the build, which can help down the road when you need to figure out exactly which version of the project is running in a dev, test or integration environment.

Thinking about how I would do this outside of Ant, my first answer was to have him run "svn info" and parse the output. As a reference for those who don't run it very often, if you were to open a terminal window and run this command in one of your sandboxes the output would look something like:

  Path: .
  URL: svn+ssh://username@my.dev.server/data/repository/project/trunk
  Repository Root: svn+ssh://username@my.dev.server/data/repository/project
  Repository UUID: 5853ccd8-1d1d-0410-918b-9390590c579a
  Revision: 668
  Node Kind: directory
  Schedule: normal
  Last Changed Author: adeveloper
  Last Changed Rev: 668
  Last Changed Date: 2007-03-30 18:53:52 -0400 (Fri, 30 Mar 2007)

It turns out that this matches the format for a properties file in Java, so parsing this is pretty straightforward in Ant. All we need to do is pipe this out to a file and ask Ant to read it in during the build. At that point, the sandbox revision number will be available in the build as a property named Revision (note the capital R). The build file snippet below shows how all of this is done in Ant using the exec and property tasks.

  <exec executable="svn" output="build/svn.properties">
    <arg value="info" />
  </exec>
  <property prefix="svn" file="build/svn.properties"/>
  <echo>Sandbox Revision: ${svn.Revision}</echo>

When run, this prints the expected output of "Sandbox Revision: 668".

This method works but has two problems. First, it counts on the fact that the svn executable is in the path of every system that will run this build file. Second, the actual implementation in Ant isn't exactly straightforward and it may not be clear what's going on to someone reading the build. Neither of these are major problems, but it still seemed like there should be a better way.

As luck would have it, there is. In addition to Subversion itself, the folks over at Tigris also have a library called SvnAnt, which is an Ant task that makes working with Subversion pretty easy. One of the commands, status, does exactly what we're after and sets an Ant property with the revision number of a given path. Using SvnAnt, our build snippet now looks like:

  <taskdef resource="org/tigris/Subversion/svnAnt/svnAntlib.xml">
    <classpath>
      <fileset dir="${build.lib.dir}/svnAnt" includes="**/*.jar" />
    </classpath>
  </taskdef>

  <svn>
    <status path="${basedir}" revisionProperty="svn.revision" />
  </svn>
  <echo>Sandbox Revision: ${svn.revision}</echo>

This is much easier to read and I think solves the clarity problem of the first approach. As for the svn executable needing to be on the path, that may be solved too depending on the version of SvnAnt you are using. While the current stable release (1.0.0) of SvnAnt requires the svn executable or the javahl bindings, the latest development release (1.1.0-RC2) includes integration with SVNKit, which is a pure Java Subversion library. This means that if the build file runs on a system that is missing the native resources for javahl, the pure Java implementation will be used and everything will still work. Nice!

Posted by mwizeman Mar 31 2007, 10:06:08 PM EST