Add a fallback path to manually get git commit on VS2022

* Loading LibGit2Sharp.dll by hand in msbuild no longer works in VS2022 due to
  architecture changes. We can fairly reliably get the same result by manually
  reading (and following the ref in) .git/HEAD
This commit is contained in:
baldurk
2022-03-18 13:20:14 +00:00
parent c161f6942c
commit 7a29e6a6bb
+67 -7
View File
@@ -66,9 +66,13 @@
<PropertyGroup>
<LibGit2SharpPath>$([MSBuild]::Unescape("$(DevEnvDir)\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\LibGit2Sharp.dll"))</LibGit2SharpPath>
<LibGit2SharpPath Condition="!exists('$(LibGit2SharpPath)')">$([MSBuild]::Unescape("$(VSInstallDir)\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\LibGit2Sharp.dll"))</LibGit2SharpPath>
<!-- if the path still doesn't work, unset and we'll do manual ref lookups instead -->
<LibGit2SharpPath Condition="!exists('$(LibGit2SharpPath)')"></LibGit2SharpPath>
<!-- on MSBuild 17 (VS2022 and up) the LibGit2Sharp.dll can't load its git dll because of architecture mismatches, so do manual ref lookups -->
<LibGit2SharpPath Condition="'$(MSBuildVersion.Length)' > 0 And '$(MSBuildVersion.Substring(0,2))' >= 17"></LibGit2SharpPath>
</PropertyGroup>
<!-- Declare the task with some inline code -->
<UsingTask TaskName="GetGitCommit" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<UsingTask TaskName="GetGitCommitDotNet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Sha1 ParameterType="System.String" Required="False" Output="True" />
<Repository ParameterType="System.String" Required="True" Output="False" />
@@ -77,14 +81,15 @@
<Task>
<Reference Include="$(LibGit2SharpPath)" />
<Code Type="Class" Language="cs">
<![CDATA[
using System;
using System.Linq;
using System.Runtime.CompilerServices;
namespace GitIntrospection {
public class GetGitCommit : Microsoft.Build.Utilities.Task {
public class GetGitCommitDotNet : Microsoft.Build.Utilities.Task {
public override bool Execute() {
System.AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =&gt; {
System.AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => {
if (args.Name.Contains("LibGit2Sharp")) {
return System.Reflection.Assembly.LoadFrom(LibGit2SharpAssemblyPath);
}
@@ -105,16 +110,71 @@ namespace GitIntrospection {
[Microsoft.Build.Framework.Output] public string Sha1 { get; set; }
}
}
]]>
</Code>
</Task>
</UsingTask>
<UsingTask TaskName="GetGitCommitManual" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Sha1 ParameterType="System.String" Required="False" Output="True" />
<Repository ParameterType="System.String" Required="True" Output="False" />
</ParameterGroup>
<Task>
<Code Type="Class" Language="cs">
<![CDATA[
using System;
using System.IO;
namespace GitIntrospection {
public class GetGitCommitManual : Microsoft.Build.Utilities.Task {
public override bool Execute() {
GetCommit();
return !Log.HasLoggedErrors;
}
private void GetCommit() {
string HEADpath = Repository + ".git\\HEAD";
if(File.Exists(HEADpath)) {
string HEADref = File.ReadAllText(HEADpath).Trim();
if(HEADref.StartsWith("ref: ")) {
string refpath = Repository + ".git\\" + HEADref.Substring(5).Replace('/', '\\');
if(File.Exists(refpath))
Sha1 = File.ReadAllText(refpath).Trim();
} else {
Sha1 = HEADref;
}
}
}
[Microsoft.Build.Framework.Required] public string Repository { get; set; }
[Microsoft.Build.Framework.Output] public string Sha1 { get; set; }
}
}
]]>
</Code>
</Task>
</UsingTask>
<PropertyGroup><DisableFastUpToDateCheck>true</DisableFastUpToDateCheck></PropertyGroup>
<!-- Only actually run the task if we located the assembly for LibGit2Sharp. Otherwise silently skip this step. -->
<Target Name="RunTask" BeforeTargets="PrepareForBuild" Condition="exists('$(LibGit2SharpPath)')">
<GetGitCommit Repository="$(SolutionDir)" LibGit2SharpAssemblyPath="$(LibGit2SharpPath)" ContinueOnError="WarnAndContinue">
<Target Name="RunTaskDotNet" BeforeTargets="PrepareForBuild" Condition="exists('$(LibGit2SharpPath)')">
<GetGitCommitDotNet Repository="$(SolutionDir)" LibGit2SharpAssemblyPath="$(LibGit2SharpPath)" ContinueOnError="WarnAndContinue">
<Output TaskParameter="Sha1" PropertyName="CommitId" />
</GetGitCommit>
<Message Importance="high" Text="Building from Git commit $(CommitId)" />
</GetGitCommitDotNet>
<Message Importance="high" Text="Fetched Git commit: '$(CommitId)'" Condition="$(CommitId.Length) &gt; 0" />
<Message Importance="high" Text="Couldn't fetch git commit" Condition="$(CommitId.Length) == 0" />
<ItemGroup Condition="$(CommitId.Length) &gt; 0">
<ClCompile>
<PreprocessorDefinitions>GIT_COMMIT_HASH="$(CommitId)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemGroup>
</Target>
<!-- Similarly, only run this task if we didn't locate the assembly (or thought we couldn't use it) -->
<Target Name="RunTaskManual" BeforeTargets="PrepareForBuild" Condition="!exists('$(LibGit2SharpPath)')">
<GetGitCommitManual Repository="$(SolutionDir)" ContinueOnError="WarnAndContinue">
<Output TaskParameter="Sha1" PropertyName="CommitId" />
</GetGitCommitManual>
<Message Importance="high" Text="Read Git commit: '$(CommitId)'" Condition="$(CommitId.Length) &gt; 0" />
<Message Importance="high" Text="Couldn't read git commit" Condition="$(CommitId.Length) == 0" />
<ItemGroup Condition="$(CommitId.Length) &gt; 0">
<ClCompile>
<PreprocessorDefinitions>GIT_COMMIT_HASH="$(CommitId)";%(PreprocessorDefinitions)</PreprocessorDefinitions>