Add a custom build task for getting the git version info

Eliminates the need to have a copy of git accessible in the msys
build environment and reduces the dependency on msys to just FFmpeg.

Probably trivially faster due to how slow shell scripts are on Windows.
This commit is contained in:
Thomas Goyne 2014-05-09 12:40:08 -07:00
parent 01dc7f9294
commit 2c0568090c
7 changed files with 131 additions and 64 deletions

View File

@ -30,11 +30,7 @@
<!-- Update git_version.h -->
<Target Name="UpdateVersion" BeforeTargets="ClCompile">
<ExecShellScript
Command="$(MSBuildThisFileDirectory)..\version.sh"
WorkingDirectory="$(AegisubSourceBase)"
Configuration="@(ExecShellScript)"
Arguments="." />
<GitVersion Root="$(AegisubSourceBase)" />
</Target>
<!-- Project References -->

View File

@ -37,6 +37,9 @@
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\..\.nuget\lib\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="LibGit2Sharp">
<HintPath>..\..\.nuget\lib\LibGit2Sharp.0.17.0.0\lib\net35\LibGit2Sharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Build" />
<Reference Include="Microsoft.Build.Engine" />
<Reference Include="Microsoft.Build.Framework" />
@ -52,11 +55,11 @@
<ItemGroup>
<Compile Include="DownloadTgzFile.cs" />
<Compile Include="ExecShellScript.cs" />
<Compile Include="GitVersion.cs" />
<Compile Include="MsysPath.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ShellWrapper.cs" />
<Compile Include="TarballProject.cs" />
<Compile Include="UpdateFile.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>
@ -64,6 +67,14 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<PropertyGroup>
<PostBuildEvent>
if not exist "$(TargetDir)NativeBinaries" md "$(TargetDir)NativeBinaries"
if not exist "$(TargetDir)NativeBinaries\x86" md "$(TargetDir)NativeBinaries\x86"
xcopy /s /y /d "$(SolutionDir).nuget\lib\LibGit2Sharp.0.17.0.0\lib\net35\NativeBinaries\x86\*.*" "$(TargetDir)NativeBinaries\x86"
if not exist "$(TargetDir)NativeBinaries\amd64" md "$(TargetDir)NativeBinaries\amd64"
xcopy /s /y /d "$(SolutionDir).nuget\lib\LibGit2Sharp.0.17.0.0\lib\net35\NativeBinaries\amd64\*.*" "$(TargetDir)NativeBinaries\amd64"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@ -0,0 +1,113 @@
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
using LibGit2Sharp;
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace BuildTasks {
public class GitVersion : Microsoft.Build.Utilities.Task {
public string Root { get; set; }
private static ObjectId LastSVNCommit = new ObjectId("16cd907fe7482cb54a7374cd28b8501f138116be");
private const string versionHTemplate =
@"#define BUILD_GIT_VERSION_NUMBER {0}
#define BUILD_GIT_VERSION_STRING ""{1}""
#define TAGGED_RELEASE {2}
#define INSTALLER_VERSION ""{3}""
";
private const string versionXmlTemplate =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<PropertyGroup>
<GitVersionNumber>{0}</GitVersionNumber>
<GitVersionString>{1}</GitVersionString>
</PropertyGroup>
</Project>
";
private string UniqueAbbreviation(Repository repo, string full) {
for (int len = 7; len < 40; ++len) {
try {
repo.Lookup(full.Substring(0, len));
return full.Substring(0, len);
}
catch (AmbiguousSpecificationException) {
continue;
}
}
return full;
}
private void WriteIfChanged(string path, string template, params object[] args) {
var body = string.Format(template, args).Replace("\r\n", "\n");
try {
var oldBody = File.ReadAllText(path);
if (body != oldBody)
File.WriteAllText(path, body);
}
catch (IOException) {
File.WriteAllText(path, body);
}
}
public override bool Execute() {
string versionHPath = Root + "build/git_version.h";
string versionXmlPath = Root + "build/git_version.xml";
if (!Directory.Exists(Root + ".git")) {
if (File.Exists(versionHPath)) {
Log.LogMessage("Using cached version.h");
return true;
}
Log.LogError("git repo not found and no cached git_version.h");
return false;
}
int commits = 6962; // Rev ID when we switched away from SVN
string installerVersion = "0.0.0";
string versionStr = null;
bool taggedRelease = false;
using (var repo = new Repository(Root + ".git")) {
commits += repo.Commits.TakeWhile(c => !c.Id.Equals(LastSVNCommit)).Count();
foreach (var tag in repo.Tags) {
if (!tag.Target.Id.Equals(repo.Head.Tip.Id)) continue;
taggedRelease = true;
versionStr = tag.Name;
if (versionStr.StartsWith("v")) versionStr = versionStr.Substring(1);
if (Regex.Match(versionStr, @"(\d)\.(\d)\.(\d)").Success)
installerVersion = versionStr;
break;
}
if (versionStr == null) {
string branch = repo.Head.Name ?? "(unnamed branch)";
versionStr = string.Format("{0}-{1}-{2}", commits, branch,
UniqueAbbreviation(repo, repo.Head.Tip.Sha.ToString()));
}
}
WriteIfChanged(versionHPath, versionHTemplate, commits, versionStr, taggedRelease ? "1" : "0", installerVersion);
WriteIfChanged(versionXmlPath, versionXmlTemplate, commits, versionStr);
return true;
}
}
}

View File

@ -1,40 +0,0 @@
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
using Microsoft.Build.Utilities;
using System;
namespace BuildTasks {
public class UpdateFile : Task {
public string File { get; set; }
public string Find { get; set; }
public string Replacement { get; set; }
public override bool Execute() {
try {
this.Log.LogMessage("Replacing '{0}' with '{1}' in '{2}'",
this.Find, this.Replacement, this.File);
var text = System.IO.File.ReadAllText(this.File).Replace(this.Find, this.Replacement);
System.IO.File.WriteAllText(this.File, text);
return true;
}
catch (Exception e) {
this.Log.LogErrorFromException(e);
return false;
}
}
}
}

View File

@ -14,24 +14,10 @@
//
// Aegisub Project http://www.aegisub.org/
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
namespace BuildTasks {
static class Utils {
static public Dictionary<string, string> ReadPropertyMap(IBuildEngine be) {
var reader = XmlReader.Create(be.ProjectFileOfTaskNode);
return new Project(reader).AllEvaluatedProperties
.Where(x => !x.IsEnvironmentProperty)
.Where(x => !x.IsGlobalProperty)
.Where(x => !x.IsReservedProperty)
.ToDictionary(x => x.Name, x => x.EvaluatedValue);
}
/// Convert an absolute windows path to an msys path
static public string MungePath(string path) {
var match = Regex.Match(path, @"([A-Za-z]):\\(.*)");

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="LibGit2Sharp" version="0.17.0.0" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
</packages>

View File

@ -25,6 +25,6 @@
<UsingTask TaskName="ExecShellScript" AssemblyFile="$(AegisubBinaryDir)BuildTasks.dll" />
<UsingTask TaskName="MsysPath" AssemblyFile="$(AegisubBinaryDir)BuildTasks.dll" />
<UsingTask TaskName="UpdateFile" AssemblyFile="$(AegisubBinaryDir)BuildTasks.dll" />
<UsingTask TaskName="GitVersion" AssemblyFile="$(AegisubBinaryDir)BuildTasks.dll" />
</Project>