26

Is there any way to include the SVN repository revision number in the version string of a .NET assembly? Something like Major.Minor.SVNRev

I've seen mention of doing this with something like CC.NET (although on ASP.NET actually), but is there any way to do it without any extra software? I've done similar things in C/C++ before using build batch scripts, but in was accomplished by reading the version number, then having the script write out a file called "ver.h" everytime with something to the effect of:

#define MAJORVER 4
#define MINORVER 23
#define SOURCEVER 965

We would then use these defines to generate the version string.

Is something like this possible for .NET?

DevelopingChris
  • 39,797
  • 30
  • 87
  • 118
Adam Haile
  • 30,705
  • 58
  • 191
  • 286
  • This one is excellent - both date and svn version number http://www.fatlemon.co.uk/2011/11/wtv-automatic-date-based-version-numbering-for-net-with-whentheversion/ – Tim Feb 10 '12 at 19:29
  • The link above may not load right. the github url is in my answer below. - For a solution that uses date AND svn rev number. – Tim Feb 11 '12 at 03:06
  • 1
    Stackoverflow show the revision number en the footer, maybe Jeff can tell us how he do this. – Jedi Master Spooky Aug 15 '08 at 12:43
  • see my answer - there is a github project that does the same – Tim Feb 10 '12 at 19:36

8 Answers8

32

Here's and C# example for updating the revision info in the assembly automatically. It is based on the answer by Will Dean, which is not very elaborate.

Example :

  1. Copy AssemblyInfo.cs to AssemblyInfoTemplate.cs in the project's folder Properties.
  2. Change the Build Action to None for AssemblyInfoTemplate.cs.
  3. Modify the line with the AssemblyFileVersion to:

    [assembly: AssemblyFileVersion("1.0.0.$WCREV$")]

  4. Consider adding:

    [assembly: AssemblyInformationalVersion("Build date: $WCNOW=%Y-%m-%d %H:%M:%S$; Revision date: $WCDATE=%Y-%m-%d %H:%M:%S$; Revision(s) in working copy: $WCRANGE$$WCMODS?; WARNING working copy had uncommitted modifications:$.")],

    which will give details about the revision status of the source the assembly was build from.

  5. Add the following Pre-build event to the project file properties:

    subwcrev "$(SolutionDir)." "$(ProjectDir)Properties\AssemblyInfoTemplate.cs" "$(ProjectDir)Properties\AssemblyInfo.cs" -f

  6. Consider adding AssemblyInfo.cs to the svn ignore list. Substituted revision numbers and dates will modify the file, which results in insignificant changes and revisions and $WCMODS$ will evaluate to true. AssemblyInfo.cs must, of course, be included in the project.

In response to the objections by Wim Coenen, I noticed that, in contrast to what was suggested by Darryl, the AssemblyFileVersion also does not support numbers above 2^16. The build will complete, but the property File Version in the actual assembly will be AssemblyFileVersion modulo 65536. Thus, 1.0.0.65536 as well as 1.0.0.131072 will yield 1.0.0.0, etc. In this example, there is always the true revision number in the AssemblyInformationalVersion property. You could leave out step 3, if you consider this a significant issue.

Edit: some additional info after having used this solution for a while.

  1. It now use AssemblyInfo.cst rather than AssemblyInfoTemplate.cs, because it will automatically have Build Action option None, and it will not clutter you Error list, but you'll loose syntax highlighting.
  2. I've added two tests to my AssemblyInfo.cst files:

    #if(!DEBUG)    
        $WCMODS?#error Working copy has uncommitted modifications, please commit all modifications before creating a release build.:$ 
    #endif 
    #if(!DEBUG)       
        $WCMIXED?#error Working copy has multiple revisions, please update to the latest revision before creating a release build.:$ 
    #endif
    

    Using this, you will normally have to perform a complete SVN Update, after a commit and before you can do a successful release build. Otherwise, $WCMIXED will be true. This seems to be caused by the fact that the committed files re at head revision after the commit, but other files not.

  3. I have had some doubts whether the first parameter to subwcrev, "$(SolutionDir)", which sets the scope for checking svn version info, does always work as desired. Maybe, it should be $(ProjectDir), if you are content if each individual assembly is in a consistent revision.

Addition To answer the comment by @tommylux.

SubWcRev can be used for any file in you project. If you want to display revision info in a web page, you could use this VersionInfo template:

