Skip to content

Instantly share code, notes, and snippets.

@dhilgarth
Last active September 13, 2018 20:34
Show Gist options
  • Save dhilgarth/2fb710f51d20767ccb1a3c25e4b6e412 to your computer and use it in GitHub Desktop.
Save dhilgarth/2fb710f51d20767ccb1a3c25e4b6e412 to your computer and use it in GitHub Desktop.
Facade to read GitVersionInformation injected by GitTools\GitVersion MSBuild task
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
namespace ReadGitVersionInformation
{
public interface IGitVersionInformation
{
string Major { get; }
string Minor { get; }
string Patch { get; }
string PreReleaseTag { get; }
string PreReleaseTagWithDash { get; }
string PreReleaseLabel { get; }
string PreReleaseNumber { get; }
string BuildMetaData { get; }
string BuildMetaDataPadded { get; }
string FullBuildMetaData { get; }
string MajorMinorPatch { get; }
string SemVer { get; }
string LegacySemVer { get; }
string LegacySemVerPadded { get; }
string AssemblySemVer { get; }
string FullSemVer { get; }
string InformationalVersion { get; }
string BranchName { get; }
string Sha { get; }
string NuGetVersionV2 { get; }
string NuGetVersion { get; }
string CommitsSinceVersionSource { get; }
string CommitsSinceVersionSourcePadded { get; }
string CommitDate { get; }
}
public static class GitVersion
{
private static readonly Dictionary<string, IGitVersionInformation> _cache =
new Dictionary<string, IGitVersionInformation>();
public static IGitVersionInformation GetVersionInformation(bool fallbackToNormalVersion = true) =>
GetVersionInformation(Assembly.GetCallingAssembly(), fallbackToNormalVersion);
public static IGitVersionInformation GetVersionInformation(Assembly assembly, bool fallbackToNormalVersion = true)
{
var name = assembly.GetName();
if (_cache.TryGetValue(name.FullName, out var cached))
return cached;
var assemblyName = name.Name;
IGitVersionInformation result;
var gitVersionInformationType = assembly.GetType(assemblyName + ".GitVersionInformation");
if (gitVersionInformationType == null)
{
var informationalVersion = (AssemblyInformationalVersionAttribute)assembly
.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)
.SingleOrDefault();
if (informationalVersion == null)
{
if (fallbackToNormalVersion)
result = new TransparentFallback(assembly);
else
throw new NotAGitVersionAssemblyException(assemblyName);
}
else
result = new GitVersionInformationFromInformationalVersion(informationalVersion.InformationalVersion);
}
else
result = new GitVersionInformationFromClass(gitVersionInformationType.GetFields());
_cache.Add(name.FullName, result);
return result;
}
}
public class NotAGitVersionAssemblyException : Exception
{
public NotAGitVersionAssemblyException(string assemblyName)
: base($"The specified assembly '{assemblyName}' does not contain GitVersion information.") =>
AssemblyName = assemblyName;
public string AssemblyName { get; }
}
internal class GitVersionInformationFromClass : IGitVersionInformation
{
private readonly Dictionary<string, string> _values;
public GitVersionInformationFromClass(IEnumerable<FieldInfo> fields)
{
if (fields == null)
throw new ArgumentNullException(nameof(fields));
_values = fields.ToDictionary(x => x.Name, x => (string)x.GetValue(null));
}
public string Major => GetFieldValue("Major");
public string Minor => GetFieldValue("Minor");
public string Patch => GetFieldValue("Patch");
public string PreReleaseTag => GetFieldValue("PreReleaseTag");
public string PreReleaseTagWithDash => GetFieldValue("PreReleaseTagWithDash");
public string PreReleaseLabel => GetFieldValue("PreReleaseLabel");
public string PreReleaseNumber => GetFieldValue("PreReleaseNumber");
public string BuildMetaData => GetFieldValue("BuildMetaData");
public string BuildMetaDataPadded => GetFieldValue("BuildMetaDataPadded");
public string FullBuildMetaData => GetFieldValue("FullBuildMetaData");
public string MajorMinorPatch => GetFieldValue("MajorMinorPatch");
public string SemVer => GetFieldValue("SemVer");
public string LegacySemVer => GetFieldValue("LegacySemVer");
public string LegacySemVerPadded => GetFieldValue("LegacySemVerPadded");
public string AssemblySemVer => GetFieldValue("AssemblySemVer");
public string FullSemVer => GetFieldValue("FullSemVer");
public string InformationalVersion => GetFieldValue("InformationalVersion");
public string BranchName => GetFieldValue("BranchName");
public string Sha => GetFieldValue("Sha");
public string NuGetVersionV2 => GetFieldValue("NuGetVersionV2");
public string NuGetVersion => GetFieldValue("NuGetVersion");
public string CommitsSinceVersionSource => GetFieldValue("CommitsSinceVersionSource");
public string CommitsSinceVersionSourcePadded => GetFieldValue("CommitsSinceVersionSourcePadded");
public string CommitDate => GetFieldValue("CommitDate");
private string GetFieldValue(string fieldName)
{
if (_values.TryGetValue(fieldName, out var value))
return value;
throw new UnknownGitVersionAssemblyVersion(fieldName);
}
}
internal class GitVersionInformationFromInformationalVersion : IGitVersionInformation
{
private static readonly Regex _regex = new Regex(
@"^(?<Major>\d?)\.(?<Minor>\d?)\.(?<Patch>\d?)-(?<PreReleaseLabel>[^.]+)\.(?<PreReleaseNumber>\d+)\+Branch\.(?<BranchName>[^.]+)\.Sha\.(?<Sha>[0-9a-z]+)$");
public GitVersionInformationFromInformationalVersion(string informationalVersion)
{
InformationalVersion = informationalVersion;
var match = _regex.Match(informationalVersion);
Major = match.Groups["Major"].Value;
Minor = match.Groups["Minor"].Value;
Patch = match.Groups["Patch"].Value;
PreReleaseLabel = match.Groups["PreReleaseLabel"].Value;
PreReleaseNumber = match.Groups["PreReleaseNumber"].Value;
BranchName = match.Groups["BranchName"].Value;
Sha = match.Groups["Sha"].Value;
}
public string Major { get; }
public string Minor { get; }
public string Patch { get; }
public string PreReleaseTag => $"{PreReleaseLabel}.{PreReleaseNumber}";
public string PreReleaseTagWithDash => $"-{PreReleaseTag}";
public string PreReleaseLabel { get; }
public string PreReleaseNumber { get; }
public string BuildMetaData => "";
public string BuildMetaDataPadded => "";
public string FullBuildMetaData => $"Branch.{BranchName}.Sha.{Sha}";
public string MajorMinorPatch => $"{Major}.{Minor}.{Patch}";
public string SemVer => $"{MajorMinorPatch}{PreReleaseTagWithDash}";
public string LegacySemVer => $"{MajorMinorPatch}-{PreReleaseLabel}{PreReleaseNumber}";
public string LegacySemVerPadded => $"{MajorMinorPatch}-{PreReleaseLabel}{CommitsSinceVersionSourcePadded}";
public string AssemblySemVer => $"{MajorMinorPatch}.{PreReleaseNumber}";
public string FullSemVer => SemVer;
public string InformationalVersion { get; }
public string BranchName { get; }
public string Sha { get; }
public string NuGetVersionV2 => LegacySemVerPadded;
public string NuGetVersion => LegacySemVerPadded;
public string CommitsSinceVersionSource => PreReleaseNumber;
public string CommitsSinceVersionSourcePadded => $"{PreReleaseNumber.PadLeft(4, '0')}";
public string CommitDate => new DateTime().ToString("yyyy-dd-MM");
}
internal class TransparentFallback : IGitVersionInformation
{
public TransparentFallback(Assembly assembly)
{
var version = assembly.GetName().Version;
Major = version.Major.ToString();
Minor = version.Minor.ToString();
Patch = version.Revision.ToString();
PreReleaseNumber = version.Build.ToString();
}
public string Major { get; }
public string Minor { get; }
public string Patch { get; }
public string PreReleaseTag => "";
public string PreReleaseTagWithDash => "";
public string PreReleaseLabel => "";
public string PreReleaseNumber { get; }
public string BuildMetaData => "";
public string BuildMetaDataPadded => "";
public string FullBuildMetaData => SemVer;
public string MajorMinorPatch => $"{Major}.{Minor}.{Patch}";
public string SemVer => $"{MajorMinorPatch}{PreReleaseTagWithDash}";
public string LegacySemVer => SemVer;
public string LegacySemVerPadded => $"{MajorMinorPatch}{PreReleaseTagWithDash}{CommitsSinceVersionSourcePadded}";
public string AssemblySemVer => $"{MajorMinorPatch}.{PreReleaseNumber}";
public string FullSemVer => SemVer;
public string InformationalVersion => SemVer;
public string BranchName => "";
public string Sha => "";
public string NuGetVersionV2 => LegacySemVerPadded;
public string NuGetVersion => LegacySemVerPadded;
public string CommitsSinceVersionSource => PreReleaseNumber;
public string CommitsSinceVersionSourcePadded => $"{PreReleaseNumber.PadLeft(4, '0')}";
public string CommitDate => new DateTime().ToString("yyyy-dd-MM");
}
internal class UnknownGitVersionAssemblyVersion : Exception
{
public UnknownGitVersionAssemblyVersion(string fieldName)
: base(
$"The field '{fieldName}' is not a known property of the automatically generated GitVersionInformation class. This most likely hints at a version mismatch.") =>
FieldName = fieldName;
public string FieldName { get; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment