Skip to content

Commit c70c576

Browse files
asbjornuJakeGinnivan
authored andcommitted
Deleted VersionAndBranchFinder, moved its caching logic into ExecuteCore and replaced all usage of the former with the latter. Also made ExecuteCore non-static.
1 parent ca3d183 commit c70c576

File tree

12 files changed

+204
-186
lines changed

12 files changed

+204
-186
lines changed

src/GitVersionTask.Tests/VersionAndBranchFinderTests.cs renamed to src/GitVersionCore.Tests/ExecuteCoreTests.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
using Shouldly;
1111

1212
[TestFixture]
13-
public class VersionAndBranchFinderTests
13+
public class ExecuteCoreTests
1414
{
1515
IFileSystem fileSystem;
1616

@@ -50,12 +50,12 @@ public void CacheFileExistsOnDisk()
5050
CommitDate: 2015-11-10
5151
";
5252

53-
var versionAndBranchFinder = new VersionAndBranchFinder(this.fileSystem);
53+
var versionAndBranchFinder = new ExecuteCore(this.fileSystem);
5454

5555
var info = RepositoryScope(versionAndBranchFinder, (fixture, vv) =>
5656
{
5757
this.fileSystem.WriteAllText(vv.FileName, versionCacheFileContent);
58-
vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false);
58+
vv = versionAndBranchFinder.ExecuteGitVersion(null, null, null, null, false, fixture.RepositoryPath, null);
5959
vv.AssemblySemVer.ShouldBe("4.10.3.0");
6060
});
6161

@@ -67,11 +67,11 @@ public void CacheFileExistsOnDisk()
6767
public void CacheFileExistsInMemory()
6868
{
6969
var cache = new ConcurrentDictionary<string, VersionVariables>();
70-
var versionAndBranchFinder = new VersionAndBranchFinder(this.fileSystem, cache.GetOrAdd);
70+
var versionAndBranchFinder = new ExecuteCore(this.fileSystem, cache.GetOrAdd);
7171

7272
var info = RepositoryScope(versionAndBranchFinder, (fixture, vv) =>
7373
{
74-
vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false);
74+
vv = versionAndBranchFinder.ExecuteGitVersion(null, null, null, null, false, fixture.RepositoryPath, null);
7575
vv.AssemblySemVer.ShouldBe("0.1.0.0");
7676
});
7777

@@ -88,18 +88,18 @@ public void CacheFileIsMissing()
8888
}
8989

9090