public class VersionInfo
{       
    public const int RevisionNumber = $WCREV$;
    public const string BuildDate = "$WCNOW=%Y-%m-%d %H:%M:%S$";
    public const string RevisionDate = "$WCDATE=%Y-%m-%d %H:%M:%S$";
    public const string RevisionsInWorkingCopy = "$WCRANGE$";
    public const bool UncommitedModification = $WCMODS?true:false$;
}

Add a pre-build event just like the one for AssemblyInfo.cst and you will have easy access to all relevant SubVersion info.

R. Schreurs
  • 8,587
  • 5
  • 43
  • 62
  • Agree, this is the right answer, not just a link to information about a tool one can use. – soupdog Dec 13 '13 at 21:59
  • 1
    Can you elaborate this second part. I dob't fully understand it. You renamed AssemblyInfo.cs to AssemblyInfo.cst? Or? What's happening to template? Where did you add these new tests? In what part of file? Great answer btw! – 100r Feb 02 '14 at 22:27
  • @100r, I corrected the file names I wrote down wrongly. I hope this will solve your confusion. If not, please let me know. – R. Schreurs Feb 04 '14 at 10:25
  • This looks really good, but how would you then print this in an ASP Page? ie: <%$ Properties: AssemblyVersion%> – tommylux Sep 22 '17 at 09:30
  • @tommylux 1) You could use the solution provided in [How can I get the executing assembly version?](https://stackoverflow.com/a/4941305/456456) – R. Schreurs Sep 22 '17 at 10:55
  • @tommylux 2) see my addition to the answer. – R. Schreurs Sep 22 '17 at 10:55
  • Thanks for getting back. I couldn't see how to get this to work in a class. I'm not overly familiar with Classes. Error ";" expected. WCREV does not exist in current context. I did add Reflection in my references. However, I did manage to print this the required by using: RevisionInfo.InnerText = System.Diagnostics.FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion.ToString(); This appears to have the correct build number from Subversion. Thanks to your Answer I have this working though I must admit, don't quite understand how AssemblyInfo.cst is called. – tommylux Sep 22 '17 at 11:54
  • 1
    Looks like I've figured out your class thing. I guess it was because I didn't know how the cst file worked. When you put Public Class VersionInfo in the cst, on build, this will populate the cs file and then it becomes usable in the project with the translated version info from source control.. Thanks again. – tommylux Sep 22 '17 at 13:17
10

