views:

362

answers:

4

This is not quite a specifc question, and more me like for a criticism of my current approach.

I would like to include the program version number in the program I am developing. This is not a commercial product, but a research application so it is important to know which version generated the results.

My method works as follows:

  1. There is a "pre-commit" hook in my .hg/hgrc file link to version_gen.sh
  2. version_gen.sh consists solely of: hg parent --template "r{rev}_{date|shortdate}" > version.num
  3. In the makefile, the line version="%__VERSION__% in the main script is replaced with the content of the version.num file.

Are there better ways of doing this? The only real short coming I can see is that if you only commit a specfic file, version.num will be updated, but it won't be commited, and if I tried to add always committing that file, that would result in an infite loop (unless I created some temp file to indicate I was already in a commit, but that seems ugly...).

A: 

What you are trying to do is called Keyword Expansion, which is not supported in Mercurial core.

You can integrate that expansion in make file, or (simpler) with the Keyword extension.

This extension allows the expansion of RCS/CVS-like and user defined keys in text files tracked by Mercurial.
Expansion takes place in the working directory or/and when creating a distribution using "hg archive"

VonC
Within the realms of vanilla Mercurial how would you judge my workaround?Also, I had never heard of keyword expansion before (and I had used CVS for a whle). Could to know that there is at least a name for what I am trying to emulate!
ArtB
@ArtB: keyword expansion goes way back ;) See http://stackoverflow.com/questions/645008/what-are-the-basic-clearcase-concepts-every-developer-should-know/645424#645424. As for your hook, I would rather use the Mercurial Keyword extension to be sure to have its configuration (about what you want to substitute) clearly recorded in the hgrc config file.
VonC
@VonC The official stance on keyword, is that Artb way of doing it the best way to do it. This should be the job of the build system, not the job of hg.@Artb: the way you're doing is very close to the way mercurial itself does it.
tonfa
@tonfa: interesting. That makes sense.
VonC
A: 

In distributed systems like Mercurial, the actual "version number" does not necessarily mean the same thing in every environment. Even if this is a single person project, and you are really careful with having only your central repo, you would still probably want to use the sha1-sum instead, since that is truly unique for the given repository state. The sha1 can be fetched through the template {node}

As a suggestion, I think that a better workflow would be to use tags instead, which btw are also local to your repository until you push them upstream. Don't write your number into a file, but instead tag your release code with a meaningful tag like
RELEASE_2
or
RELEASE_2010-04-01
or maybe script this and use the template to create the tag?

You can then add the tag to your non-versioned (in .hgignore) version.num file to be added into the build. This way you can give meaningful names to the releases and you tie the release to the unique identifier.

Kai Inkinen
+1  A: 

That you use a pre-commit hook is what's concerning. You shouldn't be putting the rest of version_gen.sh into the source files thesemves, just into the build/release artifacts which you can do more accurately with an 'update' hook.

You don't want the Makefile to actually change in the repo with each commit, that just makes merges hell. You want to insert the version after checking out the files in advance of a build, which is is what an update hook does.

Ry4an
+1  A: 

As you've identified, you've really created a Catch-22 situation here.

You can't really put meaningful information in the version.num file until the changes are committed and because you are storing version.num in the repository, you can't commit changes to the repository until you have populated the version.num file.

As @Ry4an suggests, a better solution would be for the build system to insert revision information into the software at build time, using information from the Version Control System.

The only problem with this is if you try to compile the code from an hg archive of the repository, where the build system cannot extract the relevant information. I would be inclined to discourage this however and in my own build system, the build fails if revision information can't be extracted.

Also, as @aapeli suggests, using the revision number is not portable. Rev 21 on one machine might be rev 22 on another. While this may not be a problem right now, it could be in the future, if you start colaborating with other people.

What I would suggest is:

  1. Get rid of the "pre-commit" hook and hg forget the version.num file.
  2. Adjust version_gen.sh to consist of: hg parent --template "r{node|short}_{date|shortdate}" > version.num
  3. In the makefile, make sure version_gen.sh is run before version.num is used to set the version parameter.

Incidentally, I explain my reasons for not liking the Keyword extension in a question of my own, which touches on similar issues to your own question.

Mark Booth