Print compiled Clojure svn revision?

2 views
Skip to first unread message

vdm

unread,
Nov 7, 2008, 11:46:22 AM11/7/08
to Clojure
Is there a way to make Clojure print the svn revision it was compiled
from? A standard or idiomatic way to do this (print clojure--svn-rev)
would help when trying to isolate whether observed behaviour is
happening on old or current code.

It is possible to have newer code checked out but still be using an
old compiled clojure.jar.

Graham Fawcett

unread,
Nov 7, 2008, 1:02:48 PM11/7/08
to clo...@googlegroups.com, richh...@gmail.com
On Fri, Nov 7, 2008 at 11:46 AM, vdm <vdmu...@gmail.com> wrote:
>
> Is there a way to make Clojure print the svn revision it was compiled
> from? A standard or idiomatic way to do this (print clojure--svn-rev)
> would help when trying to isolate whether observed behaviour is
> happening on old or current code.

Hi, as far as I know, no. But I agree it would be great to have, and
is certainly possible to do.

If Rich would be willing to add this to boot.clj,

(defn clojure-svn-revision []
(if-let rev (re-find #"Rev: (\d+) \$" "$Rev$")
(second rev)
"unknown"))

and then do this,

svn propset svn:keywords "Revision" boot.clj
svn commit boot.clj

...then (clojure-svn-revision) ought to return the revision number as
a string.

Best,
Graham

Rich Hickey

unread,
Nov 7, 2008, 1:15:25 PM11/7/08
to Clojure


On Nov 7, 1:02 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
This works by making $Rev$ magic in some way?

Rich

Graham Fawcett

unread,
Nov 7, 2008, 1:18:48 PM11/7/08
to clo...@googlegroups.com

Yes, exactly. See
http://svnbook.red-bean.com/en/1.1/ch07s02.html
in the "keywords" section.

Best,
Graham

Chouser

unread,
Nov 7, 2008, 1:48:16 PM11/7/08
to clo...@googlegroups.com
On Fri, Nov 7, 2008 at 1:02 PM, Graham Fawcett <graham....@gmail.com> wrote:
>
> If Rich would be willing to add this to boot.clj,
[snip]

>
> ...then (clojure-svn-revision) ought to return the revision number as
> a string.

I'd really like to see something like this too, but unfortunately I
don't think it's this simple.

Please correct me if I'm wrong, but any changes to the Clojure sources
that don't include a change to boot.clj will fail to update this
revision number. If that's the case, the number reported could be
misleading, and I'd argue would be worse than no number at all.

I think the "right" way to do this would be for the Clojure compile
process to include a call out to "svn info" to get the revision number
of the whole tree, and then somehow include the results of that back
in the .jar file for some Clojure function to read. ...but I don't
really know enough about ant (or svn either, for that matter) to do
this myself.

--Chouser

wwmorgan

unread,
Nov 7, 2008, 1:51:07 PM11/7/08
to Clojure
As a matter of style, I would rather see this functionality in a
global var than in a function. I think that's it's a more idiomatic
place for it.

user=> *version*
"r1088"



On Nov 7, 1:18 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> On Fri, Nov 7, 2008 at 1:15 PM, Rich Hickey <richhic...@gmail.com> wrote:
>
> > On Nov 7, 1:02 pm, "Graham Fawcett" <graham.fawc...@gmail.com> wrote:
> >> On Fri, Nov 7, 2008 at 11:46 AM, vdm <vdmur...@gmail.com> wrote:
>
> >> > Is there a way to make Clojure print the svn revision it was compiled
> >> > from? A standard or idiomatic way to do this (print clojure--svn-rev)
> >> > would help when trying to isolate whether observed behaviour is
> >> > happening on old or current code.
>
> >> Hi, as far as I know, no. But I agree it would be great to have, and
> >> is certainly possible to do.
>
> >> If Rich would be willing to add this to boot.clj,
>
> >> (defn clojure-svn-revision []
> >>   (if-let rev (re-find #"Rev: (\d+) \$" "$Rev$")
> >>           (second rev)
> >>           "unknown"))
>
> >> and then do this,
>
> >> svn propset svn:keywords "Revision" boot.clj
> >> svn commit boot.clj
>
> >> ...then (clojure-svn-revision) ought to return the revision number as
> >> a string.
>
> > This works by making $Rev$ magic in some way?
>
> Yes, exactly. Seehttp://svnbook.red-bean.com/en/1.1/ch07s02.html

Graham Fawcett

unread,
Nov 7, 2008, 2:20:42 PM11/7/08
to clo...@googlegroups.com
On Fri, Nov 7, 2008 at 1:48 PM, Chouser <cho...@gmail.com> wrote:
>
> On Fri, Nov 7, 2008 at 1:02 PM, Graham Fawcett <graham....@gmail.com> wrote:
>>
>> If Rich would be willing to add this to boot.clj,
> [snip]
>>
>> ...then (clojure-svn-revision) ought to return the revision number as
>> a string.
>
> I'd really like to see something like this too, but unfortunately I
> don't think it's this simple.
>
> Please correct me if I'm wrong, but any changes to the Clojure sources
> that don't include a change to boot.clj will fail to update this
> revision number. If that's the case, the number reported could be
> misleading, and I'd argue would be worse than no number at all.

Oh, excellent point.

> I think the "right" way to do this would be for the Clojure compile
> process to include a call out to "svn info" to get the revision number
> of the whole tree, and then somehow include the results of that back
> in the .jar file for some Clojure function to read. ...but I don't
> really know enough about ant (or svn either, for that matter) to do
> this myself.

I suspect there is a better way than that -- we shouldn't really
depend upon the client to have 'svn' installed at build-time, though
it would often be the case.

Subversion supports 'hook scripts' that are run server-side during a
commit process. I'm sure someone else has written such a script to
update a version-file (e.g. version.clj, containing a *version* def)
that is touched any time a revision is made.

Let me see what I can find.

Graham

Matt Revelle

unread,
Nov 7, 2008, 2:23:31 PM11/7/08
to clo...@googlegroups.com
I'm just finishing up an addition to the build script that executes
"svnversion" and stores the result in a "versioninfo" file that would
be placed in the clojure.jar file and the value stored in a *version*
var in boot.clj.

If someone is building from source, I think we can assume they have
development tools.

-Matt

Daniel Renfer

unread,
Nov 7, 2008, 2:25:36 PM11/7/08
to clo...@googlegroups.com
This wouldn't work if someone is using a mirror of the repository
using a different SCM.

For instance, there's a mirror on github.

Matt Revelle

unread,
Nov 7, 2008, 2:34:47 PM11/7/08
to clo...@googlegroups.com
On Nov 7, 2008, at 2:25 PM, Daniel Renfer wrote:

>
> This wouldn't work if someone is using a mirror of the repository
> using a different SCM.
>
> For instance, there's a mirror on github.


True, if supporting other SCMs is important we can make the "version"
task in the build file smart enough to determine which, if any, should
be used for requesting the version. The other option is to add a
commit hook that will update the contents of some file with the
current revision. The latter option is starting to sound better.

Graham Fawcett

unread,
Nov 7, 2008, 2:35:18 PM11/7/08
to clo...@googlegroups.com
On Fri, Nov 7, 2008 at 2:25 PM, Daniel Renfer <du...@kronkltd.net> wrote:
>
> This wouldn't work if someone is using a mirror of the repository
> using a different SCM.

No, but it would still include the upstream SVN revision number.

Alas, what I thought was possible with SVN hooks appears to be
impossible -- while in an SVN commit transaction, the SVN server
cannot say "and also touch this file over here" if that file was not
part of the commited patch.

It seems the best alternative is to let Ant try to get the SVN
revision and push in the change, as Chouser suggested.

Best,
Graham

Mike Hinchey

unread,
Nov 7, 2008, 2:41:37 PM11/7/08
to clo...@googlegroups.com

Matt Revelle

unread,
Nov 7, 2008, 3:51:00 PM11/7/08
to clo...@googlegroups.com
I'm in a rush and need to clean this up, but here's something that
works:

Index: build.xml
===================================================================
--- build.xml (revision 1088)
+++ build.xml (working copy)
@@ -11,6 +11,7 @@
<property name="build" location="classes"/>
<property name="clojure_jar" location="clojure.jar"/>
<property name="bootclj" location="${cljsrc}/clojure/boot.clj"/>
+ <property name="versioninfo" location="versioninfo"/>

<target name="init">
<tstamp/>
@@ -22,10 +23,18 @@
<javac srcdir="${jsrc}" destdir="${build}"
includeJavaRuntime="yes" debug="true" target="1.5"/>
</target>

- <target name="jar" depends="compile"
+ <target name="version"
+ description="Generate version information file.">
+ <exec executable="svnversion" spawn="false" dir="."
output="${versioninfo}">
+ <arg line="."/>
+ </exec>
+ </target>
+
+ <target name="jar" depends="compile, version"
description="Create jar file.">
<jar jarfile="${clojure_jar}" basedir="${build}">
<fileset dir="${cljsrc}" includes="**/*.clj"/>
+ <fileset dir="." includes="**/versioninfo"/>
<manifest>
<attribute name="Main-Class" value="clojure.lang.Repl"/>
<attribute name="Class-Path" value="."/>


Index: src/clj/clojure/boot.clj
===================================================================
--- src/clj/clojure/boot.clj (revision 1088)
+++ src/clj/clojure/boot.clj (working copy)
@@ -3674,3 +3674,4 @@
"defs the supplied var names with no bindings, useful for making
forward declarations."
[& names] `(do ~@(map #(list 'def %) names)))

+(def *version* (. (java.io.BufferedReader.
(java.io.InputStreamReader. (ClassLoader/getSystemResourceAsStream
"versioninfo"))) readLine))

user> *version*
"1088M"

The build.xml script now runs a version task that creates a
"versioninfo" file. That file is added to clojure.jar and read in
boot.clj where the value is stored in *version*.

-Matt

Matt Revelle

unread,
Nov 8, 2008, 12:03:17 PM11/8/08
to clo...@googlegroups.com
If marking SVN revisions and/or release versions is something we still
want and want automated, it now looks like using the build tool is the
only way to go. The example I sent earlier to the list includes the
creation of a "versioninfo" file from the build script which is then
read and stored in a "version" var in boot.clj.

The only problem is that the build script now depends on the
"svnversion" command being available and a SVN repository being used
for building. For tarball releases of the source, the "versioninfo"
file can be generated for the release and the build script modified to
use the existing file if "svnversion" isn't working. As for
supporting git and other SCMs used to mirror the SVN repos, the build
script can be made to use the tools available in any of the other SCMs
to identify the SVN revision and generate the "versioninfo" file.

Or have we decided this isn't worth it?

-Matt

Graham Fawcett

unread,
Nov 14, 2008, 11:43:24 AM11/14/08
to clo...@googlegroups.com
On Sat, Nov 8, 2008 at 12:03 PM, Matt Revelle <mrev...@gmail.com> wrote:
>
> If marking SVN revisions and/or release versions is something we still
> want and want automated, it now looks like using the build tool is the
> only way to go. The example I sent earlier to the list includes the
> creation of a "versioninfo" file from the build script which is then
> read and stored in a "version" var in boot.clj.
>
> The only problem is that the build script now depends on the
> "svnversion" command being available and a SVN repository being used
> for building. For tarball releases of the source, the "versioninfo"
> file can be generated for the release and the build script modified to
> use the existing file if "svnversion" isn't working. As for
> supporting git and other SCMs used to mirror the SVN repos, the build
> script can be made to use the tools available in any of the other SCMs
> to identify the SVN revision and generate the "versioninfo" file.

+1. I think it's worth it, and would really like to see this put in place.

Best,
Graham

Matt Revelle

unread,
Nov 14, 2008, 2:53:19 PM11/14/08
to clo...@googlegroups.com
Ok, will submit a patch for this early next week.

Current plan is to use a properties file (versioninfo.properties) that
will be generated from the ant build script and contain the release
version/name, the source repository, a revision indicator (number,
tag, or digest), and who built it.

All the properties may be defined on the command line when running
"ant jar". If the properties are not defined, the ant updated build
script will try to determine them.

The versioninfo.properties file will be included in the jar and loaded
by core.clj.

Two considerations:

* Should we store the properties as a Clojure map instead of as a Java
properties file?

* Should we generalize "versioninfo.properties" to
"clojure.properties" with a "version" prefix? E.g., "version.release-
name".

-Matt

On Nov 14, 2008, at 11:43 AM, "Graham Fawcett"
Reply all
Reply to author
Forward
0 new messages