Ident tool alternative in SVN property

684 Views Asked by At

We had already used "Ident" tool in CVS via RCS keywords to get some info like "ID" and "DATE" from our source codes. We could simply do that by inserting keywords $Id$ and $Date$ into the text file, and the nice thing was when we compiled the program and could gain the same info from the binary file by Ident tool:

$ ident a.out

Now, we are using SVN. It can still be simply done by svn properties with better features. The only problem is that we get this info only in text files, but we also need to somehow get them from a binary compiled file, like Ident above.

Any idea how can we get them from a binary file?

1

There are 1 best solutions below

2
On

Subversion, when keywords are set, will create an identical ID type string. The Keyword isn't set in binary programs because that will hurt binary programs. Instead, you create a string variable with the version information like this in the source:

VERSION_STRING = "$Id$";

When Subversion does a checkout, it'll expand that to:

VERSION_STRING = "$Id: foo.blah 12338 2014/06/12 02:11:38 bsmith $";

Since this is a variable, it will be preserved in the binary code, and the ident program should be able to find it.

Make sure that the Subversion property svn:keywords is set on this source file. Otherwise, Subversion won't expand the keyword.

And not why you shouldn't be using keyword expansion...


Keyword expansion was a concept that started with more primitive revision control systems. It was a way to track revisions because the concept of the working directory didn't exist. In the end, keywords ended up being more than a pain than it's worth. It's interesting that the first version control system that abandoned automatic keywords was CVS which was based upon RCS. CVS was the first version control system that created a working directory instead of individual files that are versioned one-by-one.

A program isn't one or two files, it can be dozens -- maybe hundreds. If I have one file where I put my $Id$ keyword, the version information shown is just the version information of that file. If I don't modify that file, that version information will be identical in each and every release. One way around this was to put the keyword in each file:

$ ident /bin/ksh | wc -l 
    58

There are 57 separate keywords in my /bin/ksh file. Now, all I have to do is look at each of these individual IDs and deduce what version of Kornshell I actually have.

Or I could do this:

$ ksh --version
  version         sh (AT&T Research) 93u 2011-02-08

Ah, now I know what version of my code to checkout. It's probably tagged with 93u 2011-02-08 (Well, not really since CVS and RCS didn't allow for tags with spaces, or starting with numbers. But, it I should easily be able to convert this to a particular CVS/RCS tag). With CVS, I could take a look at the log information and see what changes took place too. Did a certain bug get fixed? Was a particular feature added? Who made that code change?

To create this information, the build system used some method to modify a source file with this information when it was checked out. You don't even have to commit that change either. In fact, it's actually better not to. My source looks like this:

VERSION = "$Id: %VERSION% $";

and by build system replaces %VERSION% with whatever I want %VERSION% to be. Even non-compiled code like PHP or JavaScript releases can benefit from this. Combine this with a CI system like Jenkins that can run unit tests, and package the software with each change in the code, and you have a way of automatically including this in your actual release.

We're a Java shop, so we embed this information like this:

<copy file="${version.file}"
    tofile="${actual.version.file}">
    <filterset>
         <filter token="VERSION" value="${env.JENKINS_JOB} Build #${env.BUILD_NUMBER}"/>
    </filterset>
</copy>

And Jenkins will replace that string with the Jenkins job name and build number. Since we release our software based upon the Jenkins job and build number, we can track our changes this way.

Imagine if this change produced a compiled string like this:

$Id: Project-trunk Build #343 $

The ident command can pick this out. This build is related to a particular set of Subversion revisions (and maybe even a Subversion tag) and by using Subversion, I can see what changes were made, and if I integrated this into a issue tracking system. In fact, why you're at it, why not set it up so that SCCS's `what command can pick it up too:

$Id: @(#) Project-trunk Build #343 < $

The what command picks up the@(#)string and prints out the entire string until it runs into a NULL character, a _NL_ character, or the<`.

$ what program.exe
/opt/bin/program.ext
              Project-trunk Build #343
$ ident program.exe
/opt/bin/program.exe
              $Id: @(#) Project-trunk Build #343 < $