Aegisub/build/BuildTasks/GitVersion.cs

118 lines
4.6 KiB
C#

// 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}""
#define RESOURCE_BASE_VERSION {4}
";
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 resourceVersion = "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;
resourceVersion = versionStr.Replace(".", ", ");
}
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, resourceVersion);
WriteIfChanged(versionXmlPath, versionXmlTemplate, commits, versionStr);
return true;
}
}
}