Skip to content

Commit 2b15375

Browse files
authored
Merge pull request #2092 from Inok/fix/parallel-tests-failures
Fix parallel tests execution, fix potential collisions, cache only regexes
2 parents 5d2b42f + bc2fc37 commit 2b15375

File tree

1 file changed

+32
-41
lines changed

1 file changed

+32
-41
lines changed

src/GitVersionCore/VersionCalculation/IncrementStrategyFinder.cs

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Concurrent;
12
using System.Collections.Generic;
23
using System.Linq;
34
using System.Text.RegularExpressions;
@@ -23,6 +24,11 @@ public static class IncrementStrategyFinder
2324
public const string DefaultPatchPattern = @"\+semver:\s?(fix|patch)";
2425
public const string DefaultNoBumpPattern = @"\+semver:\s?(none|skip)";
2526

27+
private static readonly Regex DefaultMajorPatternRegex = new Regex(DefaultMajorPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
28+
private static readonly Regex DefaultMinorPatternRegex = new Regex(DefaultMinorPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
29+
private static readonly Regex DefaultPatchPatternRegex = new Regex(DefaultPatchPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
30+
private static readonly Regex DefaultNoBumpPatternRegex = new Regex(DefaultNoBumpPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
31+
2632
public static VersionField? DetermineIncrementedField(GitVersionContext context, BaseVersion baseVersion)
2733
{
2834
var commitMessageIncrement = FindCommitMessageIncrement(context, baseVersion);
@@ -69,13 +75,10 @@ public static class IncrementStrategyFinder
6975

7076
public static VersionField? GetIncrementForCommits(GitVersionContext context, IEnumerable<Commit> commits)
7177
{
72-
// More efficient use of Regexes. The static version of Regex.IsMatch caches the compiled regexes.
73-
// see: https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices#static-regular-expressions
74-
75-
var majorRegex = context.Configuration.MajorVersionBumpMessage ?? DefaultMajorPattern;
76-
var minorRegex = context.Configuration.MinorVersionBumpMessage ?? DefaultMinorPattern;
77-
var patchRegex = context.Configuration.PatchVersionBumpMessage ?? DefaultPatchPattern;
78-
var none = context.Configuration.NoBumpMessage ?? DefaultNoBumpPattern;
78+
var majorRegex = TryGetRegexOrDefault(context.Configuration.MajorVersionBumpMessage, DefaultMajorPatternRegex);
79+
var minorRegex = TryGetRegexOrDefault(context.Configuration.MinorVersionBumpMessage, DefaultMinorPatternRegex);
80+
var patchRegex = TryGetRegexOrDefault(context.Configuration.PatchVersionBumpMessage, DefaultPatchPatternRegex);
81+
var none = TryGetRegexOrDefault(context.Configuration.NoBumpMessage, DefaultNoBumpPatternRegex);
7982

8083
var increments = commits
8184
.Select(c => GetIncrementFromMessage(c.Message, majorRegex, minorRegex, patchRegex, none))
@@ -91,23 +94,36 @@ public static class IncrementStrategyFinder
9194
return null;
9295
}
9396

97+
private static Regex TryGetRegexOrDefault(string messageRegex, Regex defaultRegex)
98+
{
99+
if (messageRegex == null)
100+
{
101+
return defaultRegex;
102+
}
103+
104+
return CompiledRegexCache.GetOrAdd(messageRegex, pattern => new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase));
105+
}
106+
94107
private static IEnumerable<Commit> GetIntermediateCommits(IRepository repo, Commit baseCommit, Commit headCommit)
95108
{
96109
if (baseCommit == null) yield break;
97110

98-
if (intermediateCommitCache == null || intermediateCommitCache.LastOrDefault() != headCommit)
111+
var commitCache = intermediateCommitCache;
112+
113+
if (commitCache == null || commitCache.LastOrDefault() != headCommit)
99114
{
100115
var filter = new CommitFilter
101116
{
102117
IncludeReachableFrom = headCommit,
103118
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
104119
};
105120

106-
intermediateCommitCache = repo.Commits.QueryBy(filter).ToList();
121+
commitCache = repo.Commits.QueryBy(filter).ToList();
122+
intermediateCommitCache = commitCache;
107123
}
108124

109125
var found = false;
110-
foreach (var commit in intermediateCommitCache)
126+
foreach (var commit in commitCache)
111127
{
112128
if (found)
113129
yield return commit;
@@ -117,41 +133,16 @@ private static IEnumerable<Commit> GetIntermediateCommits(IRepository repo, Comm
117133
}
118134
}
119135

120-
private static VersionField? GetIncrementFromMessage(string message, string majorRegex, string minorRegex, string patchRegex, string none)
136+
private static VersionField? GetIncrementFromMessage(string message, Regex majorRegex, Regex minorRegex, Regex patchRegex, Regex none)
121137
{
122-
var key = message.GetHashCode();
123-
124-
if (!VersionFieldCache.TryGetValue(key, out var version))
125-
{
126-
version = FindIncrementFromMessage(message, majorRegex, minorRegex, patchRegex, none);
127-
VersionFieldCache[key] = version;
128-
}
129-
return version;
130-
}
131-
132-
private static VersionField? FindIncrementFromMessage(string message, string majorRegex, string minorRegex, string patchRegex, string noneRegex)
133-
{
134-
if (IsMatch(message, majorRegex)) return VersionField.Major;
135-
if (IsMatch(message, minorRegex)) return VersionField.Minor;
136-
if (IsMatch(message, patchRegex)) return VersionField.Patch;
137-
if (IsMatch(message, noneRegex)) return VersionField.None;
138+
if (majorRegex.IsMatch(message)) return VersionField.Major;
139+
if (minorRegex.IsMatch(message)) return VersionField.Minor;
140+
if (patchRegex.IsMatch(message)) return VersionField.Patch;
141+
if (none.IsMatch(message)) return VersionField.None;
138142
return null;
139143
}
140144

141-
private static bool IsMatch(string message, string regex)
142-
{
143-
var key = message.GetHashCode() ^ regex.GetHashCode();
144-
145-
if (!MatchCache.TryGetValue(key, out var match))
146-
{
147-
match = Regex.IsMatch(message, regex, RegexOptions.IgnoreCase);
148-
MatchCache[key] = match;
149-
}
150-
return match;
151-
}
152-
153-
private static readonly IDictionary<int, bool> MatchCache = new Dictionary<int, bool>();
154-
private static readonly IDictionary<int, VersionField?> VersionFieldCache = new Dictionary<int, VersionField?>();
145+
private static readonly ConcurrentDictionary<string, Regex> CompiledRegexCache = new ConcurrentDictionary<string, Regex>();
155146

156147
public static VersionField FindDefaultIncrementForBranch(GitVersionContext context, string branch = null)
157148
{

0 commit comments

Comments
 (0)