Search code examples
c#.netgitcommand-lineversioning

Is there a C# commandline command one-liner which can help me get the GIT commit hash of an application?


This question is a follow-up of this other one.

In that question, one mentions the usage of [assembly: AssemblyVersion(...)] to the file AssemblyInfo.cs file, and in the meanwhile I've found out that it's forbidden to execute any processing before such a line, the only thing which is allowed is something like:

[assembly: AssemblyVersion("1.0.0.0" + "-" + Namespace.Class.Attribute)], or:
[assembly: AssemblyVersion("1.0.0.0" + "-" + Namespace.Class.Method())]

Original question:
So my question: is there a Namespace.Class.Attribute or Namespace.Class.Method() which contains the commit hash (or sha or shortened sha) of a C# application?

Edit after more investigation
In the meantime I've learnt that the command git describe --always gives me the information I'm looking for, so what I need is something like:

[assembly: AssemblyVersion("1.0.0.0-" + Launch("git describe --always")]

... but how can I execute that Launch()?

I already know that I can launch a commandline command using System.Diagnostics.Process(), like this example:

System.Diagnostics.Process.Start(foldervar + "application.exe", "inputfile.txt");

... but this way does not catch the result of that command.

New question:
So, does anybody know a C# one-liner for launching commandline commands and getting their result?

Thanks in advance


Solution

  • Instead of using the AssemblyVersionAttribute, you can now use MsBuild properties to set the version (among other attributes). The advantage of using MsBuild, is that you can calculate these values as part of the build process.

    This will work for any "new style"/"SDK style" project.

    Check out: Assembly attribute properties.

    You'll end up with something along these lines:

    ConsoleApp5.csproj:
    
    <Project Sdk="Microsoft.NET.Sdk">
    
        <PropertyGroup>
            <OutputType>Exe</OutputType>
            <TargetFramework>net6.0</TargetFramework>
            <ImplicitUsings>enable</ImplicitUsings>
            <Nullable>enable</Nullable>
        </PropertyGroup>
    
        <!-- Add the property group and the target below to your project file -->
        <PropertyGroup>
            <GenerateAssemblyVersionAttribute>true</GenerateAssemblyVersionAttribute>
            <GenerateAssemblyFileVersionAttribute>true</GenerateAssemblyFileVersionAttribute>
            <GenerateAssemblyInformationalVersionAttribute>true</GenerateAssemblyInformationalVersionAttribute>
        </PropertyGroup>
    
        <Target Name="AddGitShaToAssemblyVersions" BeforeTargets="GetAssemblyVersion" Returns="AssemblyVersion, FileVersion, InformationalVersion">
            <Exec ConsoleToMsBuild="true" Command="git describe --always">
                <Output TaskParameter="ConsoleOutput" PropertyName="GitSha" />
            </Exec>
    
            <PropertyGroup>
                <AssemblyVersion>1.1.1.1</AssemblyVersion>
                <FileVersion>1.1.1.1-$(GitSha)</FileVersion>
                <InformationalVersion>1.1.1.1-$(GitSha)</InformationalVersion>
            </PropertyGroup>
        </Target>
    
        <!-- Ignore the warning generated for the AssemblyFileVersion -->
        <PropertyGroup>
          <NoWarn>$(NoWarn);7035</NoWarn>
        </PropertyGroup>
    </Project>
    

    A file is generated in the obj folder and it's automatically included in the build. You can open this file in your editor to look at the generated content:

    enter image description here

    Generated content:

    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated by a tool.
    //     Runtime Version:4.0.30319.42000
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    using System;
    using System.Reflection;
    
    [assembly: System.Reflection.AssemblyCompanyAttribute("ConsoleApp5")]
    [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
    [assembly: System.Reflection.AssemblyFileVersionAttribute("1.1.1.1-3654148")]
    [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.1.1.1-3654148")]
    [assembly: System.Reflection.AssemblyProductAttribute("ConsoleApp5")]
    [assembly: System.Reflection.AssemblyTitleAttribute("ConsoleApp5")]
    [assembly: System.Reflection.AssemblyVersionAttribute("1.1.1.1")]
    
    // Generated by the MSBuild WriteCodeFragment class.
    

    To me the advantage is that all of the logic is nicely encapsulated in the build files themselves and won't depend on my having to run any commands prior to build or putting build logic into another script, like a powershell script, scripts that Visual Studio isn't aware of.

    Do make sure you remove your existing, manually added, AssemblyVersion etc attributes from your project, or you'll end up with a warning the attribute was specified twice.