diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj
index ebb4e6db9a..7c90351d5d 100644
--- a/src/GitVersionCore/GitVersionCore.csproj
+++ b/src/GitVersionCore/GitVersionCore.csproj
@@ -105,5 +105,39 @@
Designer
-
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/GitVersionCore/GitVersionInformationResources/AddFormats/GitVersionInformation.h b/src/GitVersionCore/GitVersionInformationResources/AddFormats/GitVersionInformation.h
new file mode 100644
index 0000000000..6e959d454d
--- /dev/null
+++ b/src/GitVersionCore/GitVersionInformationResources/AddFormats/GitVersionInformation.h
@@ -0,0 +1 @@
+#define {0} {1}
\ No newline at end of file
diff --git a/src/GitVersionCore/GitVersionInformationResources/Templates/GitVersionInformation.h b/src/GitVersionCore/GitVersionInformationResources/Templates/GitVersionInformation.h
new file mode 100644
index 0000000000..b2cf273d3d
--- /dev/null
+++ b/src/GitVersionCore/GitVersionInformationResources/Templates/GitVersionInformation.h
@@ -0,0 +1,27 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// GitVersion
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#pragma once
+
+//------------------------------------------------------------------------------
+//What the values SHOULD look like after the template is applied:
+//#define VERSION_FULL MAJORVERSION,MINORVERSION,BUILDVERSION,REVISIONVERSION
+//#define VERSION_STRING VERSION_XSTR(MAJORVERSION.MINORVERSION.BUILDVERSION.REVISIONVERSION-REVISIONHASH) VERSION_BLANK "\0"
+
+//NOTE: The trailing "\0" is VERY important
+
+//------------------------------------------------------------------------------
+
+#define VERSION_STR(x) #x
+#define VERSION_XSTR(x) VERSION_STR(x)
+#define VERSION_BLANK ""
+
+#define VERSION_FULL 0,0,0,1
+#define VERSION_STRING VERSION_XSTR(0.0.0.1) VERSION_BLANK "\0"
diff --git a/src/GitVersionCore/TemplateManager.cs b/src/GitVersionCore/TemplateManager.cs
index 2613dc282d..5bb6a323cb 100644
--- a/src/GitVersionCore/TemplateManager.cs
+++ b/src/GitVersionCore/TemplateManager.cs
@@ -7,13 +7,14 @@
using GitVersionCore.Extensions;
using System.Reflection;
- enum TemplateType
+ public enum TemplateType
{
VersionAssemblyInfoResources,
- GitVersionInformationResources
+ GitVersionInformationResources,
+ NativeHeader,
}
- class TemplateManager
+ public class TemplateManager
{
readonly Dictionary templates;
readonly Dictionary addFormats;
@@ -89,4 +90,4 @@ static IEnumerable GetEmbeddedTemplates(TemplateType templateType, strin
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/GitVersionTask/GenerateGitVersionInformation.cs b/src/GitVersionTask/GenerateGitVersionInformation.cs
index 8abaa5a97d..2bf582b557 100644
--- a/src/GitVersionTask/GenerateGitVersionInformation.cs
+++ b/src/GitVersionTask/GenerateGitVersionInformation.cs
@@ -88,14 +88,17 @@ string GetFileExtension()
{
switch (Language)
{
- case "C#":
- return "cs";
+ case SupportedLanguageConstants.CSHARP:
+ return SupportedLanguageConstants.FILEEXTENSION_CSHARP;
- case "F#":
- return "fs";
+ case SupportedLanguageConstants.FSHARP:
+ return SupportedLanguageConstants.FILEEXTENSION_FSHARP;
- case "VB":
- return "vb";
+ case SupportedLanguageConstants.VBDOTNET:
+ return SupportedLanguageConstants.FILEEXTENSION_VBDOTNET;
+
+ case SupportedLanguageConstants.CPLUSPLUS:
+ return SupportedLanguageConstants.FILEEXTENSION_CPLUSPLUS;
default:
throw new Exception($"Unknown language detected: '{Language}'");
diff --git a/src/GitVersionTask/GitVersionTask.csproj b/src/GitVersionTask/GitVersionTask.csproj
index 6da556cace..06609ed62a 100644
--- a/src/GitVersionTask/GitVersionTask.csproj
+++ b/src/GitVersionTask/GitVersionTask.csproj
@@ -92,8 +92,26 @@
-
-
+
+ ..\packages\YamlDotNet.3.8.0\lib\net35\YamlDotNet.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/GitVersionTask/NugetAssets/build/GitVersionTask.targets b/src/GitVersionTask/NugetAssets/build/GitVersionTask.targets
index 1d50060976..e9bc3b99d9 100644
--- a/src/GitVersionTask/NugetAssets/build/GitVersionTask.targets
+++ b/src/GitVersionTask/NugetAssets/build/GitVersionTask.targets
@@ -1,5 +1,40 @@
-
+
+
+
+ True
+
+
+
+ false
+ true
+
+
+
+ $(MSBuildProjectDirectory)\..\
+ $(SolutionDir)
+ $(MSBuildProjectDirectory)
+ $(SolutionDir)\GitVersionTask.targets
+ $(SolutionDir)\GitVersionTask.targets
+
+ $(MSBuildProjectDirectory)\obj\$(Configuration)\
+ false
+
+
+ false
+ true
+
+
+ false
+ false
+ true
+ false
+
+
+ false
+ true
+
+
@@ -9,10 +44,143 @@
false
true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(GitVersion_FullSemVer)
+ $(GitVersion_MajorMinorPatch)
+ $(GitVersion_NuGetPreReleaseTag)
+ $(GitVersion_PreReleaseTag)
+ $(GitVersion_NuGetVersion)
+ $(GitVersion_FullSemVer)
+ $(GitVersion_InformationalVersion)
+ $(GitVersion_AssemblySemVer)
+ $(GitVersion_AssemblySemFileVer)
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
-
\ No newline at end of file
diff --git a/src/GitVersionTask/SupportedLanguageConstants.cs b/src/GitVersionTask/SupportedLanguageConstants.cs
new file mode 100644
index 0000000000..4555d82419
--- /dev/null
+++ b/src/GitVersionTask/SupportedLanguageConstants.cs
@@ -0,0 +1,31 @@
+namespace GitVersionTask
+{
+ internal static class SupportedLanguageConstants
+ {
+ internal const string VBDOTNET = "VB";
+ internal const string FSHARP = "F#";
+ internal const string CSHARP = "C#";
+ internal const string CPLUSPLUS = "C++";
+
+ internal static readonly string[] SUPPORTED_LANGUAGES =
+ {
+ VBDOTNET,
+ CSHARP,
+ FSHARP,
+ CPLUSPLUS,
+ };
+
+ internal const string FILEEXTENSION_VBDOTNET = "vb";
+ internal const string FILEEXTENSION_CSHARP = "cs";
+ internal const string FILEEXTENSION_FSHARP = "fs";
+ internal const string FILEEXTENSION_CPLUSPLUS = "h";
+
+ internal static readonly string[] SUPPORTED_LANGUAGE_FILEEXTENSIONS =
+ {
+ FILEEXTENSION_VBDOTNET,
+ FILEEXTENSION_CSHARP,
+ FILEEXTENSION_FSHARP,
+ FILEEXTENSION_CPLUSPLUS,
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/GitVersionTask/UpdateAssemblyInfo.cs b/src/GitVersionTask/UpdateAssemblyInfo.cs
index b299fcbc93..abbaf3d777 100644
--- a/src/GitVersionTask/UpdateAssemblyInfo.cs
+++ b/src/GitVersionTask/UpdateAssemblyInfo.cs
@@ -102,14 +102,14 @@ string GetFileExtension()
{
switch(Language)
{
- case "C#":
- return "cs";
+ case SupportedLanguageConstants.CSHARP:
+ return SupportedLanguageConstants.FILEEXTENSION_CSHARP;
- case "F#":
- return "fs";
+ case SupportedLanguageConstants.FSHARP:
+ return SupportedLanguageConstants.FILEEXTENSION_FSHARP;
- case "VB":
- return "vb";
+ case SupportedLanguageConstants.VBDOTNET:
+ return SupportedLanguageConstants.FILEEXTENSION_VBDOTNET;
default:
throw new Exception($"Unknown language detected: '{Language}'");
diff --git a/src/GitVersionTask/UpdateNativeVersionHeader.cs b/src/GitVersionTask/UpdateNativeVersionHeader.cs
new file mode 100644
index 0000000000..a3c650a754
--- /dev/null
+++ b/src/GitVersionTask/UpdateNativeVersionHeader.cs
@@ -0,0 +1,310 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace GitVersionTask
+{
+ using System.IO;
+ using System.Text.RegularExpressions;
+ using GitTools;
+ using GitVersion;
+ using GitVersion.Helpers;
+ using Microsoft.Build.Framework;
+
+ public sealed class UpdateNativeVersionHeader : GitVersionTaskBase
+ {
+ private TaskLogger logger;
+
+ public UpdateNativeVersionHeader()
+ {
+/*
+ #if DEBUG
+ if (!System.Diagnostics.Debugger.IsAttached)
+ {
+ System.Diagnostics.Debugger.Launch();
+ }
+#endif
+*/
+
+ logger = new TaskLogger(this);
+ Logger.SetLoggers(this.LogDebug, this.LogInfo, this.LogWarning, s => this.LogError(s));
+ }
+
+ [Required]
+ public string SolutionDirectory { get; set; }
+
+ [Required]
+ public string ProjectFile { get; set; }
+
+ [Required]
+ public string IntermediateOutputPath { get; set; }
+
+ [Required]
+ public ITaskItem[] CompileFiles { get; set; }
+
+ //Only "C++" supported at this time
+ [Required]
+ public string Language { get; set; }
+
+ [Output]
+ public string HeaderTempFilePath { get; set; }
+
+ public bool NoFetch { get; set; }
+
+ public override bool Execute()
+ {
+ try
+ {
+ InnerExecute();
+ return true;
+ }
+ catch (WarningException errorException)
+ {
+ logger.LogWarning(errorException.Message);
+ return true;
+ }
+ catch (Exception exception)
+ {
+ logger.LogError("Error occurred: " + exception);
+ return false;
+ }
+ finally
+ {
+ Logger.Reset();
+ }
+ }
+
+ void InnerExecute()
+ {
+ TempFileTracker.DeleteTempFiles();
+
+ InvalidFileChecker.CheckForInvalidFiles(CompileFiles, ProjectFile);
+
+ VersionVariables versionVariables;
+ if (!ExecuteCore.TryGetVersion(SolutionDirectory, out versionVariables, NoFetch, new Authentication()))
+ {
+ return;
+ }
+
+ CreateTempHeaderFile(versionVariables);
+ }
+
+ void CreateTempHeaderFile(VersionVariables versionVariables)
+ {
+ var fileExtension = GetFileExtension();
+ var headerFileName = $"GitVersionTaskAssemblyInfo.g.{fileExtension}";
+
+ if (IntermediateOutputPath == null)
+ {
+ headerFileName = $"AssemblyInfo_{Path.GetFileNameWithoutExtension(ProjectFile)}_{Path.GetRandomFileName()}.g.{fileExtension}";
+ }
+
+ var workingDirectory = IntermediateOutputPath ?? TempFileTracker.TempPath;
+
+ HeaderTempFilePath = Path.Combine(workingDirectory, headerFileName);
+ using (var headerFileUpdater = new NativeHeaderFileUpdater(headerFileName, workingDirectory, versionVariables, new FileSystem()))
+ {
+ headerFileUpdater.Update();
+ headerFileUpdater.CommitChanges();
+ }
+ }
+
+ string GetFileExtension()
+ {
+ switch (Language)
+ {
+ case SupportedLanguageConstants.CPLUSPLUS:
+ return SupportedLanguageConstants.FILEEXTENSION_CPLUSPLUS;
+ default:
+ throw new Exception($"Unknown language detected: '{Language}'");
+ }
+ }
+ }
+
+ internal class NativeHeaderFileUpdater : IDisposable
+ {
+ readonly List restoreBackupTasks = new List();
+ readonly List cleanupBackupTasks = new List();
+
+ ISet headerFileNames;
+ string workingDirectory;
+ VersionVariables variables;
+ IFileSystem fileSystem;
+ TemplateManager templateManager;
+
+
+ private NativeHeaderFileUpdater()
+ {
+ templateManager = new TemplateManager(TemplateType.GitVersionInformationResources);
+ }
+
+
+ public NativeHeaderFileUpdater(ISet headerFileNames, string workingDirectory, VersionVariables variables, IFileSystem fileSystem)
+ : this()
+ {
+ this.headerFileNames = headerFileNames;
+ this.workingDirectory = workingDirectory;
+ this.variables = variables;
+ this.fileSystem = fileSystem;
+ }
+
+ public NativeHeaderFileUpdater(string headerFileName, string workingDirectory, VersionVariables versionVariables, FileSystem fileSystem)
+ : this(new HashSet { headerFileName }, workingDirectory, versionVariables, fileSystem)
+ {
+ }
+
+ public void Update()
+ {
+ Logger.WriteInfo("Updating assembly info files");
+
+ var headerFiles = GetHeaderFiles(workingDirectory, headerFileNames, fileSystem).ToList();
+ Logger.WriteInfo($"Found {headerFiles.Count} files");
+
+ var assemblyVersion = variables.AssemblySemVer;
+ var assemblyVersionRegex = new Regex(@"\s*#define VERSION_FULL\s*(.*)");
+ var assemblyVersionString = !string.IsNullOrWhiteSpace(assemblyVersion) ? $"\r\n#define VERSION_FULL {assemblyVersion.Replace('.', ',')}\r\n" : "0,0,0,0";
+
+ var assemblyInfoVersion = variables.InformationalVersion;
+ var assemblyInfoVersionRegex = new Regex(@"\s*#define VERSION_STRING\s*(.*)");
+ var assemblyInfoVersionString = $"\r\n#define VERSION_STRING VERSION_XSTR({assemblyInfoVersion}) VERSION_BLANK \"\\0\"\r\n";
+
+ foreach (var headerFile in headerFiles)
+ {
+ var backupAssemblyInfo = headerFile.FullName + ".bak";
+ var localAssemblyInfo = headerFile.FullName;
+ fileSystem.Copy(headerFile.FullName, backupAssemblyInfo, true);
+
+ restoreBackupTasks.Add(() =>
+ {
+ if (fileSystem.Exists(localAssemblyInfo))
+ {
+ fileSystem.Delete(localAssemblyInfo);
+ }
+
+ fileSystem.Move(backupAssemblyInfo, localAssemblyInfo);
+ });
+
+ cleanupBackupTasks.Add(() => fileSystem.Delete(backupAssemblyInfo));
+
+ var originalFileContents = fileSystem.ReadAllText(headerFile.FullName);
+ var fileContents = originalFileContents;
+ var appendedAttributes = false;
+
+ if (!string.IsNullOrWhiteSpace(assemblyVersion))
+ {
+ fileContents = ReplaceOrAppend(assemblyVersionRegex, fileContents, assemblyVersionString, headerFile.Extension, ref appendedAttributes);
+ }
+
+ //if (!string.IsNullOrWhiteSpace(headerFile))
+ //{
+ // fileContents = ReplaceOrAppend(assemblyFileVersionRegex, fileContents, assemblyFileVersionString, assemblyInfoFile.Extension, ref appendedAttributes);
+ //}
+
+ fileContents = ReplaceOrAppend(assemblyInfoVersionRegex, fileContents, assemblyInfoVersionString, headerFile.Extension, ref appendedAttributes);
+
+ if (appendedAttributes)
+ {
+ // If we appended any attributes, put a new line after them
+ fileContents += Environment.NewLine;
+ }
+
+ if (originalFileContents != fileContents)
+ {
+ fileSystem.WriteAllText(headerFile.FullName, fileContents);
+ }
+ }
+ }
+
+ internal string ReplaceOrAppend(Regex replaceRegex, string inputString, string replaceString, string fileExtension, ref bool appendedAttributes)
+ {
+ if (replaceRegex.IsMatch(inputString))
+ {
+ appendedAttributes = false;
+ return replaceRegex.Replace(inputString, replaceString);
+ }
+ else
+ {
+ var assemblyAddFormat = templateManager.GetAddFormatFor(fileExtension);
+
+ appendedAttributes = true;
+ return inputString + Environment.NewLine + string.Format(assemblyAddFormat, replaceString);
+ }
+ }
+
+ internal IEnumerable GetHeaderFiles(string workingDirectory, ISet headerFileNames, IFileSystem fileSystem)
+ {
+ if (headerFileNames != null && headerFileNames.Any(x => !string.IsNullOrWhiteSpace(x)))
+ {
+ foreach (var headerFileName in headerFileNames)
+ {
+ var fullPath = Path.Combine(workingDirectory, headerFileName);
+
+ if (EnsureVersionHeaderFile(fileSystem, fullPath))
+ {
+ yield return new FileInfo(fullPath);
+ }
+ }
+ }
+ else
+ {
+ foreach (var item in fileSystem.DirectoryGetFiles(workingDirectory, "Version.h", SearchOption.AllDirectories))
+ {
+ var assemblyInfoFile = new FileInfo(item);
+
+ if (templateManager.IsSupported(assemblyInfoFile.Extension))
+ {
+ yield return assemblyInfoFile;
+ }
+ }
+ }
+ }
+
+ internal bool EnsureVersionHeaderFile(IFileSystem fileSystem, string fullPath)
+ {
+ if (fileSystem.Exists(fullPath))
+ {
+ return true;
+ }
+
+ var assemblyInfoSource = templateManager.GetTemplateFor(Path.GetExtension(fullPath));
+
+ if (!string.IsNullOrWhiteSpace(assemblyInfoSource))
+ {
+ var fileInfo = new FileInfo(fullPath);
+
+ if (!fileSystem.DirectoryExists(fileInfo.Directory.FullName))
+ {
+ fileSystem.CreateDirectory(fileInfo.Directory.FullName);
+ }
+
+ fileSystem.WriteAllText(fullPath, assemblyInfoSource);
+ return true;
+ }
+
+ Logger.WriteWarning($"No version header template available to create source file '{fullPath}'");
+ return false;
+ }
+
+ public virtual void Dispose()
+ {
+ foreach (var restoreBackup in restoreBackupTasks)
+ {
+ restoreBackup();
+ }
+
+ cleanupBackupTasks.Clear();
+ restoreBackupTasks.Clear();
+ }
+
+ public void CommitChanges()
+ {
+ foreach (var cleanupBackupTask in cleanupBackupTasks)
+ {
+ cleanupBackupTask();
+ }
+
+ cleanupBackupTasks.Clear();
+ restoreBackupTasks.Clear();
+ }
+ }
+}
\ No newline at end of file