Skip to content

Instantly share code, notes, and snippets.

@AraHaan
Created November 21, 2019 04:59
Show Gist options
  • Save AraHaan/a317bddce50e165e1d6245b8a206064c to your computer and use it in GitHub Desktop.
Save AraHaan/a317bddce50e165e1d6245b8a206064c to your computer and use it in GitHub Desktop.
namespace GitBuildInfo
{
/// <summary>
/// A MSBuild task that generates the msbuild information for an assembly.
///
/// Note: use in the BeforeBuild target.
/// </summary>
public class GitBuildInfoGenericTask : GitBuildInfoTask
{
/// <inheritdoc/>
public override bool Execute()
{
this.isGeneric = true;
return base.Execute();
}
}
}
namespace GitBuildInfo
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// A MSBuild task that generates the msbuild information for an assembly.
///
/// Note: use in the BeforeBuild target.
/// </summary>
public class GitBuildInfoTask : Task
{
internal bool isGeneric = false;
/// <summary>
/// Gets or sets the generated output file path.
/// </summary>
[Required]
public string OutputPath { get; set; }
/// <summary>
/// Gets or sets the type to use to get the current assembly to that the attribute is applied to.
/// </summary>
[Required]
public string AssemblyType { get; set; }
/// <inheritdoc/>
public override bool Execute()
{
var splitted = this.AssemblyType.Contains(".") ? this.AssemblyType.Split('.') : new string[] { };
var splittedLen = splitted.Length;
var usingStr = string.Empty;
foreach (var value in splitted)
{
// skip the last value.
if (value != splitted[splittedLen - 1])
{
if (value != splitted[0])
{
usingStr += ".";
}
usingStr += value;
}
}
RunGit("describe --all --always --dirty", out var git_out1);
RunGit("rev-parse --short HEAD", out var git_out2);
RunGit("name-rev --name-only HEAD", out var git_out3);
var outputData = $@"//------------------------------------------------------------------------------
// <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>
//------------------------------------------------------------------------------
{(splittedLen > 0 ? $"using {usingStr};{Environment.NewLine}" : string.Empty)}using System.Runtime.InteropServices;
[assembly: GitInformationAttribute(""{git_out1}"", ""{git_out2}"", ""{git_out3}"", typeof({(splittedLen > 0 ? splitted[splittedLen - 1] : this.AssemblyType)}{(this.isGeneric ? "<>" : "")}))]
";
// patch 112019: only print the getting build info from git message from the initial call to this task.
// all other calls will not print anything to avoid spamming up the build output.
if (!File.Exists(this.OutputPath) || !string.Equals(outputData, File.ReadAllText(this.OutputPath)))
{
this.Log.LogMessage(MessageImportance.High, "Getting build info from git");
try
{
using (var fstream = new StreamWriter(this.OutputPath, false, new UTF8Encoding(false)))
{
fstream.Write(outputData.ToCharArray(), 0, outputData.Length);
}
}
catch (IOException)
{
}
}
return true;
}
private static void RunGit(string arguments, out string git_out)
{
using (var pro1 = new Process())
{
pro1.StartInfo.FileName = "git";
pro1.StartInfo.Arguments = arguments;
pro1.StartInfo.RedirectStandardOutput = true;
pro1.StartInfo.UseShellExecute = false;
pro1.StartInfo.CreateNoWindow = true;
try
{
_ = pro1.Start();
git_out = pro1.StandardOutput.ReadToEnd();
pro1.WaitForExit();
// handle all cases of possible endlines.
git_out = git_out.Replace("\r\n", string.Empty);
git_out = git_out.Replace("\n", string.Empty);
git_out = git_out.Replace("\r", string.Empty);
// git_out = git_out.Remove(git_out.Length - 1, 1);
}
catch (Win32Exception)
{
git_out = "Not a git clone or git is not in Path.";
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment