diff --git a/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs new file mode 100644 index 0000000000..8506843fb7 --- /dev/null +++ b/src/GitVersion.Core.Tests/IntegrationTests/PerformanceScenarios.cs @@ -0,0 +1,29 @@ +using GitVersion.Configuration; +using GitVersion.Core.Tests.Helpers; + +namespace GitVersion.Core.Tests.IntegrationTests; + +public class PerformanceScenarios : TestBase +{ + [Test] + public void RepositoryWithALotOfTags() + { + var configuration = GitFlowConfigurationBuilder.New.Build(); + + using var fixture = new EmptyRepositoryFixture(); + + const int maxCommits = 500; + for (int i = 0; i < maxCommits; i++) + { + fixture.MakeATaggedCommit($"1.0.{i}"); + } + + fixture.BranchTo("feature"); + fixture.MakeACommit(); + + var sw = Stopwatch.StartNew(); + + fixture.AssertFullSemver($"1.0.{maxCommits}-feature.1+1", configuration); + sw.ElapsedMilliseconds.ShouldBeLessThan(5000); + } +} diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index 7519614147..dd8e02fc2b 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -16,6 +16,7 @@ internal class IncrementStrategyFinder : IIncrementStrategyFinder private readonly Dictionary commitIncrementCache = new(); private readonly Dictionary> headCommitsMapCache = new(); private readonly Dictionary headCommitsCache = new(); + private readonly Lazy> tagsShaCache; private static readonly Regex DefaultMajorPatternRegex = new(DefaultMajorPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex DefaultMinorPatternRegex = new(DefaultMinorPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -24,7 +25,11 @@ internal class IncrementStrategyFinder : IIncrementStrategyFinder private readonly IGitRepository repository; - public IncrementStrategyFinder(IGitRepository repository) => this.repository = repository.NotNull(); + public IncrementStrategyFinder(IGitRepository repository) + { + this.repository = repository.NotNull(); + this.tagsShaCache = new Lazy>(ReadRepositoryTagsSha); + } public VersionField DetermineIncrementedField(ICommit? currentCommit, BaseVersion baseVersion, EffectiveConfiguration configuration) { @@ -79,12 +84,10 @@ public VersionField DetermineIncrementedField(ICommit? currentCommit, BaseVersio } var commits = GetIntermediateCommits(baseCommit, currentCommit); - // consider commit messages since latest tag only (see #3071) - var tags = new HashSet(repository.Tags.Select(t => t.TargetSha)); commits = commits .Reverse() - .TakeWhile(x => !tags.Contains(x.Sha)) + .TakeWhile(x => !this.tagsShaCache.Value.Contains(x.Sha)) .Reverse(); if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly) @@ -101,6 +104,8 @@ public VersionField DetermineIncrementedField(ICommit? currentCommit, BaseVersio ); } + private IReadOnlySet ReadRepositoryTagsSha() => repository.Tags.Select(t => t.TargetSha).ToHashSet(); + private static Regex TryGetRegexOrDefault(string? messageRegex, Regex defaultRegex) => messageRegex == null ? defaultRegex