Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How good is my method of embedding version numbers into my application using Mercurial hooks?

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...).

like image 530
Sled Avatar asked Apr 01 '10 06:04

Sled


3 Answers

The problem

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.

My solution

What I would suggest is:

  1. Get rid of the "pre-commit" hook and hg forget the version.num file.
  2. Add version.num to your .hgignore file.
  3. Adjust version_gen.sh to consist of:

    hg parent --template "r{node|short}_{date|shortdate}" > version.num

  4. In the makefile, make sure version_gen.sh is run before version.num is used to set the version parameter.

My reasons

As @Ry4an suggests, getting the build system to insert revision information into the software at build time, using information from the Version Control System is a much better option. 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 - in my own build system, the build failed if revision information couldn't be extracted.

Also, as @Kai Inkinen 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.

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

I looked at Mercurials Keyword extension, since it seemed like the obvious solution. However the more I looked at it and read peoples opinions, the more that I came to the conclusion that it wasn't the right thing to do.

I also remember the problems that keyword substitution has caused me in projects at previous companies. ...

Also, I don't particularly want to have to enable Mercurial extensions to get the build to complete. I want the solution to be self contained, so that it isn't easy for the application to be accidentally compiled without the embedded version information just because an extension isn't enabled or the right helper software hasn't been installed.

Then in comments to an answer which suggested using the keyword extension anyway:

... I rejected using the keyword extension as it would be too easy to end up with the string "$Id$" being compiled into the executable. If keyword expansion was built into mercurial rather than an extension, and on by default, I might consider it, but as it stands it just wouldn't be reliable. – Mark Booth

A don't think that there can be a more reliable solution. What if someone accidentally damages .hg or builds not from a clone but from an archive? – Mr.Cat

@Mr.Cat - I don't think there can be a less reliable solution than the keywords extension. Anywhere you haven't explicitly enabled the extension (or someone has disabled it) then you get the literal string "$ID$" compiled into the object file without complaint. If mercurial or the repo is damaged (not sure which you meant) you need to fix that first anyway. As for hg archive, my original solution fails to compile if you try to build it from an archive! That is precisely what I want. I don't want any source to be compiled into our apps without it source being under revision control! – Mark Booth

like image 83
Mark Booth Avatar answered Sep 30 '22 20:09

Mark Booth


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"

like image 32
VonC Avatar answered Sep 30 '22 20:09

VonC


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.

like image 23
Ry4an Brase Avatar answered Sep 30 '22 19:09

Ry4an Brase