Skip to content

Commit 9a945cc

Browse files
committed
add a test to ensure cache key is same even if normalized again; modify cache factory to traverse refs directory instead of just looking at the timestamp (which changes if renormalized)
1 parent 35c696a commit 9a945cc

File tree

2 files changed

+122
-3
lines changed

2 files changed

+122
-3
lines changed

src/GitVersionCore.Tests/ExecuteCoreTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ public void SetUp()
1818
fileSystem = new FileSystem();
1919
}
2020

21+
[Test]
22+
public void CacheKeySameAfterReNormalizing()
23+
{
24+
var versionAndBranchFinder = new ExecuteCore(fileSystem);
25+
26+
RepositoryScope(versionAndBranchFinder, (fixture, vv) =>
27+
{
28+
var targetUrl = "https://github.com/GitTools/GitVersion.git";
29+
var targetBranch = "refs/head/master";
30+
var gitPreparer = new GitPreparer(targetUrl, null, new Authentication(), false, fixture.RepositoryPath);
31+
var cacheKey1 = GitVersionCacheKeyFactory.Create(fileSystem, gitPreparer, null);
32+
gitPreparer.Initialise(true, targetBranch);
33+
var cacheKey2 = GitVersionCacheKeyFactory.Create(fileSystem, gitPreparer, null);
34+
gitPreparer.Initialise(true, targetBranch);
35+
var cacheKey3 = GitVersionCacheKeyFactory.Create(fileSystem, gitPreparer, null);
36+
37+
cacheKey3.Value.ShouldBe(cacheKey2.Value);
38+
});
39+
}
40+
2141
[Test]
2242
public void CacheFileExistsOnDisk()
2343
{

src/GitVersionCore/GitVersionCacheKeyFactory.cs

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using GitVersion.Helpers;
44
using System;
5+
using System.Collections.Generic;
56
using System.IO;
67
using System.Security.Cryptography;
78
using System.Text;
@@ -23,10 +24,108 @@ private static string GetGitSystemHash(GitPreparer gitPreparer, IFileSystem file
2324
{
2425
var dotGitDirectory = gitPreparer.GetDotGitDirectory();
2526

26-
// Maybe using timestamp in .git/refs directory is enough?
27-
var lastGitRefsChangedTicks = fileSystem.GetLastDirectoryWrite(Path.Combine(dotGitDirectory, "refs"));
27+
// traverse the directory and get a list of files, use that for GetHash
28+
var traverse = TraverseTree(Path.Combine(dotGitDirectory, "refs"));
2829

29-
return GetHash(dotGitDirectory, lastGitRefsChangedTicks.ToString());
30+
return GetHash(traverse.ToArray());
31+
}
32+
33+
// lifted from https://msdn.microsoft.com/en-us/library/bb513869.aspx
34+
public static List<string> TraverseTree(string root)
35+
{
36+
var result = new List<string>();
37+
result.Add(root);
38+
// Data structure to hold names of subfolders to be
39+
// examined for files.
40+
Stack<string> dirs = new Stack<string>(20);
41+
42+
if (!System.IO.Directory.Exists(root))
43+
{
44+
throw new ArgumentException();
45+
}
46+
47+
dirs.Push(root);
48+
49+
while (dirs.Count > 0)
50+
{
51+
string currentDir = dirs.Pop();
52+
53+
var di = new DirectoryInfo(currentDir);
54+
result.Add(di.Name);
55+
56+
string[] subDirs;
57+
try
58+
{
59+
subDirs = System.IO.Directory.GetDirectories(currentDir);
60+
}
61+
// An UnauthorizedAccessException exception will be thrown if we do not have
62+
// discovery permission on a folder or file. It may or may not be acceptable
63+
// to ignore the exception and continue enumerating the remaining files and
64+
// folders. It is also possible (but unlikely) that a DirectoryNotFound exception
65+
// will be raised. This will happen if currentDir has been deleted by
66+
// another application or thread after our call to Directory.Exists. The
67+
// choice of which exceptions to catch depends entirely on the specific task
68+
// you are intending to perform and also on how much you know with certainty
69+
// about the systems on which this code will run.
70+
catch (UnauthorizedAccessException e)
71+
{
72+
Logger.WriteError(e.Message);
73+
continue;
74+
}
75+
catch (System.IO.DirectoryNotFoundException e)
76+
{
77+
Logger.WriteError(e.Message);
78+
continue;
79+
}
80+
81+
string[] files = null;
82+
try
83+
{
84+
files = System.IO.Directory.GetFiles(currentDir);
85+
}
86+
87+
catch (UnauthorizedAccessException e)
88+
{
89+
Logger.WriteError(e.Message);
90+
continue;
91+
}
92+
93+
catch (System.IO.DirectoryNotFoundException e)
94+
{
95+
Logger.WriteError(e.Message);
96+
continue;
97+
}
98+
// Perform the required action on each file here.
99+
// Modify this block to perform your required task.
100+
foreach (string file in files)
101+
{
102+
try
103+
{
104+
// Perform whatever action is required in your scenario.
105+
System.IO.FileInfo fi = new System.IO.FileInfo(file);
106+
result.Add(fi.Name);
107+
Logger.WriteInfo(string.Format("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime));
108+
}
109+
catch (System.IO.FileNotFoundException e)
110+
{
111+
// If file was deleted by a separate application
112+
// or thread since the call to TraverseTree()
113+
// then just continue.
114+
Logger.WriteError(e.Message);
115+
continue;
116+
}
117+
}
118+
119+
// Push the subdirectories onto the stack for traversal.
120+
// This could also be done before handing the files.
121+
// push in reverse order
122+
for (int i = subDirs.Length - 1; i >= 0; i--)
123+
{
124+
dirs.Push(subDirs[i]);
125+
}
126+
}
127+
128+
return result;
30129
}
31130

32131
private static string GetRepositorySnapshotHash(GitPreparer gitPreparer)

0 commit comments

Comments
 (0)