From 659cff49e29ce387a36b7950d3a14c00975d29a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 25 Aug 2015 16:23:18 +0200 Subject: [PATCH 01/31] Enable disk caching of version info. Cache entries are placed in .git\gitversion_cache\ directory. --- src/GitVersionCore.Tests/TestFileSystem.cs | 12 +++ src/GitVersionCore/Helpers/FileSystem.cs | 10 ++ src/GitVersionCore/Helpers/IFileSystem.cs | 2 + .../OutputVariables/VersionVariables.cs | 12 +++ src/GitVersionExe.Tests/ExecutionResults.cs | 8 +- src/GitVersionTask/CachedVersion.cs | 7 -- src/GitVersionTask/GitVersionTask.csproj | 1 - src/GitVersionTask/VersionAndBranchFinder.cs | 93 +++++++++++++++---- 8 files changed, 112 insertions(+), 33 deletions(-) delete mode 100644 src/GitVersionTask/CachedVersion.cs diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index dba500611c..a02db2c29d 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -49,4 +49,16 @@ public Stream OpenWrite(string path) { return new TestStream(path, this); } + + + public Stream OpenRead(string path) + { + throw new NotImplementedException(); + } + + + public void CreateDirectory(string path) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index a92f5ea5bc..59e10d1dfd 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -44,5 +44,15 @@ public Stream OpenWrite(string path) { return File.OpenWrite(path); } + + public Stream OpenRead(string path) + { + return File.OpenWrite(path); + } + + public void CreateDirectory(string path) + { + Directory.CreateDirectory(path); + } } } \ No newline at end of file diff --git a/src/GitVersionCore/Helpers/IFileSystem.cs b/src/GitVersionCore/Helpers/IFileSystem.cs index e7c3a0b769..7d24b40a90 100644 --- a/src/GitVersionCore/Helpers/IFileSystem.cs +++ b/src/GitVersionCore/Helpers/IFileSystem.cs @@ -13,5 +13,7 @@ public interface IFileSystem void WriteAllText(string file, string fileContents); IEnumerable DirectoryGetFiles(string directory, string searchPattern, SearchOption searchOption); Stream OpenWrite(string path); + Stream OpenRead(string path); + void CreateDirectory(string path); } } \ No newline at end of file diff --git a/src/GitVersionCore/OutputVariables/VersionVariables.cs b/src/GitVersionCore/OutputVariables/VersionVariables.cs index 8aec43c093..3831dd632c 100644 --- a/src/GitVersionCore/OutputVariables/VersionVariables.cs +++ b/src/GitVersionCore/OutputVariables/VersionVariables.cs @@ -1,11 +1,23 @@ namespace GitVersion { + using System; using System.Collections; using System.Collections.Generic; using System.Linq; public class VersionVariables : IEnumerable> { + public static VersionVariables FromDictionary(IEnumerable> properties) + { + var type = typeof(VersionVariables); + var ctor = type.GetConstructors().Single(); + var ctorArgs = ctor.GetParameters() + .Select(p => properties.Single(v => v.Key.ToLower() == p.Name.ToLower()).Value) + .Cast() + .ToArray(); + return (VersionVariables)Activator.CreateInstance(type, ctorArgs); + } + public VersionVariables(string major, string minor, string patch, string buildMetaData, string buildMetaDataPadded, string fullBuildMetaData, string branchName, string sha, string majorMinorPatch, string semVer, string legacySemVer, string legacySemVerPadded, string fullSemVer, string assemblySemVer, string preReleaseTag, string preReleaseTagWithDash, string informationalVersion, string commitDate, string nugetVersion, string nugetVersionV2, string commitsSinceVersionSource, string commitsSinceVersionSourcePadded) { diff --git a/src/GitVersionExe.Tests/ExecutionResults.cs b/src/GitVersionExe.Tests/ExecutionResults.cs index 450011df24..ca233858dd 100644 --- a/src/GitVersionExe.Tests/ExecutionResults.cs +++ b/src/GitVersionExe.Tests/ExecutionResults.cs @@ -22,13 +22,7 @@ public virtual VersionVariables OutputVariables get { var outputVariables = new JavaScriptSerializer().Deserialize>(Output); - var type = typeof(VersionVariables); - var ctor = type.GetConstructors().Single(); - var ctorArgs = ctor.GetParameters() - .Select(p => outputVariables.Single(v => v.Key.ToLower() == p.Name.ToLower()).Value) - .Cast() - .ToArray(); - return (VersionVariables) Activator.CreateInstance(type, ctorArgs); + return VersionVariables.FromDictionary(outputVariables); } } } \ No newline at end of file diff --git a/src/GitVersionTask/CachedVersion.cs b/src/GitVersionTask/CachedVersion.cs deleted file mode 100644 index 75a35d22c8..0000000000 --- a/src/GitVersionTask/CachedVersion.cs +++ /dev/null @@ -1,7 +0,0 @@ -using GitVersion; - -public class CachedVersion -{ - public VersionVariables VersionVariables; - public long Timestamp; -} \ No newline at end of file diff --git a/src/GitVersionTask/GitVersionTask.csproj b/src/GitVersionTask/GitVersionTask.csproj index 48c7a5a178..048415c5ce 100644 --- a/src/GitVersionTask/GitVersionTask.csproj +++ b/src/GitVersionTask/GitVersionTask.csproj @@ -60,7 +60,6 @@ - diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index c9b7dc260f..4cbed400b5 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -1,11 +1,20 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + using GitVersion; using GitVersion.Helpers; +using YamlDotNet.Serialization; + public static class VersionAndBranchFinder { - static Dictionary versionCacheVersions = new Dictionary(); + static ConcurrentDictionary versionCacheVersions = new ConcurrentDictionary(); + public static bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication, IFileSystem fileSystem) { @@ -22,34 +31,82 @@ public static bool TryGetVersion(string directory, out VersionVariables versionV } } + public static VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem) { var gitDir = GitDirFinder.TreeWalkForDotGitDir(directory); using (var repo = RepositoryLoader.GetRepo(gitDir)) { - var ticks = DirectoryDateFinder.GetLastDirectoryWrite(gitDir); - var key = string.Format("{0}:{1}:{2}",gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha); + // Maybe using timestamp in .git/refs directory is enough? + var ticks = DirectoryDateFinder.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); + string key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); + + return versionCacheVersions.GetOrAdd(key, k => + { + Logger.WriteInfo("Version not in memory cache. Attempting to load version from cache."); + return LoadVersionVariablesFromDiskCache(k, directory, authentication, noFetch, fileSystem, gitDir, ticks); + }); + } + } + + + static VersionVariables LoadVersionVariablesFromDiskCache(string key, string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem, string gitDir, long ticks) + { + string cacheKey; + using (var sha1 = SHA1.Create()) + { + // Make a shorter key by hashing, to avoid having to long cache filename. + cacheKey = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", ""); + } + + var cacheDir = Path.Combine(gitDir, "gitversion_cache"); + if (!fileSystem.Exists(cacheDir)) + { + Logger.WriteInfo("Creating directory for cache in " + cacheDir); + fileSystem.CreateDirectory(cacheDir); + } - Logger.WriteInfo("CacheKey: " + key ); - CachedVersion result; - if (versionCacheVersions.TryGetValue(key, out result)) + var cacheFileName = Path.Combine(cacheDir, cacheKey); + VersionVariables vv = null; + if (fileSystem.Exists(cacheFileName)) + { + try { - if (result.Timestamp != ticks) + using (var stream = fileSystem.OpenRead(cacheFileName)) + using (var sr = new StreamReader(stream)) { - Logger.WriteInfo(string.Format("Change detected. Flushing cache. OldTimeStamp: {0}. NewTimeStamp: {1}", result.Timestamp, ticks)); - result.VersionVariables = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); - result.Timestamp = ticks; + Logger.WriteInfo("Deserializing version variables from cache file " + cacheFileName); + vv = VersionVariables.FromDictionary(new Deserializer().Deserialize>(sr)); + Logger.WriteInfo("Deserializing cache file done."); } - Logger.WriteInfo("Returning version from cache"); - return result.VersionVariables; } - Logger.WriteInfo("Version not in cache. Calculating version."); + catch (Exception ex) + { + Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); + Logger.WriteInfo(ex.ToString()); + try + { + fileSystem.Delete(cacheFileName); + } + catch (Exception deleteEx) + { + Logger.WriteWarning(string.Format("Unable delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + } + } + } + if (vv == null) + { + vv = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); - return (versionCacheVersions[key] = new CachedVersion + using (var stream = fileSystem.OpenWrite(cacheFileName)) + using (var sw = new StreamWriter(stream)) { - VersionVariables = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null), - Timestamp = ticks - }).VersionVariables; + Logger.WriteInfo("Storing version variables to cache file " + cacheFileName); + var serializer = new Serializer(); + serializer.Serialize(sw, vv.ToDictionary(x => x.Key, x => x.Value)); + Logger.WriteInfo("Serialization of cache file done."); + } } + return vv; } -} +} \ No newline at end of file From c20abdb7a70625f1505fcd6bad2b4fe198b4e4be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Thu, 22 Oct 2015 15:24:43 +0200 Subject: [PATCH 02/31] Do scoped `IndentLog` instead of `WriteInfo` before and after. --- src/GitVersionTask/VersionAndBranchFinder.cs | 89 +++++++++++--------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 4cbed400b5..c847a699ec 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -52,61 +52,66 @@ public static VersionVariables GetVersion(string directory, Authentication authe static VersionVariables LoadVersionVariablesFromDiskCache(string key, string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem, string gitDir, long ticks) { - string cacheKey; - using (var sha1 = SHA1.Create()) + using (Logger.IndentLog("Loading version variables from disk cache")) { - // Make a shorter key by hashing, to avoid having to long cache filename. - cacheKey = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", ""); - } - - var cacheDir = Path.Combine(gitDir, "gitversion_cache"); - if (!fileSystem.Exists(cacheDir)) - { - Logger.WriteInfo("Creating directory for cache in " + cacheDir); - fileSystem.CreateDirectory(cacheDir); - } + string cacheKey; + using (var sha1 = SHA1.Create()) + { + // Make a shorter key by hashing, to avoid having to long cache filename. + cacheKey = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", ""); + } - var cacheFileName = Path.Combine(cacheDir, cacheKey); - VersionVariables vv = null; - if (fileSystem.Exists(cacheFileName)) - { - try + var cacheDir = Path.Combine(gitDir, "gitversion_cache"); + if (!fileSystem.Exists(cacheDir)) { - using (var stream = fileSystem.OpenRead(cacheFileName)) - using (var sr = new StreamReader(stream)) - { - Logger.WriteInfo("Deserializing version variables from cache file " + cacheFileName); - vv = VersionVariables.FromDictionary(new Deserializer().Deserialize>(sr)); - Logger.WriteInfo("Deserializing cache file done."); - } + Logger.WriteInfo("Creating directory for cache in " + cacheDir); + fileSystem.CreateDirectory(cacheDir); } - catch (Exception ex) + + var cacheFileName = Path.Combine(cacheDir, cacheKey); + VersionVariables vv = null; + if (fileSystem.Exists(cacheFileName)) { - Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); - Logger.WriteInfo(ex.ToString()); try { - fileSystem.Delete(cacheFileName); + using (var stream = fileSystem.OpenRead(cacheFileName)) + using (var sr = new StreamReader(stream)) + { + using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName)) + { + vv = VersionVariables.FromDictionary(new Deserializer().Deserialize>(sr)); + } + } } - catch (Exception deleteEx) + catch (Exception ex) { - Logger.WriteWarning(string.Format("Unable delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); + Logger.WriteInfo(ex.ToString()); + try + { + fileSystem.Delete(cacheFileName); + } + catch (Exception deleteEx) + { + Logger.WriteWarning(string.Format("Unable delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + } } } - } - if (vv == null) - { - vv = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); - - using (var stream = fileSystem.OpenWrite(cacheFileName)) - using (var sw = new StreamWriter(stream)) + if (vv == null) { - Logger.WriteInfo("Storing version variables to cache file " + cacheFileName); - var serializer = new Serializer(); - serializer.Serialize(sw, vv.ToDictionary(x => x.Key, x => x.Value)); - Logger.WriteInfo("Serialization of cache file done."); + vv = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); + + using (var stream = fileSystem.OpenWrite(cacheFileName)) + using (var sw = new StreamWriter(stream)) + { + using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName)) + { + var serializer = new Serializer(); + serializer.Serialize(sw, vv.ToDictionary(x => x.Key, x => x.Value)); + } + } } + return vv; } - return vv; } } \ No newline at end of file From fbc0d87efb2bfd7438a3282f1a34e8ed6a39e851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 23 Oct 2015 14:06:08 +0200 Subject: [PATCH 03/31] Write != Read. --- src/GitVersionCore/Helpers/FileSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index 59e10d1dfd..3e47c52a8c 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -47,7 +47,7 @@ public Stream OpenWrite(string path) public Stream OpenRead(string path) { - return File.OpenWrite(path); + return File.OpenRead(path); } public void CreateDirectory(string path) From 242a07481235803a3305611c5facdb2205345a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 23 Oct 2015 14:10:05 +0200 Subject: [PATCH 04/31] Add .yml extension to the cached version file --- src/GitVersionTask/VersionAndBranchFinder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index c847a699ec..939786e25f 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -68,7 +68,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir fileSystem.CreateDirectory(cacheDir); } - var cacheFileName = Path.Combine(cacheDir, cacheKey); + var cacheFileName = string.Concat(Path.Combine(cacheDir, cacheKey), ".yml"); VersionVariables vv = null; if (fileSystem.Exists(cacheFileName)) { From b54d7f42b6bcaaf549b026a721acb090c7c78dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 23 Oct 2015 14:10:25 +0200 Subject: [PATCH 05/31] Improved logging scopes and code readability --- src/GitVersionTask/VersionAndBranchFinder.cs | 46 ++++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 939786e25f..30321d4161 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -25,7 +25,7 @@ public static bool TryGetVersion(string directory, out VersionVariables versionV } catch (Exception ex) { - Logger.WriteWarning("Could not determine assembly version: " + ex.Message); + Logger.WriteWarning("Could not determine assembly version: " + ex); versionVariables = null; return false; } @@ -72,28 +72,32 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir VersionVariables vv = null; if (fileSystem.Exists(cacheFileName)) { - try + using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName)) { - using (var stream = fileSystem.OpenRead(cacheFileName)) - using (var sr = new StreamReader(stream)) + try { - using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName)) + using (var stream = fileSystem.OpenRead(cacheFileName)) { - vv = VersionVariables.FromDictionary(new Deserializer().Deserialize>(sr)); + using (var reader = new StreamReader(stream)) + { + var dictionary = new Deserializer().Deserialize>(reader); + vv = VersionVariables.FromDictionary(dictionary); + } } + } - } - catch (Exception ex) - { - Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); - Logger.WriteInfo(ex.ToString()); - try - { - fileSystem.Delete(cacheFileName); - } - catch (Exception deleteEx) + catch (Exception ex) { - Logger.WriteWarning(string.Format("Unable delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); + Logger.WriteInfo(ex.ToString()); + try + { + fileSystem.Delete(cacheFileName); + } + catch (Exception deleteEx) + { + Logger.WriteWarning(string.Format("Unable delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + } } } } @@ -104,10 +108,16 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir using (var stream = fileSystem.OpenWrite(cacheFileName)) using (var sw = new StreamWriter(stream)) { + Dictionary dictionary; + using (Logger.IndentLog("Creating dictionary")) + { + dictionary = vv.ToDictionary(x => x.Key, x => x.Value); + } + using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName)) { var serializer = new Serializer(); - serializer.Serialize(sw, vv.ToDictionary(x => x.Key, x => x.Value)); + serializer.Serialize(sw, dictionary); } } } From c2766ecf47f4ea5f63f4cb28d7d347505bf95519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 11:18:26 +0100 Subject: [PATCH 06/31] Clarify that we're loading version from disk cache if it can't be found in memory. --- src/GitVersionTask/VersionAndBranchFinder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 30321d4161..27405f8d3d 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -43,7 +43,7 @@ public static VersionVariables GetVersion(string directory, Authentication authe return versionCacheVersions.GetOrAdd(key, k => { - Logger.WriteInfo("Version not in memory cache. Attempting to load version from cache."); + Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache."); return LoadVersionVariablesFromDiskCache(k, directory, authentication, noFetch, fileSystem, gitDir, ticks); }); } From fe29d1133887844376ffdccf3c9053220acac59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 11:41:02 +0100 Subject: [PATCH 07/31] We don't need to check if directories exist before doing CreateDirectory(). --- src/GitVersionTask/VersionAndBranchFinder.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 27405f8d3d..5e44709ba7 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -62,11 +62,8 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir } var cacheDir = Path.Combine(gitDir, "gitversion_cache"); - if (!fileSystem.Exists(cacheDir)) - { - Logger.WriteInfo("Creating directory for cache in " + cacheDir); - fileSystem.CreateDirectory(cacheDir); - } + // If the cacheDir already exists, CreateDirectory just won't do anything (it won't fail). @asbjornu + fileSystem.CreateDirectory(cacheDir); var cacheFileName = string.Concat(Path.Combine(cacheDir, cacheKey), ".yml"); VersionVariables vv = null; @@ -96,7 +93,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir } catch (Exception deleteEx) { - Logger.WriteWarning(string.Format("Unable delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + Logger.WriteWarning(string.Format("Unable to delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); } } } From 5259594cb25063307caf8c06a9edd413ecefb82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 14:02:09 +0100 Subject: [PATCH 08/31] R# cleanup --- src/GitVersionCore.Tests/TestFileSystem.cs | 13 +++++++++++++ src/GitVersionCore/Helpers/FileSystem.cs | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index a02db2c29d..011a6c879c 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -1,50 +1,63 @@ using System; using System.Collections.Generic; using System.IO; + using GitVersion.Helpers; public class TestFileSystem : IFileSystem { Dictionary fileSystem = new Dictionary(); + public void Copy(string @from, string to, bool overwrite) { throw new NotImplementedException(); } + public void Move(string @from, string to) { throw new NotImplementedException(); } + public bool Exists(string file) { return fileSystem.ContainsKey(file); } + public void Delete(string path) { throw new NotImplementedException(); } + public string ReadAllText(string path) { return fileSystem[path]; } + public void WriteAllText(string file, string fileContents) { if (fileSystem.ContainsKey(file)) + { fileSystem[file] = fileContents; + } else + { fileSystem.Add(file, fileContents); + } } + public IEnumerable DirectoryGetFiles(string directory, string searchPattern, SearchOption searchOption) { throw new NotImplementedException(); } + public Stream OpenWrite(string path) { return new TestStream(path, this); diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index 3e47c52a8c..eebc23975d 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -10,46 +10,55 @@ public void Copy(string @from, string to, bool overwrite) File.Copy(from, to, overwrite); } + public void Move(string @from, string to) { File.Move(from, to); } + public bool Exists(string file) { return File.Exists(file); } + public void Delete(string path) { File.Delete(path); } + public string ReadAllText(string path) { return File.ReadAllText(path); } + public void WriteAllText(string file, string fileContents) { File.WriteAllText(file, fileContents); } + public IEnumerable DirectoryGetFiles(string directory, string searchPattern, SearchOption searchOption) { return Directory.GetFiles(directory, searchPattern, searchOption); } + public Stream OpenWrite(string path) { return File.OpenWrite(path); } + public Stream OpenRead(string path) { return File.OpenRead(path); } + public void CreateDirectory(string path) { Directory.CreateDirectory(path); From 407a9e379ec178f39d90b590a2b380ee1da295ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 14:08:58 +0100 Subject: [PATCH 09/31] Moved TreeWalkForDotGitDir() from GitDirFinder to IFileSystem to make testing easier. --- ...itDirFinderTests.cs => FileSystemTests.cs} | 14 ++++++++----- .../Fixtures/RemoteRepositoryFixture.cs | 4 +++- src/GitVersionCore.Tests/GitPreparerTests.cs | 16 ++++++++------- .../GitVersionCore.Tests.csproj | 2 +- src/GitVersionCore.Tests/TestFileSystem.cs | 6 ++++++ src/GitVersionCore/ExecuteCore.cs | 2 +- src/GitVersionCore/GitDirFinder.cs | 20 ------------------- src/GitVersionCore/GitPreparer.cs | 17 +++++++++++++--- src/GitVersionCore/GitVersionCore.csproj | 1 - src/GitVersionCore/Helpers/FileSystem.cs | 15 ++++++++++++++ src/GitVersionCore/Helpers/IFileSystem.cs | 1 + src/GitVersionTask/VersionAndBranchFinder.cs | 2 +- 12 files changed, 60 insertions(+), 40 deletions(-) rename src/GitVersionCore.Tests/{GitDirFinderTests.cs => FileSystemTests.cs} (68%) delete mode 100644 src/GitVersionCore/GitDirFinder.cs diff --git a/src/GitVersionCore.Tests/GitDirFinderTests.cs b/src/GitVersionCore.Tests/FileSystemTests.cs similarity index 68% rename from src/GitVersionCore.Tests/GitDirFinderTests.cs rename to src/GitVersionCore.Tests/FileSystemTests.cs index acae8f587d..4e43a4a631 100644 --- a/src/GitVersionCore.Tests/GitDirFinderTests.cs +++ b/src/GitVersionCore.Tests/FileSystemTests.cs @@ -1,18 +1,22 @@ using System; using System.IO; using GitVersion; +using GitVersion.Helpers; + using LibGit2Sharp; using NUnit.Framework; [TestFixture] -public class GitDirFinderTests +public class FileSystemTests { string workDirectory; string gitDirectory; + IFileSystem fileSystem; [SetUp] public void CreateTemporaryRepository() { + this.fileSystem = new FileSystem(); workDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); gitDirectory = Repository.Init(workDirectory) @@ -30,26 +34,26 @@ public void Cleanup() [Test] public void From_WorkingDirectory() { - Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForDotGitDir(workDirectory)); + Assert.AreEqual(gitDirectory, fileSystem.TreeWalkForDotGitDir(workDirectory)); } [Test] public void From_WorkingDirectory_Parent() { var parentDirectory = Directory.GetParent(workDirectory).FullName; - Assert.Null(GitDirFinder.TreeWalkForDotGitDir(parentDirectory)); + Assert.Null(fileSystem.TreeWalkForDotGitDir(parentDirectory)); } [Test] public void From_GitDirectory() { - Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForDotGitDir(gitDirectory)); + Assert.AreEqual(gitDirectory, fileSystem.TreeWalkForDotGitDir(gitDirectory)); } [Test] public void From_RefsDirectory() { var refsDirectory = Path.Combine(gitDirectory, "refs"); - Assert.AreEqual(gitDirectory, GitDirFinder.TreeWalkForDotGitDir(refsDirectory)); + Assert.AreEqual(gitDirectory, fileSystem.TreeWalkForDotGitDir(refsDirectory)); } } diff --git a/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs b/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs index 73c96dc4eb..3afc405641 100644 --- a/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs +++ b/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs @@ -1,5 +1,7 @@ using System; using GitVersion; +using GitVersion.Helpers; + using LibGit2Sharp; public class RemoteRepositoryFixture : RepositoryFixtureBase @@ -24,7 +26,7 @@ public RemoteRepositoryFixture(Config configuration) /// public void InitialiseRepo() { - new GitPreparer(null, null, new Authentication(), false, LocalRepositoryFixture.RepositoryPath).Initialise(true, null); + new GitPreparer(null, null, new Authentication(), false, LocalRepositoryFixture.RepositoryPath, new FileSystem()).Initialise(true, null); } static IRepository CreateNewRepository(string path) diff --git a/src/GitVersionCore.Tests/GitPreparerTests.cs b/src/GitVersionCore.Tests/GitPreparerTests.cs index 706156fc27..29aa9d9a53 100644 --- a/src/GitVersionCore.Tests/GitPreparerTests.cs +++ b/src/GitVersionCore.Tests/GitPreparerTests.cs @@ -2,6 +2,8 @@ using System.IO; using System.Linq; using GitVersion; +using GitVersion.Helpers; + using LibGit2Sharp; using NUnit.Framework; using Shouldly; @@ -37,7 +39,7 @@ public void WorksCorrectlyWithRemoteRepository(string branchName, string expecte // Copy contents into working directory File.Copy(Path.Combine(fixture.RepositoryPath, "TestFile.txt"), Path.Combine(tempDir, "TestFile.txt")); - var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir); + var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); gitPreparer.Initialise(false, branchName); dynamicRepositoryPath = gitPreparer.GetDotGitDirectory(); @@ -75,7 +77,7 @@ public void UpdatesExistingDynamicRepository() { mainRepositoryFixture.Repository.MakeCommits(1); - var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir); + var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); gitPreparer.Initialise(false, "master"); dynamicRepositoryPath = gitPreparer.GetDotGitDirectory(); @@ -116,7 +118,7 @@ public void PicksAnotherDirectoryNameWhenDynamicRepoFolderTaken() expectedDynamicRepoLocation = Path.Combine(tempPath, fixture.RepositoryPath.Split('\\').Last()); Directory.CreateDirectory(expectedDynamicRepoLocation); - var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir); + var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); gitPreparer.Initialise(false, "master"); gitPreparer.IsDynamicGitRepository.ShouldBe(true); @@ -137,7 +139,7 @@ public void PicksAnotherDirectoryNameWhenDynamicRepoFolderTaken() public void WorksCorrectlyWithLocalRepository() { var tempDir = Path.GetTempPath(); - var gitPreparer = new GitPreparer(null, null, null, false, tempDir); + var gitPreparer = new GitPreparer(null, null, null, false, tempDir, new FileSystem()); var dynamicRepositoryPath = gitPreparer.GetDotGitDirectory(); dynamicRepositoryPath.ShouldBe(null); @@ -158,7 +160,7 @@ public void UsingDynamicRepositoryWithFeatureBranchWorks() { mainRepositoryFixture.Repository.MakeACommit(); - var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir); + var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); gitPreparer.Initialise(true, "feature1"); mainRepositoryFixture.Repository.Checkout(mainRepositoryFixture.Repository.CreateBranch("feature1")); @@ -186,7 +188,7 @@ public void UsingDynamicRepositoryWithoutTargetBranchFails() { mainRepositoryFixture.Repository.MakeACommit(); - var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir); + var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); Should.Throw(() => gitPreparer.Initialise(true, null)); } @@ -207,7 +209,7 @@ public void TestErrorThrownForInvalidRepository() try { - var gitPreparer = new GitPreparer("http://127.0.0.1/testrepo.git", null, new Authentication(), false, tempDir); + var gitPreparer = new GitPreparer("http://127.0.0.1/testrepo.git", null, new Authentication(), false, tempDir, new FileSystem()); Should.Throw(() => gitPreparer.Initialise(true, "master")); } diff --git a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj index e3ab9742b7..e4816ba185 100644 --- a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj +++ b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj @@ -124,7 +124,7 @@ - + diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index 011a6c879c..1216d0cc2d 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -74,4 +74,10 @@ public void CreateDirectory(string path) { throw new NotImplementedException(); } + + + public string TreeWalkForDotGitDir(string directory) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/GitVersionCore/ExecuteCore.cs b/src/GitVersionCore/ExecuteCore.cs index 16389b46af..8a2351d92a 100644 --- a/src/GitVersionCore/ExecuteCore.cs +++ b/src/GitVersionCore/ExecuteCore.cs @@ -9,7 +9,7 @@ public static class ExecuteCore public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId) { // Normalise if we are running on build server - var gitPreparer = new GitPreparer(targetUrl, dynamicRepositoryLocation, authentication, noFetch, workingDirectory); + var gitPreparer = new GitPreparer(targetUrl, dynamicRepositoryLocation, authentication, noFetch, workingDirectory, fileSystem); var applicableBuildServers = BuildServerList.GetApplicableBuildServers(); var buildServer = applicableBuildServers.FirstOrDefault(); diff --git a/src/GitVersionCore/GitDirFinder.cs b/src/GitVersionCore/GitDirFinder.cs deleted file mode 100644 index 9478cc8da8..0000000000 --- a/src/GitVersionCore/GitDirFinder.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace GitVersion -{ - using System.IO; - using LibGit2Sharp; - - public class GitDirFinder - { - public static string TreeWalkForDotGitDir(string currentDirectory) - { - var gitDirectory = Repository.Discover(currentDirectory); - - if (gitDirectory != null) - { - return gitDirectory.TrimEnd(Path.DirectorySeparatorChar); - } - - return null; - } - } -} \ No newline at end of file diff --git a/src/GitVersionCore/GitPreparer.cs b/src/GitVersionCore/GitPreparer.cs index afc0acc8c6..0441500074 100644 --- a/src/GitVersionCore/GitPreparer.cs +++ b/src/GitVersionCore/GitPreparer.cs @@ -3,6 +3,9 @@ namespace GitVersion using System; using System.IO; using System.Linq; + + using GitVersion.Helpers; + using LibGit2Sharp; public class GitPreparer @@ -12,14 +15,22 @@ public class GitPreparer Authentication authentication; bool noFetch; string targetPath; + readonly IFileSystem fileSystem; + - public GitPreparer(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, bool noFetch, string targetPath) + public GitPreparer(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, bool noFetch, string targetPath, IFileSystem fileSystem) { + if (fileSystem == null) + { + throw new ArgumentNullException("fileSystem"); + } + this.targetUrl = targetUrl; this.dynamicRepositoryLocation = dynamicRepositoryLocation; this.authentication = authentication; this.noFetch = noFetch; this.targetPath = targetPath; + this.fileSystem = fileSystem; } public bool IsDynamicGitRepository @@ -91,7 +102,7 @@ public string GetDotGitDirectory() if (IsDynamicGitRepository) return DynamicGitRepositoryPath; - return GitDirFinder.TreeWalkForDotGitDir(targetPath); + return this.fileSystem.TreeWalkForDotGitDir(targetPath); } public string GetProjectRootDirectory() @@ -99,7 +110,7 @@ public string GetProjectRootDirectory() if (IsDynamicGitRepository) return targetPath; - return Directory.GetParent(GitDirFinder.TreeWalkForDotGitDir(targetPath)).FullName; + return Directory.GetParent(this.fileSystem.TreeWalkForDotGitDir(targetPath)).FullName; } static string CreateDynamicRepository(string targetPath, Authentication authentication, string repositoryUrl, string targetBranch, bool noFetch) diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj index e3b6a70db8..128d95d24a 100644 --- a/src/GitVersionCore/GitVersionCore.csproj +++ b/src/GitVersionCore/GitVersionCore.csproj @@ -140,7 +140,6 @@ - diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index eebc23975d..2a5113e34b 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -3,6 +3,8 @@ namespace GitVersion.Helpers using System.Collections.Generic; using System.IO; + using LibGit2Sharp; + public class FileSystem : IFileSystem { public void Copy(string @from, string to, bool overwrite) @@ -63,5 +65,18 @@ public void CreateDirectory(string path) { Directory.CreateDirectory(path); } + + + public string TreeWalkForDotGitDir(string directory) + { + var gitDirectory = Repository.Discover(directory); + + if (gitDirectory != null) + { + return gitDirectory.TrimEnd(Path.DirectorySeparatorChar); + } + + return null; + } } } \ No newline at end of file diff --git a/src/GitVersionCore/Helpers/IFileSystem.cs b/src/GitVersionCore/Helpers/IFileSystem.cs index 7d24b40a90..7644033680 100644 --- a/src/GitVersionCore/Helpers/IFileSystem.cs +++ b/src/GitVersionCore/Helpers/IFileSystem.cs @@ -15,5 +15,6 @@ public interface IFileSystem Stream OpenWrite(string path); Stream OpenRead(string path); void CreateDirectory(string path); + string TreeWalkForDotGitDir(string directory); } } \ No newline at end of file diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 5e44709ba7..41aee2ee0c 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -34,7 +34,7 @@ public static bool TryGetVersion(string directory, out VersionVariables versionV public static VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem) { - var gitDir = GitDirFinder.TreeWalkForDotGitDir(directory); + var gitDir = fileSystem.TreeWalkForDotGitDir(directory); using (var repo = RepositoryLoader.GetRepo(gitDir)) { // Maybe using timestamp in .git/refs directory is enough? From 5e4532e77e29da51707a52f31ab79ed5ffa39e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 14:18:57 +0100 Subject: [PATCH 10/31] Moved RepositoryLoader.GetRepo() to IFileSystem.GetRepository() to make testing easier. --- src/GitVersionCore.Tests/TestFileSystem.cs | 8 +++++ src/GitVersionCore/ExecuteCore.cs | 2 +- src/GitVersionCore/GitVersionCore.csproj | 1 - src/GitVersionCore/Helpers/FileSystem.cs | 25 ++++++++++++++++ src/GitVersionCore/Helpers/IFileSystem.cs | 1 + src/GitVersionCore/RepositoryLoader.cs | 31 -------------------- src/GitVersionTask/VersionAndBranchFinder.cs | 2 +- 7 files changed, 36 insertions(+), 34 deletions(-) delete mode 100644 src/GitVersionCore/RepositoryLoader.cs diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index 1216d0cc2d..398c656656 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -4,6 +4,8 @@ using GitVersion.Helpers; +using LibGit2Sharp; + public class TestFileSystem : IFileSystem { Dictionary fileSystem = new Dictionary(); @@ -80,4 +82,10 @@ public string TreeWalkForDotGitDir(string directory) { throw new NotImplementedException(); } + + + public Repository GetRepository(string gitDirectory) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/GitVersionCore/ExecuteCore.cs b/src/GitVersionCore/ExecuteCore.cs index 8a2351d92a..a6eab7f4a6 100644 --- a/src/GitVersionCore/ExecuteCore.cs +++ b/src/GitVersionCore/ExecuteCore.cs @@ -27,7 +27,7 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string var versionFinder = new GitVersionFinder(); var configuration = ConfigurationProvider.Provide(projectRoot, fileSystem); - using (var repo = RepositoryLoader.GetRepo(dotGitDirectory)) + using (var repo = fileSystem.GetRepository(dotGitDirectory)) { var gitVersionContext = new GitVersionContext(repo, configuration, commitId: commitId); var semanticVersion = versionFinder.FindVersion(gitVersionContext); diff --git a/src/GitVersionCore/GitVersionCore.csproj b/src/GitVersionCore/GitVersionCore.csproj index 128d95d24a..e6ad6f289a 100644 --- a/src/GitVersionCore/GitVersionCore.csproj +++ b/src/GitVersionCore/GitVersionCore.csproj @@ -151,7 +151,6 @@ - diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index 2a5113e34b..3e2ac4d499 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -1,5 +1,6 @@ namespace GitVersion.Helpers { + using System; using System.Collections.Generic; using System.IO; @@ -78,5 +79,29 @@ public string TreeWalkForDotGitDir(string directory) return null; } + + + public Repository GetRepository(string gitDirectory) + { + try + { + var repository = new Repository(gitDirectory); + + var branch = repository.Head; + if (branch.Tip == null) + { + throw new WarningException("No Tip found. Has repo been initialized?"); + } + return repository; + } + catch (Exception exception) + { + if (exception.Message.Contains("LibGit2Sharp.Core.NativeMethods") || exception.Message.Contains("FilePathMarshaler")) + { + throw new WarningException("Restart of the process may be required to load an updated version of LibGit2Sharp."); + } + throw; + } + } } } \ No newline at end of file diff --git a/src/GitVersionCore/Helpers/IFileSystem.cs b/src/GitVersionCore/Helpers/IFileSystem.cs index 7644033680..310efcc257 100644 --- a/src/GitVersionCore/Helpers/IFileSystem.cs +++ b/src/GitVersionCore/Helpers/IFileSystem.cs @@ -16,5 +16,6 @@ public interface IFileSystem Stream OpenRead(string path); void CreateDirectory(string path); string TreeWalkForDotGitDir(string directory); + Repository GetRepository(string gitDirectory); } } \ No newline at end of file diff --git a/src/GitVersionCore/RepositoryLoader.cs b/src/GitVersionCore/RepositoryLoader.cs deleted file mode 100644 index 41e0dfece2..0000000000 --- a/src/GitVersionCore/RepositoryLoader.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace GitVersion -{ - using System; - using LibGit2Sharp; - - public class RepositoryLoader - { - public static Repository GetRepo(string gitDirectory) - { - try - { - var repository = new Repository(gitDirectory); - - var branch = repository.Head; - if (branch.Tip == null) - { - throw new WarningException("No Tip found. Has repo been initialized?"); - } - return repository; - } - catch (Exception exception) - { - if (exception.Message.Contains("LibGit2Sharp.Core.NativeMethods") || exception.Message.Contains("FilePathMarshaler")) - { - throw new WarningException("Restart of the process may be required to load an updated version of LibGit2Sharp."); - } - throw; - } - } - } -} \ No newline at end of file diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 41aee2ee0c..a43955cd67 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -35,7 +35,7 @@ public static bool TryGetVersion(string directory, out VersionVariables versionV public static VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem) { var gitDir = fileSystem.TreeWalkForDotGitDir(directory); - using (var repo = RepositoryLoader.GetRepo(gitDir)) + using (var repo = fileSystem.GetRepository(gitDir)) { // Maybe using timestamp in .git/refs directory is enough? var ticks = DirectoryDateFinder.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); From c16acbc3a244958dc38d921655b772f4106a16b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 14:37:09 +0100 Subject: [PATCH 11/31] Moved GetLastDirectoryWrite() from DirectoryDateFinder to IFileSystem to make testing easier. --- src/GitVersionCore.Tests/TestFileSystem.cs | 6 ++++++ src/GitVersionCore/Helpers/FileSystem.cs | 12 ++++++++++++ src/GitVersionCore/Helpers/IFileSystem.cs | 3 +++ src/GitVersionTask/DirectoryDateFinder.cs | 15 --------------- src/GitVersionTask/GitVersionTask.csproj | 1 - src/GitVersionTask/VersionAndBranchFinder.cs | 2 +- 6 files changed, 22 insertions(+), 17 deletions(-) delete mode 100644 src/GitVersionTask/DirectoryDateFinder.cs diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index 398c656656..9124f60c6a 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -78,6 +78,12 @@ public void CreateDirectory(string path) } + public long GetLastDirectoryWrite(string path) + { + throw new NotImplementedException(); + } + + public string TreeWalkForDotGitDir(string directory) { throw new NotImplementedException(); diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index 3e2ac4d499..6fc2d3a61e 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -3,6 +3,7 @@ namespace GitVersion.Helpers using System; using System.Collections.Generic; using System.IO; + using System.Linq; using LibGit2Sharp; @@ -68,6 +69,17 @@ public void CreateDirectory(string path) } + public long GetLastDirectoryWrite(string path) + { + return new DirectoryInfo(path) + .GetDirectories("*.*", SearchOption.AllDirectories) + .Select(d => d.LastWriteTimeUtc) + .DefaultIfEmpty() + .Max() + .Ticks; + } + + public string TreeWalkForDotGitDir(string directory) { var gitDirectory = Repository.Discover(directory); diff --git a/src/GitVersionCore/Helpers/IFileSystem.cs b/src/GitVersionCore/Helpers/IFileSystem.cs index 310efcc257..edfe41ee55 100644 --- a/src/GitVersionCore/Helpers/IFileSystem.cs +++ b/src/GitVersionCore/Helpers/IFileSystem.cs @@ -3,6 +3,8 @@ namespace GitVersion.Helpers using System.Collections.Generic; using System.IO; + using LibGit2Sharp; + public interface IFileSystem { void Copy(string from, string to, bool overwrite); @@ -15,6 +17,7 @@ public interface IFileSystem Stream OpenWrite(string path); Stream OpenRead(string path); void CreateDirectory(string path); + long GetLastDirectoryWrite(string path); string TreeWalkForDotGitDir(string directory); Repository GetRepository(string gitDirectory); } diff --git a/src/GitVersionTask/DirectoryDateFinder.cs b/src/GitVersionTask/DirectoryDateFinder.cs deleted file mode 100644 index 0596269ba3..0000000000 --- a/src/GitVersionTask/DirectoryDateFinder.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.IO; -using System.Linq; - -public static class DirectoryDateFinder -{ - public static long GetLastDirectoryWrite(string path) - { - return new DirectoryInfo(path) - .GetDirectories("*.*", SearchOption.AllDirectories) - .Select(d => d.LastWriteTimeUtc) - .DefaultIfEmpty() - .Max() - .Ticks; - } -} \ No newline at end of file diff --git a/src/GitVersionTask/GitVersionTask.csproj b/src/GitVersionTask/GitVersionTask.csproj index 048415c5ce..b6dad9acc0 100644 --- a/src/GitVersionTask/GitVersionTask.csproj +++ b/src/GitVersionTask/GitVersionTask.csproj @@ -60,7 +60,6 @@ - diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index a43955cd67..83ee9093da 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -38,7 +38,7 @@ public static VersionVariables GetVersion(string directory, Authentication authe using (var repo = fileSystem.GetRepository(gitDir)) { // Maybe using timestamp in .git/refs directory is enough? - var ticks = DirectoryDateFinder.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); + var ticks = fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); string key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); return versionCacheVersions.GetOrAdd(key, k => From a37d211fd61760264eb72619700aed492641f5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 14:49:59 +0100 Subject: [PATCH 12/31] IRepository is easier to mock than Repository --- src/GitVersionCore.Tests/TestFileSystem.cs | 2 +- src/GitVersionCore/Helpers/FileSystem.cs | 2 +- src/GitVersionCore/Helpers/IFileSystem.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index 9124f60c6a..cc2c656d85 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -90,7 +90,7 @@ public string TreeWalkForDotGitDir(string directory) } - public Repository GetRepository(string gitDirectory) + public IRepository GetRepository(string gitDirectory) { throw new NotImplementedException(); } diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index 6fc2d3a61e..54360a63cc 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -93,7 +93,7 @@ public string TreeWalkForDotGitDir(string directory) } - public Repository GetRepository(string gitDirectory) + public IRepository GetRepository(string gitDirectory) { try { diff --git a/src/GitVersionCore/Helpers/IFileSystem.cs b/src/GitVersionCore/Helpers/IFileSystem.cs index edfe41ee55..95d1e087a5 100644 --- a/src/GitVersionCore/Helpers/IFileSystem.cs +++ b/src/GitVersionCore/Helpers/IFileSystem.cs @@ -19,6 +19,6 @@ public interface IFileSystem void CreateDirectory(string path); long GetLastDirectoryWrite(string path); string TreeWalkForDotGitDir(string directory); - Repository GetRepository(string gitDirectory); + IRepository GetRepository(string gitDirectory); } } \ No newline at end of file From 41bb6eb628bc1d50c8144666994c95aa79b6ae15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 14:53:58 +0100 Subject: [PATCH 13/31] Added NSubstitute NuGet package reference to make mocking a non-tedious and quite possibly enjoyable task. --- src/GitVersionCore.Tests/GitVersionCore.Tests.csproj | 4 ++++ src/GitVersionCore.Tests/packages.config | 1 + 2 files changed, 5 insertions(+) diff --git a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj index e4816ba185..b12b5e175a 100644 --- a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj +++ b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj @@ -72,6 +72,10 @@ ..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll True + + ..\packages\NSubstitute.1.9.2.0\lib\net45\NSubstitute.dll + True + ..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll True diff --git a/src/GitVersionCore.Tests/packages.config b/src/GitVersionCore.Tests/packages.config index 94bf961fe7..2b351bce70 100644 --- a/src/GitVersionCore.Tests/packages.config +++ b/src/GitVersionCore.Tests/packages.config @@ -7,6 +7,7 @@ + From 6a0fa0f97a8dac6c59fceb967e9631bd0a970034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 16:08:55 +0100 Subject: [PATCH 14/31] Log if the version cache file can't be found --- src/GitVersionTask/VersionAndBranchFinder.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 83ee9093da..f548ef0f2f 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -98,6 +98,11 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir } } } + else + { + Logger.WriteInfo("Cache file " + cacheFileName + " not found."); + } + if (vv == null) { vv = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); @@ -118,6 +123,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir } } } + return vv; } } From b1e41fa6f7d04e7cb686a7374b2102bd363c848a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Tue, 10 Nov 2015 16:10:44 +0100 Subject: [PATCH 15/31] Added tests for VersionBranchFinder.GetVersion() and its use of the version cache file. --- src/GitVersionCore.Tests/TestFileSystem.cs | 111 ++++++++++++++++-- .../GitVersionTask.Tests.csproj | 1 + .../VersionAndBranchFinderTests.cs | 63 ++++++++++ 3 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index cc2c656d85..aab83d642d 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Text; using GitVersion.Helpers; using LibGit2Sharp; +using NSubstitute; + public class TestFileSystem : IFileSystem { Dictionary fileSystem = new Dictionary(); @@ -25,7 +29,7 @@ public void Move(string @from, string to) public bool Exists(string file) { - return fileSystem.ContainsKey(file); + return this.fileSystem.ContainsKey(file); } @@ -37,19 +41,19 @@ public void Delete(string path) public string ReadAllText(string path) { - return fileSystem[path]; + return this.fileSystem[path]; } public void WriteAllText(string file, string fileContents) { - if (fileSystem.ContainsKey(file)) + if (this.fileSystem.ContainsKey(file)) { - fileSystem[file] = fileContents; + this.fileSystem[file] = fileContents; } else { - fileSystem.Add(file, fileContents); + this.fileSystem.Add(file, fileContents); } } @@ -68,30 +72,117 @@ public Stream OpenWrite(string path) public Stream OpenRead(string path) { - throw new NotImplementedException(); + if (this.fileSystem.ContainsKey(path)) + { + var content = this.fileSystem[path]; + return new MemoryStream(Encoding.UTF8.GetBytes(content)); + } + + throw new FileNotFoundException("File not found.", path); } public void CreateDirectory(string path) { - throw new NotImplementedException(); } public long GetLastDirectoryWrite(string path) { - throw new NotImplementedException(); + return 1; } public string TreeWalkForDotGitDir(string directory) { - throw new NotImplementedException(); + return directory; } public IRepository GetRepository(string gitDirectory) { - throw new NotImplementedException(); + var repository = Substitute.For(); + var tip = Substitute.For(); + tip.Committer.Returns(new Signature("Asbj�rn Ulsberg", "asbjorn@ulsberg.no", new DateTimeOffset(2015, 11, 10, 13, 37, 0, TimeSpan.FromHours(1)))); + var commits = new Commits + { + tip + }; + repository.Commits.QueryBy(null).ReturnsForAnyArgs(commits); + var head = Substitute.For(); + head.CanonicalName.Returns("refs/heads/master"); + tip.Sha.Returns("e7da1b19d03394896fb8da8916cd26f0efb1566f"); + head.Tip.Returns(tip); + repository.Head.Returns(head); + var branches = new Branches + { + { "master", tip } + }; + + repository.Branches.Returns(branches); + return repository; + } + + + class Branches : BranchCollection + { + IList branches; + + + public Branches() + { + this.branches = new List(); + } + + + public override Branch this[string name] + { + get { return this.branches.FirstOrDefault(b => b.Name == name); } + } + + + public override Branch Add(string name, Commit commit, bool allowOverwrite = false) + { + var branch = Substitute.For(); + branch.Name.Returns(name); + branch.Tip.Returns(commit); + this.branches.Add(branch); + return branch; + } + + + public override Branch Add(string name, Commit commit, Signature signature, string logMessage = null, bool allowOverwrite = false) + { + return Add(name, commit, allowOverwrite); + } + + + public override IEnumerator GetEnumerator() + { + return this.branches.GetEnumerator(); + } + } + + class Commits : List, IQueryableCommitLog + { + public CommitSortStrategies SortedBy { get; private set; } + + + public ICommitLog QueryBy(CommitFilter filter) + { + throw new NotImplementedException(); + } + + + public Commit FindMergeBase(Commit first, Commit second) + { + throw new NotImplementedException(); + } + + + public Commit FindMergeBase(IEnumerable commits, MergeBaseFindingStrategy strategy) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj b/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj index d4adf77842..b2fdd096b0 100644 --- a/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj +++ b/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj @@ -131,6 +131,7 @@ + diff --git a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs new file mode 100644 index 0000000000..f80025f01e --- /dev/null +++ b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs @@ -0,0 +1,63 @@ +#region License + +// -------------------------------------------------- +// Copyright © OKB. All Rights Reserved. +// +// This software is proprietary information of OKB. +// USE IS SUBJECT TO LICENSE TERMS. +// -------------------------------------------------- + +#endregion + +using NUnit.Framework; + +using Shouldly; + +[TestFixture] +public class VersionAndBranchFinderTests +{ + [Test] + public void ExistingCacheFile() + { + var fileSystem = new TestFileSystem(); + fileSystem.WriteAllText("existing\\gitversion_cache\\C7B23F8A47ECE0E14CBE2E22C04269CC5A88E275.yml", @" +Major: 4 +Minor: 10 +Patch: 3 +PreReleaseTag: test.19 +PreReleaseTagWithDash: -test.19 +BuildMetaData: +BuildMetaDataPadded: +FullBuildMetaData: Branch.feature/test.Sha.dd2a29aff0c948e1bdf3dabbe13e1576e70d5f9f +MajorMinorPatch: 4.10.3 +SemVer: 4.10.3-test.19 +LegacySemVer: 4.10.3-test19 +LegacySemVerPadded: 4.10.3-test0019 +AssemblySemVer: 4.10.3.0 +FullSemVer: 4.10.3-test.19 +InformationalVersion: 4.10.3-test.19+Branch.feature/test.Sha.dd2a29aff0c948e1bdf3dabbe13e1576e70d5f9f +BranchName: feature/test +Sha: dd2a29aff0c948e1bdf3dabbe13e1576e70d5f9f +NuGetVersionV2: 4.10.3-test0019 +NuGetVersion: 4.10.3-test0019 +CommitsSinceVersionSource: 19 +CommitsSinceVersionSourcePadded: 0019 +CommitDate: 2015-11-10 +"); + + var vv = VersionAndBranchFinder.GetVersion("existing", null, false, fileSystem); + + vv.AssemblySemVer.ShouldBe("4.10.3.0"); + } + + + [Test] + public void MissingCacheFile() + { + var fileSystem = new TestFileSystem(); + + var vv = VersionAndBranchFinder.GetVersion("missing", null, false, fileSystem); + + vv.AssemblySemVer.ShouldBe("0.1.0.0"); + } +} \ No newline at end of file From a5d425bb172c12963884dcbdaf5fd58ffc4ff56f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 14:29:01 +0100 Subject: [PATCH 16/31] R# cleanup --- .../OutputVariables/VersionVariables.cs | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/src/GitVersionCore/OutputVariables/VersionVariables.cs b/src/GitVersionCore/OutputVariables/VersionVariables.cs index 3831dd632c..412bd78ebd 100644 --- a/src/GitVersionCore/OutputVariables/VersionVariables.cs +++ b/src/GitVersionCore/OutputVariables/VersionVariables.cs @@ -7,19 +7,28 @@ public class VersionVariables : IEnumerable> { - public static VersionVariables FromDictionary(IEnumerable> properties) - { - var type = typeof(VersionVariables); - var ctor = type.GetConstructors().Single(); - var ctorArgs = ctor.GetParameters() - .Select(p => properties.Single(v => v.Key.ToLower() == p.Name.ToLower()).Value) - .Cast() - .ToArray(); - return (VersionVariables)Activator.CreateInstance(type, ctorArgs); - } - - public VersionVariables(string major, string minor, string patch, string buildMetaData, string buildMetaDataPadded, string fullBuildMetaData, string branchName, string sha, string majorMinorPatch, string semVer, string legacySemVer, string legacySemVerPadded, string fullSemVer, string assemblySemVer, string preReleaseTag, string preReleaseTagWithDash, string informationalVersion, - string commitDate, string nugetVersion, string nugetVersionV2, string commitsSinceVersionSource, string commitsSinceVersionSourcePadded) + public VersionVariables(string major, + string minor, + string patch, + string buildMetaData, + string buildMetaDataPadded, + string fullBuildMetaData, + string branchName, + string sha, + string majorMinorPatch, + string semVer, + string legacySemVer, + string legacySemVerPadded, + string fullSemVer, + string assemblySemVer, + string preReleaseTag, + string preReleaseTagWithDash, + string informationalVersion, + string commitDate, + string nugetVersion, + string nugetVersionV2, + string commitsSinceVersionSource, + string commitsSinceVersionSourcePadded) { Major = major; Minor = minor; @@ -45,6 +54,7 @@ public VersionVariables(string major, string minor, string patch, string buildMe CommitsSinceVersionSourcePadded = commitsSinceVersionSourcePadded; } + public string Major { get; private set; } public string Minor { get; private set; } public string Patch { get; private set; } @@ -74,26 +84,41 @@ public static IEnumerable AvailableVariables public string CommitDate { get; set; } + public string this[string variable] + { + get { return (string)typeof(VersionVariables).GetProperty(variable).GetValue(this, null); } + } + + public IEnumerator> GetEnumerator() { var type = typeof(string); return typeof(VersionVariables) .GetProperties() .Where(p => p.PropertyType == type && !p.GetIndexParameters().Any()) - .Select(p => new KeyValuePair(p.Name, (string) p.GetValue(this, null))) + .Select(p => new KeyValuePair(p.Name, (string)p.GetValue(this, null))) .GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } - public string this [string variable] + + public static VersionVariables FromDictionary(IEnumerable> properties) { - get { return (string) typeof(VersionVariables).GetProperty(variable).GetValue(this, null); } + var type = typeof(VersionVariables); + var ctor = type.GetConstructors().Single(); + var ctorArgs = ctor.GetParameters() + .Select(p => properties.Single(v => v.Key.ToLower() == p.Name.ToLower()).Value) + .Cast() + .ToArray(); + return (VersionVariables)Activator.CreateInstance(type, ctorArgs); } + public bool TryGetValue(string variable, out string variableValue) { if (ContainsKey(variable)) @@ -106,6 +131,7 @@ public bool TryGetValue(string variable, out string variableValue) return false; } + public bool ContainsKey(string variable) { return typeof(VersionVariables).GetProperty(variable) != null; From 82a134679ba1de1c93fe320020163927e4849ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 14:55:55 +0100 Subject: [PATCH 17/31] Use string.Equals() with explicit StringComparison --- src/GitVersionCore/OutputVariables/VersionVariables.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitVersionCore/OutputVariables/VersionVariables.cs b/src/GitVersionCore/OutputVariables/VersionVariables.cs index 412bd78ebd..ac735a644f 100644 --- a/src/GitVersionCore/OutputVariables/VersionVariables.cs +++ b/src/GitVersionCore/OutputVariables/VersionVariables.cs @@ -112,7 +112,7 @@ public static VersionVariables FromDictionary(IEnumerable properties.Single(v => v.Key.ToLower() == p.Name.ToLower()).Value) + .Select(p => properties.Single(v => string.Equals(v.Key, p.Name, StringComparison.CurrentCultureIgnoreCase)).Value) .Cast() .ToArray(); return (VersionVariables)Activator.CreateInstance(type, ctorArgs); From 56b9b2dfd4dda48128cf4e929c1b56a133a54c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 14:58:41 +0100 Subject: [PATCH 18/31] Use the AvailableVariables property instead of doing GetProperties() everywhere. --- src/GitVersionTask.Tests/GetVersionTaskTests.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/GitVersionTask.Tests/GetVersionTaskTests.cs b/src/GitVersionTask.Tests/GetVersionTaskTests.cs index 707f7b4eda..0030d56da0 100644 --- a/src/GitVersionTask.Tests/GetVersionTaskTests.cs +++ b/src/GitVersionTask.Tests/GetVersionTaskTests.cs @@ -16,10 +16,7 @@ public void OutputsShouldMatchVariableProvider() .Where(p => p.GetCustomAttributes(typeof(OutputAttribute), false).Any()) .Select(p => p.Name); - var variablesProperties = typeof(VersionVariables) - .GetProperties() - .Select(p => p.Name) - .Except(new[] { "AvailableVariables", "Item" }); + var variablesProperties = VersionVariables.AvailableVariables; taskProperties.ShouldBe(variablesProperties, ignoreOrder: true); } From 6638e891cb13f1e852573e1aebee46ca6f9dce63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 14:59:52 +0100 Subject: [PATCH 19/31] Don't crash if cleanup fails --- src/GitVersionTask.Tests/InvalidFileCheckerTests.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/GitVersionTask.Tests/InvalidFileCheckerTests.cs b/src/GitVersionTask.Tests/InvalidFileCheckerTests.cs index 5681304ec5..4c719ae102 100644 --- a/src/GitVersionTask.Tests/InvalidFileCheckerTests.cs +++ b/src/GitVersionTask.Tests/InvalidFileCheckerTests.cs @@ -25,7 +25,14 @@ public void CreateTemporaryProject() [TearDown] public void Cleanup() { - Directory.Delete(projectDirectory, true); + try + { + Directory.Delete(projectDirectory, true); + } + catch (Exception exception) + { + Console.WriteLine(exception); + } } [Test] From 0114126d2ae7e2e86100a7903f82350dbe72558b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 15:04:02 +0100 Subject: [PATCH 20/31] Add [ReflectionIgnore] attribute to properties in VersionVariables so it's easier and more consistent to exclude properties that aren't version variables. --- .../OutputVariables/VersionVariables.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/GitVersionCore/OutputVariables/VersionVariables.cs b/src/GitVersionCore/OutputVariables/VersionVariables.cs index ac735a644f..e492748c67 100644 --- a/src/GitVersionCore/OutputVariables/VersionVariables.cs +++ b/src/GitVersionCore/OutputVariables/VersionVariables.cs @@ -77,13 +77,22 @@ public VersionVariables(string major, public string CommitsSinceVersionSource { get; private set; } public string CommitsSinceVersionSourcePadded { get; private set; } + [ReflectionIgnore] public static IEnumerable AvailableVariables { - get { return typeof(VersionVariables).GetProperties().Select(p => p.Name).OrderBy(a => a); } + get + { + return typeof(VersionVariables) + .GetProperties() + .Where(p => !p.GetCustomAttributes(typeof(ReflectionIgnoreAttribute), false).Any()) + .Select(p => p.Name) + .OrderBy(a => a); + } } public string CommitDate { get; set; } + [ReflectionIgnore] public string this[string variable] { get { return (string)typeof(VersionVariables).GetProperty(variable).GetValue(this, null); } @@ -95,7 +104,7 @@ public IEnumerator> GetEnumerator() var type = typeof(string); return typeof(VersionVariables) .GetProperties() - .Where(p => p.PropertyType == type && !p.GetIndexParameters().Any()) + .Where(p => p.PropertyType == type && !p.GetIndexParameters().Any() && !p.GetCustomAttributes(typeof(ReflectionIgnoreAttribute), false).Any()) .Select(p => new KeyValuePair(p.Name, (string)p.GetValue(this, null))) .GetEnumerator(); } @@ -136,5 +145,10 @@ public bool ContainsKey(string variable) { return typeof(VersionVariables).GetProperty(variable) != null; } + + + sealed class ReflectionIgnoreAttribute : Attribute + { + } } } \ No newline at end of file From 216c0440ff356b13f13ad86104d3bd9324d6a66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 15:04:32 +0100 Subject: [PATCH 21/31] Added `VersionVariables.FromFile()` method and corresponding `FileName` property and make use of it in `VersionAndBranchFinderLoadVersionVariablesFromDiskCache()`. --- .../OutputVariables/VersionVariables.cs | 23 +++++++++++++++++++ src/GitVersionTask/VersionAndBranchFinder.cs | 11 ++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/GitVersionCore/OutputVariables/VersionVariables.cs b/src/GitVersionCore/OutputVariables/VersionVariables.cs index e492748c67..ebc0ab78fe 100644 --- a/src/GitVersionCore/OutputVariables/VersionVariables.cs +++ b/src/GitVersionCore/OutputVariables/VersionVariables.cs @@ -3,8 +3,13 @@ using System; using System.Collections; using System.Collections.Generic; + using System.IO; using System.Linq; + using GitVersion.Helpers; + + using YamlDotNet.Serialization; + public class VersionVariables : IEnumerable> { public VersionVariables(string major, @@ -92,6 +97,9 @@ public static IEnumerable AvailableVariables public string CommitDate { get; set; } + [ReflectionIgnore] + public string FileName { get; set; } + [ReflectionIgnore] public string this[string variable] { @@ -128,6 +136,21 @@ public static VersionVariables FromDictionary(IEnumerable>(reader); + var versionVariables = FromDictionary(dictionary); + versionVariables.FileName = filePath; + return versionVariables; + } + } + } + + public bool TryGetValue(string variable, out string variableValue) { if (ContainsKey(variable)) diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index f548ef0f2f..99c620654c 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -73,15 +73,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir { try { - using (var stream = fileSystem.OpenRead(cacheFileName)) - { - using (var reader = new StreamReader(stream)) - { - var dictionary = new Deserializer().Deserialize>(reader); - vv = VersionVariables.FromDictionary(dictionary); - } - } - + vv = VersionVariables.FromFile(cacheFileName, fileSystem); } catch (Exception ex) { @@ -106,6 +98,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir if (vv == null) { vv = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); + vv.FileName = cacheFileName; using (var stream = fileSystem.OpenWrite(cacheFileName)) using (var sw = new StreamWriter(stream)) From ed5edd648bad13ed0cae6e77b6a58b98c2d6ccd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 15:21:43 +0100 Subject: [PATCH 22/31] Make the `VersionAndBranchFinder.VersionCacheVersions` dictionary internal and internals visible to GitVersionTask.Tests so we can reset the in-memory cache for testing. Not very elegant, but that's `static` for you. :-/ --- src/GitVersionTask/AssemblyInfo.cs | 2 ++ src/GitVersionTask/VersionAndBranchFinder.cs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/GitVersionTask/AssemblyInfo.cs b/src/GitVersionTask/AssemblyInfo.cs index 782d9b63f7..507682e593 100644 --- a/src/GitVersionTask/AssemblyInfo.cs +++ b/src/GitVersionTask/AssemblyInfo.cs @@ -1,6 +1,8 @@ using System.Reflection; +using System.Runtime.CompilerServices; [assembly: AssemblyTitle("GitVersionTask")] [assembly: AssemblyProduct("GitVersionTask")] [assembly: AssemblyVersion("1.0.0")] [assembly: AssemblyFileVersion("1.0.0")] +[assembly: InternalsVisibleTo("GitVersionTask.Tests")] \ No newline at end of file diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 99c620654c..16fedffb5e 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -13,7 +13,7 @@ public static class VersionAndBranchFinder { - static ConcurrentDictionary versionCacheVersions = new ConcurrentDictionary(); + internal static ConcurrentDictionary VersionCacheVersions = new ConcurrentDictionary(); public static bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication, IFileSystem fileSystem) @@ -41,7 +41,7 @@ public static VersionVariables GetVersion(string directory, Authentication authe var ticks = fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); string key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); - return versionCacheVersions.GetOrAdd(key, k => + return VersionCacheVersions.GetOrAdd(key, k => { Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache."); return LoadVersionVariablesFromDiskCache(k, directory, authentication, noFetch, fileSystem, gitDir, ticks); From 5000e3cbc7d3bbe36427784cfd2d559652b30d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 15:23:06 +0100 Subject: [PATCH 23/31] Rewrote the VersionAndBranchFinder tests so they do actual file system work, since AppVeyor don't seem to agree with local test running in that everything is green. Not trying to fake it may be a better solution anyhow. Ref https://ci.appveyor.com/project/GitTools/gitversion/build/3.3.1-PullRequest.711+28%20(Build%20458) --- .../VersionAndBranchFinderTests.cs | 97 +++++++++++++++++-- 1 file changed, 87 insertions(+), 10 deletions(-) diff --git a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs index f80025f01e..e90cd47421 100644 --- a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs +++ b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs @@ -9,6 +9,13 @@ #endregion +using System; +using System.Collections.Concurrent; +using System.Text; + +using GitVersion; +using GitVersion.Helpers; + using NUnit.Framework; using Shouldly; @@ -17,10 +24,9 @@ public class VersionAndBranchFinderTests { [Test] - public void ExistingCacheFile() + public void CacheFileExistsOnDisk() { - var fileSystem = new TestFileSystem(); - fileSystem.WriteAllText("existing\\gitversion_cache\\C7B23F8A47ECE0E14CBE2E22C04269CC5A88E275.yml", @" + const string versionCacheFileContent = @" Major: 4 Minor: 10 Patch: 3 @@ -43,21 +49,92 @@ public void ExistingCacheFile() CommitsSinceVersionSource: 19 CommitsSinceVersionSourcePadded: 0019 CommitDate: 2015-11-10 -"); +"; + + var infoBuilder = new StringBuilder(); + Action infoLogger = s => { infoBuilder.AppendLine(s); }; + + Logger.SetLoggers(infoLogger, null, null); + + using (var fixture = new EmptyRepositoryFixture(new Config())) + { + var fileSystem = new FileSystem(); + fixture.Repository.MakeACommit(); + var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); + + vv.AssemblySemVer.ShouldBe("0.1.0.0"); + + vv.FileName.ShouldNotBeNullOrEmpty(); + + fileSystem.WriteAllText(vv.FileName, versionCacheFileContent); + + // I would rather see that VersionAndBranchFinder was non-static and could be reinstantiated to + // clear the in-memory cache, but that's not the case, so I have to perform this ugly hack. @asbjornu + VersionAndBranchFinder.VersionCacheVersions = new ConcurrentDictionary(); + + vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); + + vv.AssemblySemVer.ShouldBe("4.10.3.0"); + } + + var info = infoBuilder.ToString(); + + Console.WriteLine(info); + + info.ShouldContain("Deserializing version variables from cache file", () => info); + } + + + [Test] + public void CacheFileExistsInMemory() + { + var infoBuilder = new StringBuilder(); + Action infoLogger = s => { infoBuilder.AppendLine(s); }; + + Logger.SetLoggers(infoLogger, null, null); + + using (var fixture = new EmptyRepositoryFixture(new Config())) + { + var fileSystem = new FileSystem(); + fixture.Repository.MakeACommit(); + var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); - var vv = VersionAndBranchFinder.GetVersion("existing", null, false, fileSystem); + vv.AssemblySemVer.ShouldBe("0.1.0.0"); - vv.AssemblySemVer.ShouldBe("4.10.3.0"); + vv.FileName.ShouldNotBeNullOrEmpty(); + + vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); + + vv.AssemblySemVer.ShouldBe("0.1.0.0"); + } + + var info = infoBuilder.ToString(); + + Console.WriteLine(info); + + info.ShouldContain("yml not found", () => info); + info.ShouldNotContain("Deserializing version variables from cache file", () => info); } [Test] - public void MissingCacheFile() + public void CacheFileIsMissing() { - var fileSystem = new TestFileSystem(); + var infoBuilder = new StringBuilder(); + Action infoLogger = s => { infoBuilder.AppendLine(s); }; + + Logger.SetLoggers(infoLogger, null, null); + + using (var fixture = new EmptyRepositoryFixture(new Config())) + { + fixture.Repository.MakeACommit(); + var fileSystem = new FileSystem(); + var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); - var vv = VersionAndBranchFinder.GetVersion("missing", null, false, fileSystem); + vv.AssemblySemVer.ShouldBe("0.1.0.0"); + } - vv.AssemblySemVer.ShouldBe("0.1.0.0"); + var info = infoBuilder.ToString(); + info.ShouldContain("yml not found", () => info); } } \ No newline at end of file From 1c2c2739d8201daef17fd4631ad03c82303459d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Fri, 13 Nov 2015 15:44:44 +0100 Subject: [PATCH 24/31] Made the VersionAndBranchFinder tests a bit more DRY --- .../VersionAndBranchFinderTests.cs | 65 ++++++------------- 1 file changed, 21 insertions(+), 44 deletions(-) diff --git a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs index e90cd47421..c7d6bf5ad6 100644 --- a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs +++ b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs @@ -51,35 +51,18 @@ public void CacheFileExistsOnDisk() CommitDate: 2015-11-10 "; - var infoBuilder = new StringBuilder(); - Action infoLogger = s => { infoBuilder.AppendLine(s); }; - - Logger.SetLoggers(infoLogger, null, null); - - using (var fixture = new EmptyRepositoryFixture(new Config())) + var info = RepositoryScope((fixture, vv, fs) => { - var fileSystem = new FileSystem(); - fixture.Repository.MakeACommit(); - var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); - - vv.AssemblySemVer.ShouldBe("0.1.0.0"); - - vv.FileName.ShouldNotBeNullOrEmpty(); - - fileSystem.WriteAllText(vv.FileName, versionCacheFileContent); + fs.WriteAllText(vv.FileName, versionCacheFileContent); // I would rather see that VersionAndBranchFinder was non-static and could be reinstantiated to // clear the in-memory cache, but that's not the case, so I have to perform this ugly hack. @asbjornu VersionAndBranchFinder.VersionCacheVersions = new ConcurrentDictionary(); - vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); + vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fs); vv.AssemblySemVer.ShouldBe("4.10.3.0"); - } - - var info = infoBuilder.ToString(); - - Console.WriteLine(info); + }); info.ShouldContain("Deserializing version variables from cache file", () => info); } @@ -88,29 +71,11 @@ public void CacheFileExistsOnDisk() [Test] public void CacheFileExistsInMemory() { - var infoBuilder = new StringBuilder(); - Action infoLogger = s => { infoBuilder.AppendLine(s); }; - - Logger.SetLoggers(infoLogger, null, null); - - using (var fixture = new EmptyRepositoryFixture(new Config())) + var info = RepositoryScope((fixture, vv, fs) => { - var fileSystem = new FileSystem(); - fixture.Repository.MakeACommit(); - var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); - + vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fs); vv.AssemblySemVer.ShouldBe("0.1.0.0"); - - vv.FileName.ShouldNotBeNullOrEmpty(); - - vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); - - vv.AssemblySemVer.ShouldBe("0.1.0.0"); - } - - var info = infoBuilder.ToString(); - - Console.WriteLine(info); + }); info.ShouldContain("yml not found", () => info); info.ShouldNotContain("Deserializing version variables from cache file", () => info); @@ -119,6 +84,13 @@ public void CacheFileExistsInMemory() [Test] public void CacheFileIsMissing() + { + var info = RepositoryScope(); + info.ShouldContain("yml not found", () => info); + } + + + static string RepositoryScope(Action fixtureAction = null) { var infoBuilder = new StringBuilder(); Action infoLogger = s => { infoBuilder.AppendLine(s); }; @@ -132,9 +104,14 @@ public void CacheFileIsMissing() var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); vv.AssemblySemVer.ShouldBe("0.1.0.0"); + vv.FileName.ShouldNotBeNullOrEmpty(); + + if (fixtureAction != null) + { + fixtureAction(fixture, vv, fileSystem); + } } - var info = infoBuilder.ToString(); - info.ShouldContain("yml not found", () => info); + return infoBuilder.ToString(); } } \ No newline at end of file From ba89853ab3338ca2a2dc4b9bcb8eaba39e075419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 10:05:35 +0100 Subject: [PATCH 25/31] Deleted `IFileSystem.TreeWalkForDotGitDir()` and replaced its usage with `Repository.Discover()`. --- src/GitVersionCore.Tests/FileSystemTests.cs | 13 ++---- .../Fixtures/RemoteRepositoryFixture.cs | 2 +- src/GitVersionCore.Tests/GitPreparerTests.cs | 14 +++--- src/GitVersionCore.Tests/TestFileSystem.cs | 6 --- src/GitVersionCore/ExecuteCore.cs | 13 ++++-- src/GitVersionCore/GitPreparer.cs | 46 ++++++++++--------- src/GitVersionCore/Helpers/FileSystem.cs | 13 ------ src/GitVersionCore/Helpers/IFileSystem.cs | 1 - src/GitVersionTask/VersionAndBranchFinder.cs | 4 +- 9 files changed, 49 insertions(+), 63 deletions(-) diff --git a/src/GitVersionCore.Tests/FileSystemTests.cs b/src/GitVersionCore.Tests/FileSystemTests.cs index 4e43a4a631..4d7e8f7de6 100644 --- a/src/GitVersionCore.Tests/FileSystemTests.cs +++ b/src/GitVersionCore.Tests/FileSystemTests.cs @@ -11,16 +11,13 @@ public class FileSystemTests { string workDirectory; string gitDirectory; - IFileSystem fileSystem; [SetUp] public void CreateTemporaryRepository() { - this.fileSystem = new FileSystem(); workDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - gitDirectory = Repository.Init(workDirectory) - .TrimEnd(new[] { Path.DirectorySeparatorChar }); + gitDirectory = Repository.Init(workDirectory); Assert.NotNull(gitDirectory); } @@ -34,26 +31,26 @@ public void Cleanup() [Test] public void From_WorkingDirectory() { - Assert.AreEqual(gitDirectory, fileSystem.TreeWalkForDotGitDir(workDirectory)); + Assert.AreEqual(gitDirectory, Repository.Discover(workDirectory)); } [Test] public void From_WorkingDirectory_Parent() { var parentDirectory = Directory.GetParent(workDirectory).FullName; - Assert.Null(fileSystem.TreeWalkForDotGitDir(parentDirectory)); + Assert.Null(Repository.Discover(parentDirectory)); } [Test] public void From_GitDirectory() { - Assert.AreEqual(gitDirectory, fileSystem.TreeWalkForDotGitDir(gitDirectory)); + Assert.AreEqual(gitDirectory, Repository.Discover(gitDirectory)); } [Test] public void From_RefsDirectory() { var refsDirectory = Path.Combine(gitDirectory, "refs"); - Assert.AreEqual(gitDirectory, fileSystem.TreeWalkForDotGitDir(refsDirectory)); + Assert.AreEqual(gitDirectory, Repository.Discover(refsDirectory)); } } diff --git a/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs b/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs index 3afc405641..ce53cb1e8c 100644 --- a/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs +++ b/src/GitVersionCore.Tests/Fixtures/RemoteRepositoryFixture.cs @@ -26,7 +26,7 @@ public RemoteRepositoryFixture(Config configuration) /// public void InitialiseRepo() { - new GitPreparer(null, null, new Authentication(), false, LocalRepositoryFixture.RepositoryPath, new FileSystem()).Initialise(true, null); + new GitPreparer(null, null, new Authentication(), false, LocalRepositoryFixture.RepositoryPath).Initialise(true, null); } static IRepository CreateNewRepository(string path) diff --git a/src/GitVersionCore.Tests/GitPreparerTests.cs b/src/GitVersionCore.Tests/GitPreparerTests.cs index 29aa9d9a53..ff9b344e1c 100644 --- a/src/GitVersionCore.Tests/GitPreparerTests.cs +++ b/src/GitVersionCore.Tests/GitPreparerTests.cs @@ -39,7 +39,7 @@ public void WorksCorrectlyWithRemoteRepository(string branchName, string expecte // Copy contents into working directory File.Copy(Path.Combine(fixture.RepositoryPath, "TestFile.txt"), Path.Combine(tempDir, "TestFile.txt")); - var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir); gitPreparer.Initialise(false, branchName); dynamicRepositoryPath = gitPreparer.GetDotGitDirectory(); @@ -77,7 +77,7 @@ public void UpdatesExistingDynamicRepository() { mainRepositoryFixture.Repository.MakeCommits(1); - var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir); gitPreparer.Initialise(false, "master"); dynamicRepositoryPath = gitPreparer.GetDotGitDirectory(); @@ -118,7 +118,7 @@ public void PicksAnotherDirectoryNameWhenDynamicRepoFolderTaken() expectedDynamicRepoLocation = Path.Combine(tempPath, fixture.RepositoryPath.Split('\\').Last()); Directory.CreateDirectory(expectedDynamicRepoLocation); - var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer(fixture.RepositoryPath, null, new Authentication(), false, tempDir); gitPreparer.Initialise(false, "master"); gitPreparer.IsDynamicGitRepository.ShouldBe(true); @@ -139,7 +139,7 @@ public void PicksAnotherDirectoryNameWhenDynamicRepoFolderTaken() public void WorksCorrectlyWithLocalRepository() { var tempDir = Path.GetTempPath(); - var gitPreparer = new GitPreparer(null, null, null, false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer(null, null, null, false, tempDir); var dynamicRepositoryPath = gitPreparer.GetDotGitDirectory(); dynamicRepositoryPath.ShouldBe(null); @@ -160,7 +160,7 @@ public void UsingDynamicRepositoryWithFeatureBranchWorks() { mainRepositoryFixture.Repository.MakeACommit(); - var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir); gitPreparer.Initialise(true, "feature1"); mainRepositoryFixture.Repository.Checkout(mainRepositoryFixture.Repository.CreateBranch("feature1")); @@ -188,7 +188,7 @@ public void UsingDynamicRepositoryWithoutTargetBranchFails() { mainRepositoryFixture.Repository.MakeACommit(); - var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer(mainRepositoryFixture.RepositoryPath, null, new Authentication(), false, tempDir); Should.Throw(() => gitPreparer.Initialise(true, null)); } @@ -209,7 +209,7 @@ public void TestErrorThrownForInvalidRepository() try { - var gitPreparer = new GitPreparer("http://127.0.0.1/testrepo.git", null, new Authentication(), false, tempDir, new FileSystem()); + var gitPreparer = new GitPreparer("http://127.0.0.1/testrepo.git", null, new Authentication(), false, tempDir); Should.Throw(() => gitPreparer.Initialise(true, "master")); } diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index aab83d642d..a64f4cd278 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -93,12 +93,6 @@ public long GetLastDirectoryWrite(string path) } - public string TreeWalkForDotGitDir(string directory) - { - return directory; - } - - public IRepository GetRepository(string gitDirectory) { var repository = Substitute.For(); diff --git a/src/GitVersionCore/ExecuteCore.cs b/src/GitVersionCore/ExecuteCore.cs index a6eab7f4a6..9e6a2adb28 100644 --- a/src/GitVersionCore/ExecuteCore.cs +++ b/src/GitVersionCore/ExecuteCore.cs @@ -2,6 +2,7 @@ namespace GitVersion { using System; using System.Linq; + using GitVersion.Helpers; public static class ExecuteCore @@ -9,7 +10,7 @@ public static class ExecuteCore public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId) { // Normalise if we are running on build server - var gitPreparer = new GitPreparer(targetUrl, dynamicRepositoryLocation, authentication, noFetch, workingDirectory, fileSystem); + var gitPreparer = new GitPreparer(targetUrl, dynamicRepositoryLocation, authentication, noFetch, workingDirectory); var applicableBuildServers = BuildServerList.GetApplicableBuildServers(); var buildServer = applicableBuildServers.FirstOrDefault(); @@ -29,7 +30,7 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string using (var repo = fileSystem.GetRepository(dotGitDirectory)) { - var gitVersionContext = new GitVersionContext(repo, configuration, commitId: commitId); + var gitVersionContext = new GitVersionContext(repo, configuration, commitId : commitId); var semanticVersion = versionFinder.FindVersion(gitVersionContext); variables = VariableProvider.GetVariablesFor(semanticVersion, gitVersionContext.Configuration, gitVersionContext.IsCurrentCommitTagged); } @@ -37,9 +38,13 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string return variables; } - private static string ResolveCurrentBranch(IBuildServer buildServer, string targetBranch) + + static string ResolveCurrentBranch(IBuildServer buildServer, string targetBranch) { - if (buildServer == null) return targetBranch; + if (buildServer == null) + { + return targetBranch; + } var currentBranch = buildServer.GetCurrentBranch() ?? targetBranch; Logger.WriteInfo("Branch from build environment: " + currentBranch); diff --git a/src/GitVersionCore/GitPreparer.cs b/src/GitVersionCore/GitPreparer.cs index 0441500074..92d5ec7e14 100644 --- a/src/GitVersionCore/GitPreparer.cs +++ b/src/GitVersionCore/GitPreparer.cs @@ -4,35 +4,27 @@ namespace GitVersion using System.IO; using System.Linq; - using GitVersion.Helpers; - using LibGit2Sharp; public class GitPreparer { - string targetUrl; - string dynamicRepositoryLocation; Authentication authentication; + string dynamicRepositoryLocation; bool noFetch; string targetPath; - readonly IFileSystem fileSystem; + string targetUrl; - public GitPreparer(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, bool noFetch, string targetPath, IFileSystem fileSystem) + public GitPreparer(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, bool noFetch, string targetPath) { - if (fileSystem == null) - { - throw new ArgumentNullException("fileSystem"); - } - this.targetUrl = targetUrl; this.dynamicRepositoryLocation = dynamicRepositoryLocation; this.authentication = authentication; this.noFetch = noFetch; this.targetPath = targetPath; - this.fileSystem = fileSystem; } + public bool IsDynamicGitRepository { get { return !string.IsNullOrWhiteSpace(DynamicGitRepositoryPath); } @@ -40,6 +32,7 @@ public bool IsDynamicGitRepository public string DynamicGitRepositoryPath { get; private set; } + public void Initialise(bool normaliseGitDirectory, string currentBranch) { if (string.IsNullOrWhiteSpace(targetUrl)) @@ -56,6 +49,7 @@ public void Initialise(bool normaliseGitDirectory, string currentBranch) DynamicGitRepositoryPath = CreateDynamicRepository(tempRepositoryPath, authentication, targetUrl, currentBranch, noFetch); } + static string CalculateTemporaryRepositoryPath(string targetUrl, string dynamicRepositoryLocation) { var userTemp = dynamicRepositoryLocation ?? Path.GetTempPath(); @@ -81,6 +75,7 @@ static string CalculateTemporaryRepositoryPath(string targetUrl, string dynamicR return possiblePath; } + static bool GitRepoHasMatchingRemote(string possiblePath, string targetUrl) { try @@ -94,25 +89,31 @@ static bool GitRepoHasMatchingRemote(string possiblePath, string targetUrl) { return false; } - } + public string GetDotGitDirectory() { if (IsDynamicGitRepository) + { return DynamicGitRepositoryPath; + } - return this.fileSystem.TreeWalkForDotGitDir(targetPath); + return Repository.Discover(this.targetPath); } + public string GetProjectRootDirectory() { if (IsDynamicGitRepository) + { return targetPath; + } - return Directory.GetParent(this.fileSystem.TreeWalkForDotGitDir(targetPath)).FullName; + return Directory.GetParent(Repository.Discover(this.targetPath)).FullName; } + static string CreateDynamicRepository(string targetPath, Authentication authentication, string repositoryUrl, string targetBranch, bool noFetch) { if (string.IsNullOrWhiteSpace(targetBranch)) @@ -138,7 +139,8 @@ static string CreateDynamicRepository(string targetPath, Authentication authenti return gitDirectory; } - private static void CloneRepository(string repositoryUrl, string gitDirectory, Authentication authentication) + + static void CloneRepository(string repositoryUrl, string gitDirectory, Authentication authentication) { Credentials credentials = null; if (!string.IsNullOrWhiteSpace(authentication.Username) && !string.IsNullOrWhiteSpace(authentication.Password)) @@ -157,11 +159,11 @@ private static void CloneRepository(string repositoryUrl, string gitDirectory, A try { Repository.Clone(repositoryUrl, gitDirectory, - new CloneOptions - { - Checkout = false, - CredentialsProvider = (url, usernameFromUrl, types) => credentials - }); + new CloneOptions + { + Checkout = false, + CredentialsProvider = (url, usernameFromUrl, types) => credentials + }); } catch (LibGit2SharpException ex) { @@ -178,7 +180,7 @@ private static void CloneRepository(string repositoryUrl, string gitDirectory, A { throw new Exception("Not found: The repository was not found"); } - + throw new Exception("There was an unknown problem with the Git repository you provided"); } } diff --git a/src/GitVersionCore/Helpers/FileSystem.cs b/src/GitVersionCore/Helpers/FileSystem.cs index 54360a63cc..1a4b51a544 100644 --- a/src/GitVersionCore/Helpers/FileSystem.cs +++ b/src/GitVersionCore/Helpers/FileSystem.cs @@ -80,19 +80,6 @@ public long GetLastDirectoryWrite(string path) } - public string TreeWalkForDotGitDir(string directory) - { - var gitDirectory = Repository.Discover(directory); - - if (gitDirectory != null) - { - return gitDirectory.TrimEnd(Path.DirectorySeparatorChar); - } - - return null; - } - - public IRepository GetRepository(string gitDirectory) { try diff --git a/src/GitVersionCore/Helpers/IFileSystem.cs b/src/GitVersionCore/Helpers/IFileSystem.cs index 95d1e087a5..524fd3d293 100644 --- a/src/GitVersionCore/Helpers/IFileSystem.cs +++ b/src/GitVersionCore/Helpers/IFileSystem.cs @@ -18,7 +18,6 @@ public interface IFileSystem Stream OpenRead(string path); void CreateDirectory(string path); long GetLastDirectoryWrite(string path); - string TreeWalkForDotGitDir(string directory); IRepository GetRepository(string gitDirectory); } } \ No newline at end of file diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 16fedffb5e..3ff45c4424 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -9,6 +9,8 @@ using GitVersion; using GitVersion.Helpers; +using LibGit2Sharp; + using YamlDotNet.Serialization; public static class VersionAndBranchFinder @@ -34,7 +36,7 @@ public static bool TryGetVersion(string directory, out VersionVariables versionV public static VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem) { - var gitDir = fileSystem.TreeWalkForDotGitDir(directory); + var gitDir = Repository.Discover(directory); using (var repo = fileSystem.GetRepository(gitDir)) { // Maybe using timestamp in .git/refs directory is enough? From 7b5e3c5cecaabd65e76ca27738e3486adc8d646e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 10:06:50 +0100 Subject: [PATCH 26/31] Removed license --- .../VersionAndBranchFinderTests.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs index c7d6bf5ad6..8b9cce2e6e 100644 --- a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs +++ b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs @@ -1,15 +1,4 @@ -#region License - -// -------------------------------------------------- -// Copyright © OKB. All Rights Reserved. -// -// This software is proprietary information of OKB. -// USE IS SUBJECT TO LICENSE TERMS. -// -------------------------------------------------- - -#endregion - -using System; +using System; using System.Collections.Concurrent; using System.Text; From 817729d9495e72d87ad4e4aa098d17ecbd564bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 10:17:05 +0100 Subject: [PATCH 27/31] Removed mocking of IRepository since it's not being used by any of the tests anymore. --- src/GitVersionCore.Tests/TestFileSystem.cs | 87 +--------------------- 1 file changed, 1 insertion(+), 86 deletions(-) diff --git a/src/GitVersionCore.Tests/TestFileSystem.cs b/src/GitVersionCore.Tests/TestFileSystem.cs index a64f4cd278..50b4dcde16 100644 --- a/src/GitVersionCore.Tests/TestFileSystem.cs +++ b/src/GitVersionCore.Tests/TestFileSystem.cs @@ -1,15 +1,12 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using GitVersion.Helpers; using LibGit2Sharp; -using NSubstitute; - public class TestFileSystem : IFileSystem { Dictionary fileSystem = new Dictionary(); @@ -95,88 +92,6 @@ public long GetLastDirectoryWrite(string path) public IRepository GetRepository(string gitDirectory) { - var repository = Substitute.For(); - var tip = Substitute.For(); - tip.Committer.Returns(new Signature("Asbj�rn Ulsberg", "asbjorn@ulsberg.no", new DateTimeOffset(2015, 11, 10, 13, 37, 0, TimeSpan.FromHours(1)))); - var commits = new Commits - { - tip - }; - repository.Commits.QueryBy(null).ReturnsForAnyArgs(commits); - var head = Substitute.For(); - head.CanonicalName.Returns("refs/heads/master"); - tip.Sha.Returns("e7da1b19d03394896fb8da8916cd26f0efb1566f"); - head.Tip.Returns(tip); - repository.Head.Returns(head); - var branches = new Branches - { - { "master", tip } - }; - - repository.Branches.Returns(branches); - return repository; - } - - - class Branches : BranchCollection - { - IList branches; - - - public Branches() - { - this.branches = new List(); - } - - - public override Branch this[string name] - { - get { return this.branches.FirstOrDefault(b => b.Name == name); } - } - - - public override Branch Add(string name, Commit commit, bool allowOverwrite = false) - { - var branch = Substitute.For(); - branch.Name.Returns(name); - branch.Tip.Returns(commit); - this.branches.Add(branch); - return branch; - } - - - public override Branch Add(string name, Commit commit, Signature signature, string logMessage = null, bool allowOverwrite = false) - { - return Add(name, commit, allowOverwrite); - } - - - public override IEnumerator GetEnumerator() - { - return this.branches.GetEnumerator(); - } - } - - class Commits : List, IQueryableCommitLog - { - public CommitSortStrategies SortedBy { get; private set; } - - - public ICommitLog QueryBy(CommitFilter filter) - { - throw new NotImplementedException(); - } - - - public Commit FindMergeBase(Commit first, Commit second) - { - throw new NotImplementedException(); - } - - - public Commit FindMergeBase(IEnumerable commits, MergeBaseFindingStrategy strategy) - { - throw new NotImplementedException(); - } + throw new NotImplementedException(); } } \ No newline at end of file From c6943e61515385c23e16a26a6bd2a5208fa6e5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 11:20:03 +0100 Subject: [PATCH 28/31] R# cleanup --- .../GitVersionTaskDirectoryTests.cs | 25 +++++---- .../AssemblyInfoBuilder/UpdateAssemblyInfo.cs | 45 +++++++++------- src/GitVersionTask/GetVersion.cs | 26 +++++----- src/GitVersionTask/VersionAndBranchFinder.cs | 20 +++---- .../WriteVersionInfoToBuildLog.cs | 52 ++++++++++--------- 5 files changed, 92 insertions(+), 76 deletions(-) diff --git a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs index 0c80458a56..44e5671d84 100644 --- a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs +++ b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs @@ -1,37 +1,41 @@ using System; using System.IO; + using LibGit2Sharp; + using NUnit.Framework; [TestFixture] public class GitVersionTaskDirectoryTests { - string workDirectory; string gitDirectory; + string workDirectory; + [SetUp] public void CreateTemporaryRepository() { - workDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + this.workDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + this.gitDirectory = Repository.Init(this.workDirectory) + .TrimEnd(Path.DirectorySeparatorChar); - gitDirectory = Repository.Init(workDirectory) - .TrimEnd(new[] { Path.DirectorySeparatorChar }); - - Assert.NotNull(gitDirectory); + Assert.NotNull(this.gitDirectory); } + [TearDown] public void Cleanup() { - Directory.Delete(workDirectory, true); + Directory.Delete(this.workDirectory, true); } + [Test] public void Finds_GitDirectory() { try { - VersionAndBranchFinder.GetVersion(workDirectory, null, true, null); + VersionAndBranchFinder.GetVersion(this.workDirectory, null, true, null); } catch (Exception ex) { @@ -41,10 +45,11 @@ public void Finds_GitDirectory() } } + [Test] public void Finds_GitDirectory_In_Parent() { - var childDir = Path.Combine(workDirectory, "child"); + var childDir = Path.Combine(this.workDirectory, "child"); Directory.CreateDirectory(childDir); try @@ -58,4 +63,4 @@ public void Finds_GitDirectory_In_Parent() Assert.IsNotAssignableFrom(ex); } } -} +} \ No newline at end of file diff --git a/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs b/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs index 046f81c704..4d1a26d104 100644 --- a/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs +++ b/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs @@ -3,14 +3,30 @@ using System; using System.IO; using System.Text; + using GitVersion; using GitVersion.Helpers; + using Microsoft.Build.Framework; - using Microsoft.Build.Utilities; - using Logger = GitVersion.Logger; public class UpdateAssemblyInfo : Task { + IFileSystem fileSystem; + + TaskLogger logger; + + + public UpdateAssemblyInfo() + { + CompileFiles = new ITaskItem[] + { + }; + this.logger = new TaskLogger(this); + this.fileSystem = new FileSystem(); + Logger.SetLoggers(this.LogInfo, this.LogWarning, s => this.LogError(s)); + } + + [Required] public string SolutionDirectory { get; set; } @@ -31,19 +47,6 @@ public class UpdateAssemblyInfo : Task public bool NoFetch { get; set; } - TaskLogger logger; - IFileSystem fileSystem; - - public UpdateAssemblyInfo() - { - CompileFiles = new ITaskItem[] { }; - logger = new TaskLogger(this); - fileSystem = new FileSystem(); - Logger.SetLoggers( - this.LogInfo, - this.LogWarning, - s => this.LogError(s)); - } public override bool Execute() { @@ -54,12 +57,12 @@ public override bool Execute() } catch (WarningException errorException) { - logger.LogWarning(errorException.Message); + this.logger.LogWarning(errorException.Message); return true; } catch (Exception exception) { - logger.LogError("Error occurred: " + exception); + this.logger.LogError("Error occurred: " + exception); return false; } finally @@ -68,20 +71,22 @@ public override bool Execute() } } - public void InnerExecute() + + void InnerExecute() { TempFileTracker.DeleteTempFiles(); InvalidFileChecker.CheckForInvalidFiles(CompileFiles, ProjectFile); VersionVariables versionVariables; - if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out versionVariables, NoFetch, new Authentication(), fileSystem)) + if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out versionVariables, NoFetch, new Authentication())) { return; } CreateTempAssemblyInfo(versionVariables); } + void CreateTempAssemblyInfo(VersionVariables versionVariables) { if (IntermediateOutputPath == null) @@ -105,7 +110,9 @@ void CreateTempAssemblyInfo(VersionVariables versionVariables) { var content = File.ReadAllText(AssemblyInfoTempFilePath, Encoding.UTF8).Trim(); if (string.Equals(assemblyInfo, content, StringComparison.Ordinal)) + { return; // nothign to do as the file matches what we'd create + } } } catch (Exception) diff --git a/src/GitVersionTask/GetVersion.cs b/src/GitVersionTask/GetVersion.cs index 93c46d2044..b4ea18669b 100644 --- a/src/GitVersionTask/GetVersion.cs +++ b/src/GitVersionTask/GetVersion.cs @@ -9,6 +9,17 @@ public class GetVersion : Task { + TaskLogger logger; + + + public GetVersion() + { + this.logger = new TaskLogger(this); + this.fileSystem = new FileSystem(); + Logger.SetLoggers(this.LogInfo, this.LogWarning, s => this.LogError(s)); + } + + [Required] public string SolutionDirectory { get; set; } @@ -80,19 +91,8 @@ public class GetVersion : Task [Output] public string CommitsSinceVersionSourcePadded { get; set; } - TaskLogger logger; IFileSystem fileSystem; - public GetVersion() - { - logger = new TaskLogger(this); - fileSystem = new FileSystem(); - Logger.SetLoggers( - this.LogInfo, - this.LogWarning, - s => this.LogError(s)); - } - public override bool Execute() { try @@ -111,12 +111,12 @@ public override bool Execute() } catch (WarningException errorException) { - logger.LogWarning(errorException.Message); + this.logger.LogWarning(errorException.Message); return true; } catch (Exception exception) { - logger.LogError("Error occurred: " + exception); + this.logger.LogError("Error occurred: " + exception); return false; } finally diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 3ff45c4424..41c2374618 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -103,18 +103,20 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir vv.FileName = cacheFileName; using (var stream = fileSystem.OpenWrite(cacheFileName)) - using (var sw = new StreamWriter(stream)) { - Dictionary dictionary; - using (Logger.IndentLog("Creating dictionary")) + using (var sw = new StreamWriter(stream)) { - dictionary = vv.ToDictionary(x => x.Key, x => x.Value); - } + Dictionary dictionary; + using (Logger.IndentLog("Creating dictionary")) + { + dictionary = vv.ToDictionary(x => x.Key, x => x.Value); + } - using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName)) - { - var serializer = new Serializer(); - serializer.Serialize(sw, dictionary); + using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName)) + { + var serializer = new Serializer(); + serializer.Serialize(sw, dictionary); + } } } } diff --git a/src/GitVersionTask/WriteVersionInfoToBuildLog.cs b/src/GitVersionTask/WriteVersionInfoToBuildLog.cs index 262191a301..deb246746c 100644 --- a/src/GitVersionTask/WriteVersionInfoToBuildLog.cs +++ b/src/GitVersionTask/WriteVersionInfoToBuildLog.cs @@ -1,33 +1,33 @@ namespace GitVersionTask { + using System; + using System.Collections.Generic; + using GitVersion; using GitVersion.Helpers; + using Microsoft.Build.Framework; - using Microsoft.Build.Utilities; - using System; - using System.Collections.Generic; - using Logger = GitVersion.Logger; public class WriteVersionInfoToBuildLog : Task { - [Required] - public string SolutionDirectory { get; set; } - - public bool NoFetch { get; set; } + readonly IFileSystem fileSystem; + readonly TaskLogger logger; - TaskLogger logger; - IFileSystem fileSystem; public WriteVersionInfoToBuildLog() { - logger = new TaskLogger(this); - fileSystem = new FileSystem(); - Logger.SetLoggers( - this.LogInfo, - this.LogWarning, - s => this.LogError(s)); + this.logger = new TaskLogger(this); + this.fileSystem = new FileSystem(); + Logger.SetLoggers(this.LogInfo, this.LogWarning, s => this.LogError(s)); } + + [Required] + public string SolutionDirectory { get; set; } + + public bool NoFetch { get; set; } + + public override bool Execute() { try @@ -37,12 +37,12 @@ public override bool Execute() } catch (WarningException errorException) { - logger.LogWarning(errorException.Message); + this.logger.LogWarning(errorException.Message); return true; } catch (Exception exception) { - logger.LogError("Error occurred: " + exception); + this.logger.LogError("Error occurred: " + exception); return false; } finally @@ -51,27 +51,29 @@ public override bool Execute() } } - public void InnerExecute() + + void InnerExecute() { VersionVariables result; if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out result, NoFetch, new Authentication(), fileSystem)) { return; } - + WriteIntegrationParameters(BuildServerList.GetApplicableBuildServers(), result); } - public void WriteIntegrationParameters(IEnumerable applicableBuildServers, VersionVariables variables) + + void WriteIntegrationParameters(IEnumerable applicableBuildServers, VersionVariables variables) { foreach (var buildServer in applicableBuildServers) { - logger.LogInfo(string.Format("Executing GenerateSetVersionMessage for '{0}'.", buildServer.GetType().Name)); - logger.LogInfo(buildServer.GenerateSetVersionMessage(variables)); - logger.LogInfo(string.Format("Executing GenerateBuildLogOutput for '{0}'.", buildServer.GetType().Name)); + this.logger.LogInfo(string.Format("Executing GenerateSetVersionMessage for '{0}'.", buildServer.GetType().Name)); + this.logger.LogInfo(buildServer.GenerateSetVersionMessage(variables)); + this.logger.LogInfo(string.Format("Executing GenerateBuildLogOutput for '{0}'.", buildServer.GetType().Name)); foreach (var buildParameter in BuildOutputFormatter.GenerateBuildLogOutput(buildServer, variables)) { - logger.LogInfo(buildParameter); + this.logger.LogInfo(buildParameter); } } } From f7f95c25fbd18bb7caa7e62a0623b752b1ad0e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 12:54:27 +0100 Subject: [PATCH 29/31] Refactored `VersionAndBranchFinder` to a non-static file. --- .../GitVersionTaskDirectoryTests.cs | 7 +-- .../VersionAndBranchFinderTests.cs | 39 ++++++++------ .../AssemblyInfoBuilder/UpdateAssemblyInfo.cs | 6 +-- src/GitVersionTask/GetVersion.cs | 11 ++-- src/GitVersionTask/GitVersionTask.csproj | 1 + src/GitVersionTask/GitVersionTaskBase.cs | 34 ++++++++++++ src/GitVersionTask/VersionAndBranchFinder.cs | 53 ++++++++++++------- .../WriteVersionInfoToBuildLog.cs | 7 +-- 8 files changed, 105 insertions(+), 53 deletions(-) create mode 100644 src/GitVersionTask/GitVersionTaskBase.cs diff --git a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs index 44e5671d84..3cf5219e03 100644 --- a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs +++ b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs @@ -9,6 +9,7 @@ public class GitVersionTaskDirectoryTests { string gitDirectory; + VersionAndBranchFinder versionAndBranchFinder; string workDirectory; @@ -18,7 +19,7 @@ public void CreateTemporaryRepository() this.workDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); this.gitDirectory = Repository.Init(this.workDirectory) .TrimEnd(Path.DirectorySeparatorChar); - + this.versionAndBranchFinder = new VersionAndBranchFinder(new TestFileSystem()); Assert.NotNull(this.gitDirectory); } @@ -35,7 +36,7 @@ public void Finds_GitDirectory() { try { - VersionAndBranchFinder.GetVersion(this.workDirectory, null, true, null); + this.versionAndBranchFinder.GetVersion(this.workDirectory, null, true); } catch (Exception ex) { @@ -54,7 +55,7 @@ public void Finds_GitDirectory_In_Parent() try { - VersionAndBranchFinder.GetVersion(childDir, null, true, null); + this.versionAndBranchFinder.GetVersion(childDir, null, true); } catch (Exception ex) { diff --git a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs index 8b9cce2e6e..a3b1c0029b 100644 --- a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs +++ b/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs @@ -12,6 +12,16 @@ [TestFixture] public class VersionAndBranchFinderTests { + IFileSystem fileSystem; + + + [SetUp] + public void SetUp() + { + this.fileSystem = new FileSystem(); + } + + [Test] public void CacheFileExistsOnDisk() { @@ -40,16 +50,12 @@ public void CacheFileExistsOnDisk() CommitDate: 2015-11-10 "; - var info = RepositoryScope((fixture, vv, fs) => - { - fs.WriteAllText(vv.FileName, versionCacheFileContent); - - // I would rather see that VersionAndBranchFinder was non-static and could be reinstantiated to - // clear the in-memory cache, but that's not the case, so I have to perform this ugly hack. @asbjornu - VersionAndBranchFinder.VersionCacheVersions = new ConcurrentDictionary(); - - vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fs); + var versionAndBranchFinder = new VersionAndBranchFinder(this.fileSystem); + var info = RepositoryScope(versionAndBranchFinder, (fixture, vv) => + { + this.fileSystem.WriteAllText(vv.FileName, versionCacheFileContent); + vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false); vv.AssemblySemVer.ShouldBe("4.10.3.0"); }); @@ -60,9 +66,12 @@ public void CacheFileExistsOnDisk() [Test] public void CacheFileExistsInMemory() { - var info = RepositoryScope((fixture, vv, fs) => + var cache = new ConcurrentDictionary(); + var versionAndBranchFinder = new VersionAndBranchFinder(this.fileSystem, cache.GetOrAdd); + + var info = RepositoryScope(versionAndBranchFinder, (fixture, vv) => { - vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fs); + vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false); vv.AssemblySemVer.ShouldBe("0.1.0.0"); }); @@ -79,25 +88,25 @@ public void CacheFileIsMissing() } - static string RepositoryScope(Action fixtureAction = null) + string RepositoryScope(VersionAndBranchFinder versionAndBranchFinder = null, Action fixtureAction = null) { var infoBuilder = new StringBuilder(); Action infoLogger = s => { infoBuilder.AppendLine(s); }; + versionAndBranchFinder = versionAndBranchFinder ?? new VersionAndBranchFinder(this.fileSystem); Logger.SetLoggers(infoLogger, null, null); using (var fixture = new EmptyRepositoryFixture(new Config())) { fixture.Repository.MakeACommit(); - var fileSystem = new FileSystem(); - var vv = VersionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false, fileSystem); + var vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false); vv.AssemblySemVer.ShouldBe("0.1.0.0"); vv.FileName.ShouldNotBeNullOrEmpty(); if (fixtureAction != null) { - fixtureAction(fixture, vv, fileSystem); + fixtureAction(fixture, vv); } } diff --git a/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs b/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs index 4d1a26d104..8d770cbcca 100644 --- a/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs +++ b/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs @@ -5,14 +5,11 @@ using System.Text; using GitVersion; - using GitVersion.Helpers; using Microsoft.Build.Framework; - public class UpdateAssemblyInfo : Task + public class UpdateAssemblyInfo : GitVersionTaskBase { - IFileSystem fileSystem; - TaskLogger logger; @@ -22,7 +19,6 @@ public UpdateAssemblyInfo() { }; this.logger = new TaskLogger(this); - this.fileSystem = new FileSystem(); Logger.SetLoggers(this.LogInfo, this.LogWarning, s => this.LogError(s)); } diff --git a/src/GitVersionTask/GetVersion.cs b/src/GitVersionTask/GetVersion.cs index b4ea18669b..22c03e902a 100644 --- a/src/GitVersionTask/GetVersion.cs +++ b/src/GitVersionTask/GetVersion.cs @@ -1,13 +1,12 @@ namespace GitVersionTask { using System; + using GitVersion; - using GitVersion.Helpers; + using Microsoft.Build.Framework; - using Microsoft.Build.Utilities; - using Logger = GitVersion.Logger; - public class GetVersion : Task + public class GetVersion : GitVersionTaskBase { TaskLogger logger; @@ -15,7 +14,6 @@ public class GetVersion : Task public GetVersion() { this.logger = new TaskLogger(this); - this.fileSystem = new FileSystem(); Logger.SetLoggers(this.LogInfo, this.LogWarning, s => this.LogError(s)); } @@ -91,7 +89,6 @@ public GetVersion() [Output] public string CommitsSinceVersionSourcePadded { get; set; } - IFileSystem fileSystem; public override bool Execute() { @@ -99,7 +96,7 @@ public override bool Execute() { VersionVariables variables; - if (VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out variables, NoFetch, new Authentication(), fileSystem)) + if (VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out variables, NoFetch, new Authentication())) { var thisType = typeof(GetVersion); foreach (var variable in variables) diff --git a/src/GitVersionTask/GitVersionTask.csproj b/src/GitVersionTask/GitVersionTask.csproj index b6dad9acc0..d3794b4dc1 100644 --- a/src/GitVersionTask/GitVersionTask.csproj +++ b/src/GitVersionTask/GitVersionTask.csproj @@ -60,6 +60,7 @@ + diff --git a/src/GitVersionTask/GitVersionTaskBase.cs b/src/GitVersionTask/GitVersionTaskBase.cs new file mode 100644 index 0000000000..c6338e5c19 --- /dev/null +++ b/src/GitVersionTask/GitVersionTaskBase.cs @@ -0,0 +1,34 @@ +namespace GitVersionTask +{ + using System.Collections.Concurrent; + + using GitVersion; + using GitVersion.Helpers; + + using Microsoft.Build.Utilities; + + public abstract class GitVersionTaskBase : Task + { + static readonly ConcurrentDictionary versionVariablesCache; + readonly VersionAndBranchFinder versionAndBranchFinder; + + + static GitVersionTaskBase() + { + versionVariablesCache = new ConcurrentDictionary(); + } + + + protected GitVersionTaskBase() + { + var fileSystem = new FileSystem(); + this.versionAndBranchFinder = new VersionAndBranchFinder(fileSystem, versionVariablesCache.GetOrAdd); + } + + + protected VersionAndBranchFinder VersionAndBranchFinder + { + get { return this.versionAndBranchFinder; } + } + } +} \ No newline at end of file diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs index 41c2374618..1a1f52f020 100644 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ b/src/GitVersionTask/VersionAndBranchFinder.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -13,16 +12,29 @@ using YamlDotNet.Serialization; -public static class VersionAndBranchFinder +public class VersionAndBranchFinder { - internal static ConcurrentDictionary VersionCacheVersions = new ConcurrentDictionary(); + readonly IFileSystem fileSystem; + readonly Func, VersionVariables> getVersionVariablesFromMemoryCache; - public static bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication, IFileSystem fileSystem) + public VersionAndBranchFinder(IFileSystem fileSystem, Func, VersionVariables> getVersionVariablesFromMemoryCache = null) + { + if (fileSystem == null) + { + throw new ArgumentNullException("fileSystem"); + } + + this.getVersionVariablesFromMemoryCache = getVersionVariablesFromMemoryCache; + this.fileSystem = fileSystem; + } + + + public bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication) { try { - versionVariables = GetVersion(directory, authentication, noFetch, fileSystem); + versionVariables = GetVersion(directory, authentication, noFetch); return true; } catch (Exception ex) @@ -34,25 +46,30 @@ public static bool TryGetVersion(string directory, out VersionVariables versionV } - public static VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem) + public VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch) { var gitDir = Repository.Discover(directory); - using (var repo = fileSystem.GetRepository(gitDir)) + using (var repo = this.fileSystem.GetRepository(gitDir)) { // Maybe using timestamp in .git/refs directory is enough? - var ticks = fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); - string key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); + var ticks = this.fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); + var key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); - return VersionCacheVersions.GetOrAdd(key, k => + if (this.getVersionVariablesFromMemoryCache != null) { - Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache."); - return LoadVersionVariablesFromDiskCache(k, directory, authentication, noFetch, fileSystem, gitDir, ticks); - }); + return this.getVersionVariablesFromMemoryCache(key, k => + { + Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache."); + return LoadVersionVariablesFromDiskCache(key, directory, authentication, noFetch, gitDir); + }); + } + + return LoadVersionVariablesFromDiskCache(key, directory, authentication, noFetch, gitDir); } } - static VersionVariables LoadVersionVariablesFromDiskCache(string key, string directory, Authentication authentication, bool noFetch, IFileSystem fileSystem, string gitDir, long ticks) + VersionVariables LoadVersionVariablesFromDiskCache(string key, string directory, Authentication authentication, bool noFetch, string gitDir) { using (Logger.IndentLog("Loading version variables from disk cache")) { @@ -65,11 +82,11 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir var cacheDir = Path.Combine(gitDir, "gitversion_cache"); // If the cacheDir already exists, CreateDirectory just won't do anything (it won't fail). @asbjornu - fileSystem.CreateDirectory(cacheDir); + this.fileSystem.CreateDirectory(cacheDir); var cacheFileName = string.Concat(Path.Combine(cacheDir, cacheKey), ".yml"); VersionVariables vv = null; - if (fileSystem.Exists(cacheFileName)) + if (this.fileSystem.Exists(cacheFileName)) { using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName)) { @@ -83,7 +100,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir Logger.WriteInfo(ex.ToString()); try { - fileSystem.Delete(cacheFileName); + this.fileSystem.Delete(cacheFileName); } catch (Exception deleteEx) { @@ -99,7 +116,7 @@ static VersionVariables LoadVersionVariablesFromDiskCache(string key, string dir if (vv == null) { - vv = ExecuteCore.ExecuteGitVersion(fileSystem, null, null, authentication, null, noFetch, directory, null); + vv = ExecuteCore.ExecuteGitVersion(this.fileSystem, null, null, authentication, null, noFetch, directory, null); vv.FileName = cacheFileName; using (var stream = fileSystem.OpenWrite(cacheFileName)) diff --git a/src/GitVersionTask/WriteVersionInfoToBuildLog.cs b/src/GitVersionTask/WriteVersionInfoToBuildLog.cs index deb246746c..42cf5047cf 100644 --- a/src/GitVersionTask/WriteVersionInfoToBuildLog.cs +++ b/src/GitVersionTask/WriteVersionInfoToBuildLog.cs @@ -4,20 +4,17 @@ using System.Collections.Generic; using GitVersion; - using GitVersion.Helpers; using Microsoft.Build.Framework; - public class WriteVersionInfoToBuildLog : Task + public class WriteVersionInfoToBuildLog : GitVersionTaskBase { - readonly IFileSystem fileSystem; readonly TaskLogger logger; public WriteVersionInfoToBuildLog() { this.logger = new TaskLogger(this); - this.fileSystem = new FileSystem(); Logger.SetLoggers(this.LogInfo, this.LogWarning, s => this.LogError(s)); } @@ -55,7 +52,7 @@ public override bool Execute() void InnerExecute() { VersionVariables result; - if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out result, NoFetch, new Authentication(), fileSystem)) + if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out result, NoFetch, new Authentication())) { return; } From 5dd4d3f51f72b35572da7d90c85a9e81b7818723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 16:46:08 +0100 Subject: [PATCH 30/31] Avoid `NullReferenceException` in `Logger` by null-guarding the loggers in `SetLoggers()`. --- src/GitVersionCore/Logger.cs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/GitVersionCore/Logger.cs b/src/GitVersionCore/Logger.cs index d880b0f9cc..9fe8621741 100644 --- a/src/GitVersionCore/Logger.cs +++ b/src/GitVersionCore/Logger.cs @@ -9,16 +9,18 @@ public static class Logger static readonly Regex ObscurePasswordRegex = new Regex("(https?://)(.+)(:.+@)", RegexOptions.Compiled); static string indent = string.Empty; - public static Action WriteInfo { get; private set; } - public static Action WriteWarning { get; private set; } - public static Action WriteError { get; private set; } - static Logger() { Reset(); } + + public static Action WriteInfo { get; private set; } + public static Action WriteWarning { get; private set; } + public static Action WriteError { get; private set; } + + public static IDisposable IndentLog(string operationDescription) { var start = DateTime.Now; @@ -31,6 +33,7 @@ public static IDisposable IndentLog(string operationDescription) }); } + static Action ObscurePassword(Action info) { Action logAction = s => @@ -41,18 +44,36 @@ static Action ObscurePassword(Action info) return logAction; } + public static void SetLoggers(Action info, Action warn, Action error) { + if (info == null) + { + throw new ArgumentNullException("info"); + } + + if (warn == null) + { + throw new ArgumentNullException("warn"); + } + + if (error == null) + { + throw new ArgumentNullException("error"); + } + WriteInfo = LogMessage(ObscurePassword(info), "INFO"); WriteWarning = LogMessage(ObscurePassword(warn), "WARN"); WriteError = LogMessage(ObscurePassword(error), "ERROR"); } + static Action LogMessage(Action logAction, string level) { return s => logAction(string.Format(CultureInfo.InvariantCulture, "{0}{1} [{2:MM/dd/yy H:mm:ss:ff}] {3}", indent, level, DateTime.Now, s)); } + public static void Reset() { WriteInfo = s => { throw new Exception("Logger not defined."); }; @@ -60,15 +81,18 @@ public static void Reset() WriteError = s => { throw new Exception("Logger not defined."); }; } + class ActionDisposable : IDisposable { readonly Action action; + public ActionDisposable(Action action) { this.action = action; } + public void Dispose() { action(); From 207cc67b759daefefd63215ad89fd596352a9206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Ulsberg?= Date: Mon, 16 Nov 2015 17:07:21 +0100 Subject: [PATCH 31/31] Deleted `VersionAndBranchFinder`, moved its caching logic into `ExecuteCore` and replaced all usage of the former with the latter. Also made `ExecuteCore` non-static. --- .../ExecuteCoreTests.cs} | 18 +- .../GitVersionCore.Tests.csproj | 1 + src/GitVersionCore/ExecuteCore.cs | 171 ++++++++++++++++-- src/GitVersionExe/SpecifiedArgumentRunner.cs | 30 ++- .../GitVersionTask.Tests.csproj | 1 - .../GitVersionTaskDirectoryTests.cs | 10 +- .../AssemblyInfoBuilder/UpdateAssemblyInfo.cs | 2 +- src/GitVersionTask/GetVersion.cs | 2 +- src/GitVersionTask/GitVersionTask.csproj | 1 - src/GitVersionTask/GitVersionTaskBase.cs | 8 +- src/GitVersionTask/VersionAndBranchFinder.cs | 144 --------------- .../WriteVersionInfoToBuildLog.cs | 2 +- 12 files changed, 204 insertions(+), 186 deletions(-) rename src/{GitVersionTask.Tests/VersionAndBranchFinderTests.cs => GitVersionCore.Tests/ExecuteCoreTests.cs} (76%) delete mode 100644 src/GitVersionTask/VersionAndBranchFinder.cs diff --git a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs b/src/GitVersionCore.Tests/ExecuteCoreTests.cs similarity index 76% rename from src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs rename to src/GitVersionCore.Tests/ExecuteCoreTests.cs index a3b1c0029b..f1018d1107 100644 --- a/src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs +++ b/src/GitVersionCore.Tests/ExecuteCoreTests.cs @@ -10,7 +10,7 @@ using Shouldly; [TestFixture] -public class VersionAndBranchFinderTests +public class ExecuteCoreTests { IFileSystem fileSystem; @@ -50,12 +50,12 @@ public void CacheFileExistsOnDisk() CommitDate: 2015-11-10 "; - var versionAndBranchFinder = new VersionAndBranchFinder(this.fileSystem); + var versionAndBranchFinder = new ExecuteCore(this.fileSystem); var info = RepositoryScope(versionAndBranchFinder, (fixture, vv) => { this.fileSystem.WriteAllText(vv.FileName, versionCacheFileContent); - vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false); + vv = versionAndBranchFinder.ExecuteGitVersion(null, null, null, null, false, fixture.RepositoryPath, null); vv.AssemblySemVer.ShouldBe("4.10.3.0"); }); @@ -67,11 +67,11 @@ public void CacheFileExistsOnDisk() public void CacheFileExistsInMemory() { var cache = new ConcurrentDictionary(); - var versionAndBranchFinder = new VersionAndBranchFinder(this.fileSystem, cache.GetOrAdd); + var versionAndBranchFinder = new ExecuteCore(this.fileSystem, cache.GetOrAdd); var info = RepositoryScope(versionAndBranchFinder, (fixture, vv) => { - vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false); + vv = versionAndBranchFinder.ExecuteGitVersion(null, null, null, null, false, fixture.RepositoryPath, null); vv.AssemblySemVer.ShouldBe("0.1.0.0"); }); @@ -88,18 +88,18 @@ public void CacheFileIsMissing() } - string RepositoryScope(VersionAndBranchFinder versionAndBranchFinder = null, Action fixtureAction = null) + string RepositoryScope(ExecuteCore executeCore = null, Action fixtureAction = null) { var infoBuilder = new StringBuilder(); Action infoLogger = s => { infoBuilder.AppendLine(s); }; - versionAndBranchFinder = versionAndBranchFinder ?? new VersionAndBranchFinder(this.fileSystem); + executeCore = executeCore ?? new ExecuteCore(this.fileSystem); - Logger.SetLoggers(infoLogger, null, null); + Logger.SetLoggers(infoLogger, s => { }, s => { }); using (var fixture = new EmptyRepositoryFixture(new Config())) { fixture.Repository.MakeACommit(); - var vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false); + var vv = executeCore.ExecuteGitVersion(null, null, null, null, false, fixture.RepositoryPath, null); vv.AssemblySemVer.ShouldBe("0.1.0.0"); vv.FileName.ShouldNotBeNullOrEmpty(); diff --git a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj index b12b5e175a..22607d952f 100644 --- a/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj +++ b/src/GitVersionCore.Tests/GitVersionCore.Tests.csproj @@ -178,6 +178,7 @@ + diff --git a/src/GitVersionCore/ExecuteCore.cs b/src/GitVersionCore/ExecuteCore.cs index 9e6a2adb28..6d1cafc604 100644 --- a/src/GitVersionCore/ExecuteCore.cs +++ b/src/GitVersionCore/ExecuteCore.cs @@ -1,13 +1,164 @@ namespace GitVersion { using System; + using System.Collections.Generic; + using System.IO; using System.Linq; + using System.Security.Cryptography; + using System.Text; using GitVersion.Helpers; - public static class ExecuteCore + using LibGit2Sharp; + + using YamlDotNet.Serialization; + + public class ExecuteCore { - public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId) + readonly IFileSystem fileSystem; + readonly Func, VersionVariables> getOrAddFromCache; + + + public ExecuteCore(IFileSystem fileSystem, Func, VersionVariables> getOrAddFromCache = null) + { + if (fileSystem == null) + { + throw new ArgumentNullException("fileSystem"); + } + + this.getOrAddFromCache = getOrAddFromCache; + this.fileSystem = fileSystem; + } + + + public VersionVariables ExecuteGitVersion(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId) + { + var gitDir = Repository.Discover(workingDirectory); + using (var repo = this.fileSystem.GetRepository(gitDir)) + { + // Maybe using timestamp in .git/refs directory is enough? + var ticks = this.fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); + var key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); + + if (this.getOrAddFromCache != null) + { + return this.getOrAddFromCache(key, k => + { + Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache."); + return LoadVersionVariablesFromDiskCache(key, gitDir, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, workingDirectory, commitId); + }); + } + + return LoadVersionVariablesFromDiskCache(key, gitDir, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, workingDirectory, commitId); + } + } + + + public bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication) + { + try + { + versionVariables = ExecuteGitVersion(null, null, authentication, null, noFetch, directory, null); + return true; + } + catch (Exception ex) + { + Logger.WriteWarning("Could not determine assembly version: " + ex); + versionVariables = null; + return false; + } + } + + + static string ResolveCurrentBranch(IBuildServer buildServer, string targetBranch) + { + if (buildServer == null) + { + return targetBranch; + } + + var currentBranch = buildServer.GetCurrentBranch() ?? targetBranch; + Logger.WriteInfo("Branch from build environment: " + currentBranch); + + return currentBranch; + } + + + VersionVariables LoadVersionVariablesFromDiskCache(string key, string gitDir, string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId) + { + using (Logger.IndentLog("Loading version variables from disk cache")) + { + string cacheKey; + using (var sha1 = SHA1.Create()) + { + // Make a shorter key by hashing, to avoid having to long cache filename. + cacheKey = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", ""); + } + + var cacheDir = Path.Combine(gitDir, "gitversion_cache"); + // If the cacheDir already exists, CreateDirectory just won't do anything (it won't fail). @asbjornu + this.fileSystem.CreateDirectory(cacheDir); + + var cacheFileName = string.Concat(Path.Combine(cacheDir, cacheKey), ".yml"); + VersionVariables vv = null; + if (this.fileSystem.Exists(cacheFileName)) + { + using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName)) + { + try + { + vv = VersionVariables.FromFile(cacheFileName, fileSystem); + } + catch (Exception ex) + { + Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); + Logger.WriteInfo(ex.ToString()); + try + { + this.fileSystem.Delete(cacheFileName); + } + catch (Exception deleteEx) + { + Logger.WriteWarning(string.Format("Unable to delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); + } + } + } + } + else + { + Logger.WriteInfo("Cache file " + cacheFileName + " not found."); + } + + if (vv == null) + { + vv = ExecuteInternal(targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, workingDirectory, commitId); + vv.FileName = cacheFileName; + + using (var stream = fileSystem.OpenWrite(cacheFileName)) + { + using (var sw = new StreamWriter(stream)) + { + Dictionary dictionary; + using (Logger.IndentLog("Creating dictionary")) + { + dictionary = vv.ToDictionary(x => x.Key, x => x.Value); + } + + using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName)) + { + var serializer = new Serializer(); + serializer.Serialize(sw, dictionary); + } + } + } + } + + return vv; + } + } + + + VersionVariables ExecuteInternal(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId) { // Normalise if we are running on build server var gitPreparer = new GitPreparer(targetUrl, dynamicRepositoryLocation, authentication, noFetch, workingDirectory); @@ -28,7 +179,7 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string var versionFinder = new GitVersionFinder(); var configuration = ConfigurationProvider.Provide(projectRoot, fileSystem); - using (var repo = fileSystem.GetRepository(dotGitDirectory)) + using (var repo = this.fileSystem.GetRepository(dotGitDirectory)) { var gitVersionContext = new GitVersionContext(repo, configuration, commitId : commitId); var semanticVersion = versionFinder.FindVersion(gitVersionContext); @@ -37,19 +188,5 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string return variables; } - - - static string ResolveCurrentBranch(IBuildServer buildServer, string targetBranch) - { - if (buildServer == null) - { - return targetBranch; - } - - var currentBranch = buildServer.GetCurrentBranch() ?? targetBranch; - Logger.WriteInfo("Branch from build environment: " + currentBranch); - - return currentBranch; - } } } \ No newline at end of file diff --git a/src/GitVersionExe/SpecifiedArgumentRunner.cs b/src/GitVersionExe/SpecifiedArgumentRunner.cs index 30324e4aae..a6e6dc8f98 100644 --- a/src/GitVersionExe/SpecifiedArgumentRunner.cs +++ b/src/GitVersionExe/SpecifiedArgumentRunner.cs @@ -1,13 +1,23 @@ namespace GitVersion { using System; + using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; + using GitVersion.Helpers; class SpecifiedArgumentRunner { const string MsBuild = @"c:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe"; + static readonly ConcurrentDictionary versionCache; + + + static SpecifiedArgumentRunner() + { + versionCache = new ConcurrentDictionary(); + } + public static void Run(Arguments arguments, IFileSystem fileSystem) { @@ -19,7 +29,8 @@ public static void Run(Arguments arguments, IFileSystem fileSystem) var targetBranch = arguments.TargetBranch; var commitId = arguments.CommitId; - var variables = ExecuteCore.ExecuteGitVersion(fileSystem, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId); + var executeCore = new ExecuteCore(fileSystem, versionCache.GetOrAdd); + var variables = executeCore.ExecuteGitVersion(targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId); if (arguments.Output == OutputType.BuildServer) { @@ -66,9 +77,13 @@ public static void Run(Arguments arguments, IFileSystem fileSystem) } } + static bool RunMsBuildIfNeeded(Arguments args, string workingDirectory, VersionVariables variables) { - if (string.IsNullOrEmpty(args.Proj)) return false; + if (string.IsNullOrEmpty(args.Proj)) + { + return false; + } Logger.WriteInfo(string.Format("Launching {0} \"{1}\" {2}", MsBuild, args.Proj, args.ProjArgs)); var results = ProcessHelper.Run( @@ -77,14 +92,20 @@ static bool RunMsBuildIfNeeded(Arguments args, string workingDirectory, VersionV GetEnvironmentalVariables(variables)); if (results != 0) + { throw new WarningException("MsBuild execution failed, non-zero return code"); + } return true; } + static bool RunExecCommandIfNeeded(Arguments args, string workingDirectory, VersionVariables variables) { - if (string.IsNullOrEmpty(args.Exec)) return false; + if (string.IsNullOrEmpty(args.Exec)) + { + return false; + } Logger.WriteInfo(string.Format("Launching {0} {1}", args.Exec, args.ExecArgs)); var results = ProcessHelper.Run( @@ -92,11 +113,14 @@ static bool RunExecCommandIfNeeded(Arguments args, string workingDirectory, Vers null, args.Exec, args.ExecArgs, workingDirectory, GetEnvironmentalVariables(variables)); if (results != 0) + { throw new WarningException(string.Format("Execution of {0} failed, non-zero return code", args.Exec)); + } return true; } + static KeyValuePair[] GetEnvironmentalVariables(VersionVariables variables) { return variables diff --git a/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj b/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj index b2fdd096b0..d4adf77842 100644 --- a/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj +++ b/src/GitVersionTask.Tests/GitVersionTask.Tests.csproj @@ -131,7 +131,6 @@ - diff --git a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs index 3cf5219e03..22496879e7 100644 --- a/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs +++ b/src/GitVersionTask.Tests/GitVersionTaskDirectoryTests.cs @@ -1,6 +1,8 @@ using System; using System.IO; +using GitVersion; + using LibGit2Sharp; using NUnit.Framework; @@ -8,8 +10,8 @@ [TestFixture] public class GitVersionTaskDirectoryTests { + ExecuteCore executeCore; string gitDirectory; - VersionAndBranchFinder versionAndBranchFinder; string workDirectory; @@ -19,7 +21,7 @@ public void CreateTemporaryRepository() this.workDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); this.gitDirectory = Repository.Init(this.workDirectory) .TrimEnd(Path.DirectorySeparatorChar); - this.versionAndBranchFinder = new VersionAndBranchFinder(new TestFileSystem()); + this.executeCore = new ExecuteCore(new TestFileSystem()); Assert.NotNull(this.gitDirectory); } @@ -36,7 +38,7 @@ public void Finds_GitDirectory() { try { - this.versionAndBranchFinder.GetVersion(this.workDirectory, null, true); + this.executeCore.ExecuteGitVersion(null, null, null, null, true, this.workDirectory, null); } catch (Exception ex) { @@ -55,7 +57,7 @@ public void Finds_GitDirectory_In_Parent() try { - this.versionAndBranchFinder.GetVersion(childDir, null, true); + this.executeCore.ExecuteGitVersion(null, null, null, null, true, childDir, null); } catch (Exception ex) { diff --git a/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs b/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs index 8d770cbcca..302fa5513d 100644 --- a/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs +++ b/src/GitVersionTask/AssemblyInfoBuilder/UpdateAssemblyInfo.cs @@ -75,7 +75,7 @@ void InnerExecute() InvalidFileChecker.CheckForInvalidFiles(CompileFiles, ProjectFile); VersionVariables versionVariables; - if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out versionVariables, NoFetch, new Authentication())) + if (!ExecuteCore.TryGetVersion(SolutionDirectory, out versionVariables, NoFetch, new Authentication())) { return; } diff --git a/src/GitVersionTask/GetVersion.cs b/src/GitVersionTask/GetVersion.cs index 22c03e902a..781c1156b5 100644 --- a/src/GitVersionTask/GetVersion.cs +++ b/src/GitVersionTask/GetVersion.cs @@ -96,7 +96,7 @@ public override bool Execute() { VersionVariables variables; - if (VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out variables, NoFetch, new Authentication())) + if (ExecuteCore.TryGetVersion(SolutionDirectory, out variables, NoFetch, new Authentication())) { var thisType = typeof(GetVersion); foreach (var variable in variables) diff --git a/src/GitVersionTask/GitVersionTask.csproj b/src/GitVersionTask/GitVersionTask.csproj index d3794b4dc1..d80f2fb583 100644 --- a/src/GitVersionTask/GitVersionTask.csproj +++ b/src/GitVersionTask/GitVersionTask.csproj @@ -67,7 +67,6 @@ - diff --git a/src/GitVersionTask/GitVersionTaskBase.cs b/src/GitVersionTask/GitVersionTaskBase.cs index c6338e5c19..2fedd58f9c 100644 --- a/src/GitVersionTask/GitVersionTaskBase.cs +++ b/src/GitVersionTask/GitVersionTaskBase.cs @@ -10,7 +10,7 @@ public abstract class GitVersionTaskBase : Task { static readonly ConcurrentDictionary versionVariablesCache; - readonly VersionAndBranchFinder versionAndBranchFinder; + readonly ExecuteCore executeCore; static GitVersionTaskBase() @@ -22,13 +22,13 @@ static GitVersionTaskBase() protected GitVersionTaskBase() { var fileSystem = new FileSystem(); - this.versionAndBranchFinder = new VersionAndBranchFinder(fileSystem, versionVariablesCache.GetOrAdd); + this.executeCore = new ExecuteCore(fileSystem, versionVariablesCache.GetOrAdd); } - protected VersionAndBranchFinder VersionAndBranchFinder + protected ExecuteCore ExecuteCore { - get { return this.versionAndBranchFinder; } + get { return this.executeCore; } } } } \ No newline at end of file diff --git a/src/GitVersionTask/VersionAndBranchFinder.cs b/src/GitVersionTask/VersionAndBranchFinder.cs deleted file mode 100644 index 1a1f52f020..0000000000 --- a/src/GitVersionTask/VersionAndBranchFinder.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; - -using GitVersion; -using GitVersion.Helpers; - -using LibGit2Sharp; - -using YamlDotNet.Serialization; - -public class VersionAndBranchFinder -{ - readonly IFileSystem fileSystem; - readonly Func, VersionVariables> getVersionVariablesFromMemoryCache; - - - public VersionAndBranchFinder(IFileSystem fileSystem, Func, VersionVariables> getVersionVariablesFromMemoryCache = null) - { - if (fileSystem == null) - { - throw new ArgumentNullException("fileSystem"); - } - - this.getVersionVariablesFromMemoryCache = getVersionVariablesFromMemoryCache; - this.fileSystem = fileSystem; - } - - - public bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication) - { - try - { - versionVariables = GetVersion(directory, authentication, noFetch); - return true; - } - catch (Exception ex) - { - Logger.WriteWarning("Could not determine assembly version: " + ex); - versionVariables = null; - return false; - } - } - - - public VersionVariables GetVersion(string directory, Authentication authentication, bool noFetch) - { - var gitDir = Repository.Discover(directory); - using (var repo = this.fileSystem.GetRepository(gitDir)) - { - // Maybe using timestamp in .git/refs directory is enough? - var ticks = this.fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs")); - var key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks); - - if (this.getVersionVariablesFromMemoryCache != null) - { - return this.getVersionVariablesFromMemoryCache(key, k => - { - Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache."); - return LoadVersionVariablesFromDiskCache(key, directory, authentication, noFetch, gitDir); - }); - } - - return LoadVersionVariablesFromDiskCache(key, directory, authentication, noFetch, gitDir); - } - } - - - VersionVariables LoadVersionVariablesFromDiskCache(string key, string directory, Authentication authentication, bool noFetch, string gitDir) - { - using (Logger.IndentLog("Loading version variables from disk cache")) - { - string cacheKey; - using (var sha1 = SHA1.Create()) - { - // Make a shorter key by hashing, to avoid having to long cache filename. - cacheKey = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", ""); - } - - var cacheDir = Path.Combine(gitDir, "gitversion_cache"); - // If the cacheDir already exists, CreateDirectory just won't do anything (it won't fail). @asbjornu - this.fileSystem.CreateDirectory(cacheDir); - - var cacheFileName = string.Concat(Path.Combine(cacheDir, cacheKey), ".yml"); - VersionVariables vv = null; - if (this.fileSystem.Exists(cacheFileName)) - { - using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName)) - { - try - { - vv = VersionVariables.FromFile(cacheFileName, fileSystem); - } - catch (Exception ex) - { - Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it."); - Logger.WriteInfo(ex.ToString()); - try - { - this.fileSystem.Delete(cacheFileName); - } - catch (Exception deleteEx) - { - Logger.WriteWarning(string.Format("Unable to delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName)); - } - } - } - } - else - { - Logger.WriteInfo("Cache file " + cacheFileName + " not found."); - } - - if (vv == null) - { - vv = ExecuteCore.ExecuteGitVersion(this.fileSystem, null, null, authentication, null, noFetch, directory, null); - vv.FileName = cacheFileName; - - using (var stream = fileSystem.OpenWrite(cacheFileName)) - { - using (var sw = new StreamWriter(stream)) - { - Dictionary dictionary; - using (Logger.IndentLog("Creating dictionary")) - { - dictionary = vv.ToDictionary(x => x.Key, x => x.Value); - } - - using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName)) - { - var serializer = new Serializer(); - serializer.Serialize(sw, dictionary); - } - } - } - } - - return vv; - } - } -} \ No newline at end of file diff --git a/src/GitVersionTask/WriteVersionInfoToBuildLog.cs b/src/GitVersionTask/WriteVersionInfoToBuildLog.cs index 42cf5047cf..97e2cadbed 100644 --- a/src/GitVersionTask/WriteVersionInfoToBuildLog.cs +++ b/src/GitVersionTask/WriteVersionInfoToBuildLog.cs @@ -52,7 +52,7 @@ public override bool Execute() void InnerExecute() { VersionVariables result; - if (!VersionAndBranchFinder.TryGetVersion(SolutionDirectory, out result, NoFetch, new Authentication())) + if (!ExecuteCore.TryGetVersion(SolutionDirectory, out result, NoFetch, new Authentication())) { return; }