It is possible but you shouldn't: the components of the assembly version string are limited to 16-bit numbers (max 65535). Subversion revision numbers can easily become bigger than that so at some point the compiler is suddenly going to complain.

Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
  • 2
    Good point. At 20 commits per day this will last for 8 years. 100 commits will last less than 2 years. It may be fine for small projects. Certainly not good for large ones. – Tim Feb 10 '12 at 19:39
  • @Tim, only if project members are working full time 7 days a week :-) Assuming a 5 day work week, the estimates are 13 and 2,6 years, respectively. For the former case, the difference may be significant. – Péter Török Jun 20 '12 at 08:41
  • 2
    Plus you should only change the assembly version if it breaks compatibility with the previous version - you shouldn't put build version info into the assembly version. Build version info can and should be put into the AssemblyFileVersion, which DOES support 32-bit numbers. See http://stackoverflow.com/questions/64602. – Darryl Nov 01 '12 at 16:58
  • -1, this is not a very good reason. 65536 commits is not a practical limitation for most products. And even for products that do exceed that number, the major-minor-rev ought to give enough context to "unwrap" the revision to the right value (you certainly aren't going to have 64k commits for each revision of your app if you are versioning sensibly). – soupdog Dec 13 '13 at 22:04
  • @soupdog: Your suggestion for "unwrapping" a revision is a good one that I have considered myself. It complicates things a bit though, as you need to choose an offset to subtract from the revision and remember to check whether the offset needs to be updated each time the `major.minor` changes. It's one more thing to maintain. When you have repositories with tens of thousands of revisions like in our case, cognitive load is an issue. – Wim Coenen Dec 14 '13 at 13:43
  • @WimCoenen: I don't think it's as complicated as that. By major-minor-rev giving you enough context, what I mean is it ought to be easy enough to (manually) identify the realm of SVN revisions you are in by looking at those first three numbers, and then you can resolve how many times to add 65536 to the build number to get the absolute SVN revision. I guess it depends on how you want to use the information and what level of automation is required. At any rate, I was mostly disagreeing with the blanket statement that "you shouldn't", because for most people it ought to be an adequate scheme. – soupdog Dec 17 '13 at 18:24
  • You can also specify a negative offset. From the [SubWcRev manual, chapter 6](http://tortoisesvn.net/docs/nightly/TortoiseSVN_en/tsvn-subwcrev-keywords.html): _$WCREV-$, $WCREV+$ Replaced with the highest commit revision in the working copy, with the value after the + or - char added or subtracted. For example: $WCREV-1000$_. This could used to reset/lower the revision number after, e.g, the major has been increased. – R. Schreurs Jun 26 '15 at 13:31
6

Have a look at SubWCRev - http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-subwcrev.html

The assembly version numbers are usually in assemblyinfo.cs

Will Dean
  • 39,055
  • 11
  • 90
  • 118
5

Read/skim these docs:

Accessing the Subversion repository from .NET using DotSVN

How to: Write a Task

Insert SVN version and Build number in your C# AssemblyInfo file

Compiling Apps With Custom Tasks For The Microsoft Build Engine

The MSBuildCommunityTasks svnversion mentioned in third reference would not perform with svn on Mac 10.5.6 and VS2008 C# project build inside Parallels hosting Vista (ie., across OS).

Write your own task to retrieve revision from repository using DotSVN:

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using DotSVN.Common;
using DotSVN.Common.Entities;
using DotSVN.Common.Util;
using DotSVN.Server.RepositoryAccess;

namespace GetSVNVersion
{
    public class GetRevision : Task
    {
        [Required]
        public string Repository { get; set; }
        [Output]
        public string Revision { get; set; }

        public override bool Execute()
        {
            ISVNRepository repo;
            bool connected = true;
            try
            {
                repo = SVNRepositoryFactory.Create(new SVNURL(Repository));
                repo.OpenRepository();
                Revision = repo.GetLatestRevision().ToString();
                Log.LogCommandLine(Repository + " is revision " + Revision);
                repo.CloseRepository();
            }
            catch(Exception e)
            {
                Log.LogError("Error retrieving revision number for " + Repository + ": " + e.Message);
                connected = false;
            }
            return connected;
        }
    }
}

This way allows the repository path to be "file:///Y:/repo" where Y: is a Mac directory mapped into Vista.

  • 3
    Unfortunately dotSVN is no longer maintained and one of the things that was left out was repositories on http. – Martin Jun 02 '10 at 09:50
4

Another answer mentioned that SVN revision number might not be a good idea because of the limit on the size of the number.

The following link provides not only an SNV revision number, but also a date version info template.

Adding this to a .NET project is simple - very little work needs to be done.

Here is a github project that addresses this https://github.com/AndrewFreemantle/When-The-Version/downloads

The following url may load slowly but is a step-by-step explanation of how to make this work (easy and short 3 or 4 steps)

http://www.fatlemon.co.uk/2011/11/wtv-automatic-date-based-version-numbering-for-net-with-whentheversion/

Tim
  • 20,184
  • 24
  • 117
  • 214
2

svn info, tells you the version you are on, you can make a "pre-build" event in VS on your project to generate the assemblyinfo.cs by running svn info and parsing its results with a home grown command line app.

I have done this before, but quickly switched to just having ccnet pass it as a variable to nant.

DevelopingChris
  • 39,797
  • 30
  • 87
  • 118
2

If you want to update the version number in a projects AssemblyInfo.cs you may be interested in this article:

CodeProject: Use Subversion Revision numbers in your Visual Studio Projects

If you enable SVN Keywords then every time you check in the project Subversion scans your files for certain "keywords" and replaces the keywords with some information.

For example, At the top of my source files I would create a header contain the following keywords:

'$Author:$
'$Id:$
'$Rev:$

When I check this file into Subversion these keywords are replaced with the following:

'$Author: paulbetteridge $
'$Id: myfile.vb 145 2008-07-16 15:24:29Z paulbetteridge $
'$Rev: 145 $

Eric Schoonover
  • 47,184
  • 49
  • 157
  • 202
  • 4
    from that article: "The limitation of using the $Rev$ keyword is that it only gives you the revision of the file and not the entire project so using $rev$ keyword cannot work as part of my software versioning." so you would have to edit/commit assembly.cs on every revision to keep it updated? – Lucas May 30 '09 at 05:40
0

You can use a shared Assembly Version file that you can reference in all of your projects.

UppercuT does this - http://ferventcoder.com/archive/2009/05/21/uppercut---automated-builds---versionbuilder.aspx

This will give you an idea of what you can do to get versions in your assemblies.

ferventcoder
  • 11,952
  • 3
  • 57
  • 90