91-
string RepositoryScope(VersionAndBranchFinder versionAndBranchFinder = null, Action<EmptyRepositoryFixture, VersionVariables> fixtureAction = null)
91+
string RepositoryScope(ExecuteCore executeCore = null, Action<EmptyRepositoryFixture, VersionVariables> fixtureAction = null)
9292
{
9393
var infoBuilder = new StringBuilder();
9494
Action<string> infoLogger = s => { infoBuilder.AppendLine(s); };
95-
versionAndBranchFinder = versionAndBranchFinder ?? new VersionAndBranchFinder(this.fileSystem);
95+
executeCore = executeCore ?? new ExecuteCore(this.fileSystem);
9696

97-
Logger.SetLoggers(infoLogger, null, null);
97+
Logger.SetLoggers(infoLogger, s => { }, s => { });
9898

9999
using (var fixture = new EmptyRepositoryFixture(new Config()))
100100
{
101101
fixture.Repository.MakeACommit();
102-
var vv = versionAndBranchFinder.GetVersion(fixture.RepositoryPath, null, false);
102+
var vv = executeCore.ExecuteGitVersion(null, null, null, null, false, fixture.RepositoryPath, null);
103103

104104
vv.AssemblySemVer.ShouldBe("0.1.0.0");
105105
vv.FileName.ShouldNotBeNullOrEmpty();

src/GitVersionCore.Tests/GitVersionCore.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
<Compile Include="TestFileSystem.cs" />
180180
<Compile Include="TestStream.cs" />
181181
<Compile Include="VariableProviderTests.cs" />
182+
<Compile Include="ExecuteCoreTests.cs" />
182183
<Compile Include="VersionCalculation\BaseVersionCalculatorTests.cs" />
183184
<Compile Include="VersionCalculation\NextVersionCalculatorTests.cs" />
184185
<Compile Include="VersionCalculation\Strategies\ConfigNextVersionBaseVersionStrategyTests.cs" />

src/GitVersionCore/ExecuteCore.cs

Lines changed: 154 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,164 @@
11
namespace GitVersion
22
{
33
using System;
4+
using System.Collections.Generic;
5+
using System.IO;
46
using System.Linq;
7+
using System.Security.Cryptography;
8+
using System.Text;
59

610
using GitVersion.Helpers;
711

8-
public static class ExecuteCore
12+
using LibGit2Sharp;
13+
14+
using YamlDotNet.Serialization;
15+
16+
public class ExecuteCore
917
{
10-
public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId)
18+
readonly IFileSystem fileSystem;
19+
readonly Func<string, Func<string, VersionVariables>, VersionVariables> getOrAddFromCache;
20+
21+
22+
public ExecuteCore(IFileSystem fileSystem, Func<string, Func<string, VersionVariables>, VersionVariables> getOrAddFromCache = null)
23+
{
24+
if (fileSystem == null)
25+
{
26+
throw new ArgumentNullException("fileSystem");
27+
}
28+
29+
this.getOrAddFromCache = getOrAddFromCache;
30+
this.fileSystem = fileSystem;
31+
}
32+
33+
34+
public VersionVariables ExecuteGitVersion(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId)
35+
{
36+
var gitDir = Repository.Discover(workingDirectory);
37+
using (var repo = this.fileSystem.GetRepository(gitDir))
38+
{
39+
// Maybe using timestamp in .git/refs directory is enough?
40+
var ticks = this.fileSystem.GetLastDirectoryWrite(Path.Combine(gitDir, "refs"));
41+
var key = string.Format("{0}:{1}:{2}:{3}", gitDir, repo.Head.CanonicalName, repo.Head.Tip.Sha, ticks);
42+
43+
if (this.getOrAddFromCache != null)
44+
{
45+
return this.getOrAddFromCache(key, k =>
46+
{
47+
Logger.WriteInfo("Version not in memory cache. Attempting to load version from disk cache.");
48+
return LoadVersionVariablesFromDiskCache(key, gitDir, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, workingDirectory, commitId);
49+
});
50+
}
51+
52+
return LoadVersionVariablesFromDiskCache(key, gitDir, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, workingDirectory, commitId);
53+
}
54+
}
55+
56+
57+
public bool TryGetVersion(string directory, out VersionVariables versionVariables, bool noFetch, Authentication authentication)
58+
{
59+
try
60+
{
61+
versionVariables = ExecuteGitVersion(null, null, authentication, null, noFetch, directory, null);
62+
return true;
63+
}
64+
catch (Exception ex)
65+
{
66+
Logger.WriteWarning("Could not determine assembly version: " + ex);
67+
versionVariables = null;
68+
return false;
69+
}
70+
}
71+
72+
73+
static string ResolveCurrentBranch(IBuildServer buildServer, string targetBranch)
74+
{
75+
if (buildServer == null)
76+
{
77+
return targetBranch;
78+
}
79+
80+
var currentBranch = buildServer.GetCurrentBranch() ?? targetBranch;
81+
Logger.WriteInfo("Branch from build environment: " + currentBranch);
82+
83+
return currentBranch;
84+
}
85+
86+
87+
VersionVariables LoadVersionVariablesFromDiskCache(string key, string gitDir, string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId)
88+
{
89+
using (Logger.IndentLog("Loading version variables from disk cache"))
90+
{
91+
string cacheKey;
92+
using (var sha1 = SHA1.Create())
93+
{
94+
// Make a shorter key by hashing, to avoid having to long cache filename.
95+
cacheKey = BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(key))).Replace("-", "");
96+
}
97+
98+
var cacheDir = Path.Combine(gitDir, "gitversion_cache");
99+
// If the cacheDir already exists, CreateDirectory just won't do anything (it won't fail). @asbjornu
100+
this.fileSystem.CreateDirectory(cacheDir);
101+
102+
var cacheFileName = string.Concat(Path.Combine(cacheDir, cacheKey), ".yml");
103+
VersionVariables vv = null;
104+
if (this.fileSystem.Exists(cacheFileName))
105+
{
106+
using (Logger.IndentLog("Deserializing version variables from cache file " + cacheFileName))
107+
{
108+
try
109+
{
110+
vv = VersionVariables.FromFile(cacheFileName, fileSystem);
111+
}
112+
catch (Exception ex)
113+
{
114+
Logger.WriteWarning("Unable to read cache file " + cacheFileName + ", deleting it.");
115+
Logger.WriteInfo(ex.ToString());
116+
try
117+
{
118+
this.fileSystem.Delete(cacheFileName);
119+
}
120+
catch (Exception deleteEx)
121+
{
122+
Logger.WriteWarning(string.Format("Unable to delete corrupted version cache file {0}. Got {1} exception.", cacheFileName, deleteEx.GetType().FullName));
123+
}
124+
}
125+
}
126+
}
127+
else
128+
{
129+
Logger.WriteInfo("Cache file " + cacheFileName + " not found.");
130+
}
131+
132+
if (vv == null)
133+
{
134+
vv = ExecuteInternal(targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, workingDirectory, commitId);
135+
vv.FileName = cacheFileName;
136+
137+
using (var stream = fileSystem.OpenWrite(cacheFileName))
138+
{
139+
using (var sw = new StreamWriter(stream))
140+
{
141+
Dictionary<string, string> dictionary;
142+
using (Logger.IndentLog("Creating dictionary"))
143+
{
144+
dictionary = vv.ToDictionary(x => x.Key, x => x.Value);
145+
}
146+
147+
using (Logger.IndentLog("Storing version variables to cache file " + cacheFileName))
148+
{
149+
var serializer = new Serializer();
150+
serializer.Serialize(sw, dictionary);
151+
}
152+
}
153+
}
154+
}
155+
156+
return vv;
157+
}
158+
}
159+
160+
161+
VersionVariables ExecuteInternal(string targetUrl, string dynamicRepositoryLocation, Authentication authentication, string targetBranch, bool noFetch, string workingDirectory, string commitId)
11162
{
12163
// Normalise if we are running on build server
13164
var gitPreparer = new GitPreparer(targetUrl, dynamicRepositoryLocation, authentication, noFetch, workingDirectory);
@@ -28,7 +179,7 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string
28179
var versionFinder = new GitVersionFinder();
29180
var configuration = ConfigurationProvider.Provide(projectRoot, fileSystem);
30181

31-
using (var repo = fileSystem.GetRepository(dotGitDirectory))
182+
using (var repo = this.fileSystem.GetRepository(dotGitDirectory))
32183
{
33184
var gitVersionContext = new GitVersionContext(repo, configuration, commitId : commitId);
34185
var semanticVersion = versionFinder.FindVersion(gitVersionContext);
@@ -37,19 +188,5 @@ public static VersionVariables ExecuteGitVersion(IFileSystem fileSystem, string
37188

38189
return variables;
39190
}
40-
41-
42-
static string ResolveCurrentBranch(IBuildServer buildServer, string targetBranch)
43-
{
44-
if (buildServer == null)
45-
{
46-
return targetBranch;
47-
}
48-
49-
var currentBranch = buildServer.GetCurrentBranch() ?? targetBranch;
50-
Logger.WriteInfo("Branch from build environment: " + currentBranch);
51-
52-
return currentBranch;
53-
}
54191
}
55192
}

src/GitVersionExe/SpecifiedArgumentRunner.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
namespace GitVersion
22
{
33
using System;
4+
using System.Collections.Concurrent;
45
using System.Collections.Generic;
56
using System.Linq;
7+
68
using GitVersion.Helpers;
79

810
class SpecifiedArgumentRunner
911
{
1012
const string MsBuild = @"c:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe";
13+
static readonly ConcurrentDictionary<string, VersionVariables> versionCache;
14+
15+
16+
static SpecifiedArgumentRunner()
17+
{
18+
versionCache = new ConcurrentDictionary<string, VersionVariables>();
19+
}
20+
1121

1222
public static void Run(Arguments arguments, IFileSystem fileSystem)
1323
{
@@ -19,7 +29,8 @@ public static void Run(Arguments arguments, IFileSystem fileSystem)
1929
var targetBranch = arguments.TargetBranch;
2030
var commitId = arguments.CommitId;
2131

22-
var variables = ExecuteCore.ExecuteGitVersion(fileSystem, targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId);
32+
var executeCore = new ExecuteCore(fileSystem, versionCache.GetOrAdd);
33+
var variables = executeCore.ExecuteGitVersion(targetUrl, dynamicRepositoryLocation, authentication, targetBranch, noFetch, targetPath, commitId);
2334

2435
if (arguments.Output == OutputType.BuildServer)
2536
{
@@ -66,9 +77,13 @@ public static void Run(Arguments arguments, IFileSystem fileSystem)
6677
}
6778
}
6879

80+
6981
static bool RunMsBuildIfNeeded(Arguments args, string workingDirectory, VersionVariables variables)
7082
{
71-
if (string.IsNullOrEmpty(args.Proj)) return false;
83+
if (string.IsNullOrEmpty(args.Proj))
84+
{
85+
return false;
86+
}
7287

7388
Logger.WriteInfo(string.Format("Launching {0} \"{1}\" {2}", MsBuild, args.Proj, args.ProjArgs));
7489
var results = ProcessHelper.Run(
@@ -77,26 +92,35 @@ static bool RunMsBuildIfNeeded(Arguments args, string workingDirectory, VersionV
7792
GetEnvironmentalVariables(variables));
7893

7994
if (results != 0)
95+
{
8096
throw new WarningException("MsBuild execution failed, non-zero return code");
97+
}
8198

8299
return true;
83100
}
84101

102+
85103
static bool RunExecCommandIfNeeded(Arguments args, string workingDirectory, VersionVariables variables)
86104
{
87-
if (string.IsNullOrEmpty(args.Exec)) return false;
105+
if (string.IsNullOrEmpty(args.Exec))
106+
{
107+
return false;
108+
}
88109

89110
Logger.WriteInfo(string.Format("Launching {0} {1}", args.Exec, args.ExecArgs));
90111
var results = ProcessHelper.Run(
91112
Logger.WriteInfo, Logger.WriteError,
92113
null, args.Exec, args.ExecArgs, workingDirectory,
93114
GetEnvironmentalVariables(variables));
94115
if (results != 0)
116+
{
95117
throw new WarningException(string.Format("Execution of {0} failed, non-zero return code", args.Exec));
118+
}
96119

97120
return true;
98121
}
99122

123+
100124
static KeyValuePair<string, string>[] GetEnvironmentalVariables(VersionVariables variables)
101125
{
102126
return variables

src/GitVersionTask.Tests/GitVersionTask.Tests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@
131131
<Compile Include="Helpers\SelfCleaningDirectory.cs" />
132132
<Compile Include="Mocks\MockTaskItem.cs" />
133133
<Compile Include="ModuleInitializer.cs" />
134-
<Compile Include="VersionAndBranchFinderTests.cs" />
135134
</ItemGroup>
136135
<ItemGroup>
137136
<None Include="app.config" />

0 commit comments

Comments
 (0)