Sunday, February 22, 2009

Extracting Subversion status from Maven or Ant build

UPDATE 2009/02/24: the original version didn't work, it worked on my machine only since the task quietly falls back to the command line interface if loading SVNkit fails. Since it needs not only SVNkit, but also the JavaHL API for SVNkit (I can't find that documented anywhere, but the source tells you), it failed in the original version. There was also an issue with the version of SVNkit since I took what was available in the Maven repositories (1.1.0), but that version is too old to handle SVN 1.5 working copies. The fix was to replace a dependency on SVNkit 1.1.0 with one on SVNkit-JavaHL 1.2.2 (which in turn depends on SVNkit 1.2.2).

To extract the current revision and potential changes of a Subversion working copy during a build a combination of the SVN Ant task and SVNKit can be used, which means it is a 100% pure Java solution. It requires around 2MB of libraries in the build chain, which will not be deployed.

Here is the solution in the context of Maven, bound to the "process-resource" phase of the lifecycle. Note that I declare a dependency on the Ant task (and transitively to the SVN client adapter) that is resolved against a local repository. I couldn't find those in a standard repository. The SVNkit available, is not the youngest, so we have a newer one in a local repository, too -- including the svnkit-javahl.jar, which contains the compatibility API the Ant task uses. You should be able to get away with four JARs: one for the Ant task itself, one for the client adapter and the SVNkit library as well as its JavaHL adapter.

If you want to use the solution in Ant, just use the part in the <tasks> element and replace the classpathref with a suitable classpath containing the three JARs mentioned above.

You don't have to use SVNkit (makes most of the solution's size) but can use JavaHL or the command line interface instead by changing the attributes of the <svn> task. I much prefer the pure Java way, though.


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>svn_status</id>
<phase>process-resources</phase>
<configuration>
<tasks>
<taskdef name="svn"
classname="org.tigris.subversion.svnant.SvnTask"
classpathref="maven.plugin.classpath" />
<svn javahl="false" svnkit="true">
<!-- change @path if not interested in the base directory -->
<!-- set @processUnversioned to "true" if new files should show up as modifications -->
<wcVersion path="${basedir}" prefix="buildInfo.svn." processUnversioned="false"/>
</svn>

<!-- set properties not set by wcVersion to "false" so we get nice output -->
<property name="buildInfo.svn.modified" value="false"/>
<property name="buildInfo.svn.mixed" value="false"/>

<!-- set @file to wherever you want the properties file -->
<!-- we copy all information from wcVersion, even if it is redundant -->
<propertyfile file="target/classes/META-INF/build.properties" comment="Build information">
<entry key="svn.repository.url" value="${buildInfo.svn.repository.url}"/>
<entry key="svn.repository.path" value="${buildInfo.svn.repository.path}"/>
<entry key="svn.revision.max" value="${buildInfo.svn.revision.max}"/>
<entry key="svn.revision.max-with-flags" value="${buildInfo.svn.revision.max-with-flags}"/>
<entry key="svn.revision.range" value="${buildInfo.svn.revision.range}"/>
<entry key="svn.committed.max" value="${buildInfo.svn.committed.max}"/>
<entry key="svn.committed.max-with-flags" value="${buildInfo.svn.committed.max-with-flags}"/>
<entry key="svn.modified" value="${buildInfo.svn.modified}"/>
<entry key="svn.mixed" value="${buildInfo.svn.mixed}"/>
<entry key="build.timestamp"
type="date"
pattern="yyyy-MM-dd'T'HH:mm:ss"
value="now"/>
<!-- put more useful information here -->
</propertyfile>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-optional</artifactId>
<version>1.5.3-1</version>
</dependency>
<dependency>
<groupId>org.tigris.subversion</groupId>
<artifactId>svnant</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.svnkit</groupId>
<artifactId>svnkit-javahl</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
</plugin>

1 comment:

Manchester United said...

Ich bin froh, dass ich diese Website gefunden, ich konnte keine Kenntnisse zu diesem Thema vor finden to.Also eine Website betreiben und wenn Sie jemals daran interessiert sind, einige Besucher für mich zu schreiben tun, wenn möglich, fühlen Sie sich frei, mich zu informieren, im immer für die Leute meine Website zu überprüfen. lese mehr