Jun 20, 2012

Replacing SVN's SubWCRev when using Hg

SubWCRev is a nice tool bundled with Subversion. It allows you to replace tokens in a file with information from the source code repository. I previously blogged about how to use it in Eclipse. I'm not going to repeat all the steps I used for the overall process so if you're wondering what the deal is with version.txt and version.h take a look at that post. Now that I'm switching over to Hg (Mercurial) for Source Code Control I wanted the equivalent functionality.

I couldn't find an exact replacement but since I've been studying up on PowerShell I thought I could leverage it to achieve the goal.

The tutorials I read indicated that typing PowerShell from a command prompt would launch the executable but I found I had to modify my Path environment variable to explicitly include the path:


The new path variable was accessible to the next Command Prompt (the old DOS one) window I opened. It wasn't available to Eclipse until I restarted my machine.

If you've never heard of PowerShell it is the new command line shell and scripting language for Windows. It is integrated with (and requires) .NET. This is a much more modern shell than the old cmd.exe we've all come to know and hate. If you have Windows 7 you already have PowerShell 2.0, if not you can downloaded Windows PowerShell. It's easy to think you have PowerShell 1.0 on Windows 7 because in their infinite goofiness MS put the executable here:


You can always type $Host.Version from a PowerShell command window and it will display the version information.

The PowerShell Script

Hg has a lot of different ways to retrieve the information I want from the repository. I ended up using:

hg tip –template "{rev}:{date|shortdate}

I should point out that I work alone, so the simple rev numbers work for me. If you work on a team, rev numbers are not an adequate way to identify a code release since each clone of the repo can duplicate rev numbers.

I no longer need all the SVN tokens in version.txt so I replaced the line that had them with this:

const char ITS_6100_VERSION[] = "1.0.hgRevision";

The script will replace hgRevision with the revision and date. Keep in mind I'm a beginner in PowerShell scripting so this may not be the best or most elegant approach. Here's the full script:


Here's a harder to read (but easier to copy and paste) text version:

$exe = "C:\Program Files\TortoiseHg\hg.exe"
$my_dir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$vers_text_path = Join-Path $my_dir "version.txt"
$vers_inc_path = Join-Path $my_dir "version.h"
$rev_date = &$exe tip --template "{rev}:{date|shortdate}"
Get-Content $vers_text_path|ForEach-Object{$_ -replace "hgRevision", $rev_date}|Set-Content $vers_inc_path
Write-Host "An error occurred."
Write-Host $_.ErrorID
Write-Host $_.Exception.Message

You can see that $rev_date is holding the results of the hg command. The Get-Content command is loading the version.txt file and looking for the token "hgRevision" and replacing it with the contents of $rev_date. Finally Set-Content writes the result out to version.h. $MyInvocation is a PowerShell variable. The rest of the script is just an attempt to create paths that will work correctly when I use this script in multiple projects. I saved this script off in a file called hgRevAndDate.ps1.

Getting The Script To Run

As a security precaution PowerShell scripts aren't allowed to run by default.  My solution was to set the execution policy right in the command where I run PowerShell. In Eclipse I used the following line:
PowerShell   -executionpolicy  RemoteSigned  ${workspace_loc}\PulseGenLib_hg\hgRevAndDate.ps1
Below you can where this command goes:

When the project is built the version.h file now has this line:

const char ITS_6100_VERSION[] = "1.0.39:2012-06-20";

About Me

My photo
Tod Gentille (@todgentille) is now a Curriculum Director for Pluralsight. He's been programming professionally since well before you were born and was a software consultant for most of his career. He's also a father, husband, drummer, and windsurfer. He wants to be a guitar player but he just hasn't got the chops for it.