From 9dc2a92ca4c6b644b6d19dde8baadc5a4e35a8a0 Mon Sep 17 00:00:00 2001 From: HHobeck Date: Sun, 14 Apr 2024 09:46:15 +0200 Subject: [PATCH 1/4] Create TaggedSemanticVersionService class --- .../Extensions/GitToolsTestingExtensions.cs | 1 - .../IntegrationTests/DocumentationSamples.cs | 6 +- .../FallbackVersionStrategyScenarios.cs | 29 -- .../Core/EffectiveConfigurationExtensions.cs | 30 +++ .../Core/ITaggedSemanticVersionRepository.cs | 19 -- .../Core/ITaggedSemanticVersionService.cs | 42 +++ .../Core/TaggedSemanticVersionRepository.cs | 180 +------------ .../Core/TaggedSemanticVersionService.cs | 247 ++++++++++++++++++ .../Core/TaggedSemanticVersions.cs | 17 ++ src/GitVersion.Core/GitVersionCoreModule.cs | 1 + .../NextVersionCalculator.cs | 23 +- .../FallbacktVersionStrategy.cs | 12 +- .../TaggedCommitVersionStrategy.cs | 25 +- .../TrunkBasedVersionStrategy.cs | 21 +- 14 files changed, 405 insertions(+), 248 deletions(-) create mode 100644 src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs create mode 100644 src/GitVersion.Core/Core/ITaggedSemanticVersionService.cs create mode 100644 src/GitVersion.Core/Core/TaggedSemanticVersionService.cs create mode 100644 src/GitVersion.Core/Core/TaggedSemanticVersions.cs diff --git a/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs b/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs index 947d4e6fc4..5697f70f09 100644 --- a/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs +++ b/src/GitVersion.Core.Tests/Extensions/GitToolsTestingExtensions.cs @@ -61,7 +61,6 @@ public static GitVersionVariables GetVersion(this RepositoryFixtureBase fixture, { repository ??= fixture.Repository; configuration ??= GitFlowConfigurationBuilder.New.Build(); - Console.WriteLine("---------"); var overrideConfiguration = new Dictionary(); var options = Options.Create(new GitVersionOptions diff --git a/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs b/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs index 9f1a2a895b..e3480f25cf 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs @@ -202,7 +202,7 @@ public void GitFlowMajorRelease() fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/2.0.0"); fixture.Checkout(MainBranch); - fixture.AssertFullSemver("2.0.0-0"); + fixture.AssertFullSemver("2.0.0-4"); fixture.ApplyTag("2.0.0"); fixture.AssertFullSemver("2.0.0"); @@ -291,7 +291,7 @@ public void GitFlowSupportMinorRelease() fixture.MergeNoFF("release/1.4.0"); fixture.SequenceDiagram.Destroy("release/1.4.0"); fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/1.4.0"); - fixture.AssertFullSemver("1.4.0-0"); + fixture.AssertFullSemver("1.4.0-4"); fixture.ApplyTag("1.4.0"); fixture.AssertFullSemver("1.4.0"); Console.WriteLine(fixture.SequenceDiagram.GetDiagram()); @@ -392,7 +392,7 @@ public void GitHubFlowMajorRelease() fixture.SequenceDiagram.Destroy("release/2.0.0"); fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/2.0.0"); - fixture.AssertFullSemver("2.0.0-0"); + fixture.AssertFullSemver("2.0.0-4"); fixture.ApplyTag("2.0.0"); fixture.AssertFullSemver("2.0.0"); fixture.MakeACommit(); diff --git a/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs index b574e1c808..0ef417e9fa 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs @@ -93,33 +93,4 @@ public void TakeTheLatestCommitAsBaseVersion(bool mode) // ✅ succeeds as expected fixture.AssertFullSemver("1.0.0-1+1", configuration); } - - [Test] - public void TakeTheCommitBranchedFromAsBaseVersion() - { - var configuration = ConfigurationBuilder - .WithBranch("main", _ => _ - .WithIncrement(IncrementStrategy.Major) - .WithTrackMergeTarget(false) - .WithTracksReleaseBranches(true) - ).Build(); - - using EmptyRepositoryFixture fixture = new("main"); - - fixture.MakeACommit("A"); - fixture.MakeACommit("B"); - fixture.BranchTo("release/foo"); - fixture.Checkout("main"); - fixture.MakeACommit("C"); - fixture.Checkout("release/foo"); - fixture.MakeACommit("D"); - fixture.ApplyTag("0.0.0"); - fixture.Checkout("main"); - fixture.MakeACommit("D"); - - // ✅ succeeds as expected - fixture.AssertFullSemver("1.0.0-1+2", configuration); - - fixture.Repository.DumpGraph(); - } } diff --git a/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs b/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs new file mode 100644 index 0000000000..4b1f5bbe86 --- /dev/null +++ b/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs @@ -0,0 +1,30 @@ +using GitVersion.Configuration; +using GitVersion.Extensions; + +namespace GitVersion.Core; + +internal static class EffectiveConfigurationExtensions +{ + public static TaggedSemanticVersions GetTaggedSemanticVersion(this EffectiveConfiguration effectiveConfiguration) + { + effectiveConfiguration.NotNull(); + + TaggedSemanticVersions taggedSemanticVersion = TaggedSemanticVersions.OfBranch; + + if (effectiveConfiguration.TrackMergeTarget) + { + taggedSemanticVersion |= TaggedSemanticVersions.OfMergeTargets; + } + + if (effectiveConfiguration.TrackMergeTarget) + { + taggedSemanticVersion |= TaggedSemanticVersions.OfReleaseBranches; + } + + if (!effectiveConfiguration.IsMainBranch && !effectiveConfiguration.IsReleaseBranch) + { + taggedSemanticVersion |= TaggedSemanticVersions.OfMainBranches; + } + return taggedSemanticVersion; + } +} diff --git a/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs b/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs index a93a6f42d5..8177f1600d 100644 --- a/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs +++ b/src/GitVersion.Core/Core/ITaggedSemanticVersionRepository.cs @@ -5,13 +5,6 @@ namespace GitVersion.Core; internal interface ITaggedSemanticVersionRepository { - ILookup GetAllTaggedSemanticVersions( - IGitVersionConfiguration configuration, - EffectiveConfiguration effectiveConfiguration, - IBranch branch, - string? label, - DateTimeOffset? notOlderThan); - ILookup GetTaggedSemanticVersionsOfBranch( IBranch branch, string? tagPrefix, @@ -24,18 +17,6 @@ ILookup GetTaggedSemanticVersionsOfMergeTarget( SemanticVersionFormat format, IIgnoreConfiguration ignore); - ILookup GetTaggedSemanticVersionsOfMainBranches( - IGitVersionConfiguration configuration, - string? tagPrefix, - SemanticVersionFormat format, - params IBranch[] excludeBranches); - - ILookup GetTaggedSemanticVersionsOfReleaseBranches( - IGitVersionConfiguration configuration, - string? tagPrefix, - SemanticVersionFormat format, - params IBranch[] excludeBranches); - ILookup GetTaggedSemanticVersions( string? tagPrefix, SemanticVersionFormat format, IIgnoreConfiguration ignore); } diff --git a/src/GitVersion.Core/Core/ITaggedSemanticVersionService.cs b/src/GitVersion.Core/Core/ITaggedSemanticVersionService.cs new file mode 100644 index 0000000000..8c476cc7f5 --- /dev/null +++ b/src/GitVersion.Core/Core/ITaggedSemanticVersionService.cs @@ -0,0 +1,42 @@ +using GitVersion.Configuration; +using GitVersion.Git; + +namespace GitVersion.Core; + +internal interface ITaggedSemanticVersionService +{ + ILookup GetTaggedSemanticVersions( + IBranch branch, + IGitVersionConfiguration configuration, + string? label, + DateTimeOffset? notOlderThan, + TaggedSemanticVersions taggedSemanticVersion); + + ILookup GetTaggedSemanticVersionsOfBranch( + IBranch branch, + string? tagPrefix, + SemanticVersionFormat format, + IIgnoreConfiguration ignore, + string? label = null, + DateTimeOffset? notOlderThan = null); + + ILookup GetTaggedSemanticVersionsOfMergeTarget( + IBranch branch, + string? tagPrefix, + SemanticVersionFormat format, + IIgnoreConfiguration ignore, + string? label = null, + DateTimeOffset? notOlderThan = null); + + ILookup GetTaggedSemanticVersionsOfMainBranches( + IGitVersionConfiguration configuration, + DateTimeOffset? notOlderThan = null, + string? label = null, + params IBranch[] excludeBranches); + + ILookup GetTaggedSemanticVersionsOfReleaseBranches( + IGitVersionConfiguration configuration, + DateTimeOffset? notOlderThan = null, + string? label = null, + params IBranch[] excludeBranches); +} diff --git a/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs b/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs index 9ed2ee7144..953f3a91b5 100644 --- a/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs +++ b/src/GitVersion.Core/Core/TaggedSemanticVersionRepository.cs @@ -6,122 +6,17 @@ namespace GitVersion.Core; -internal sealed class TaggedSemanticVersionRepository( - ILog log, - IGitRepository gitRepository, - IBranchRepository branchRepository) - : ITaggedSemanticVersionRepository +internal sealed class TaggedSemanticVersionRepository(ILog log, IGitRepository gitRepository) : ITaggedSemanticVersionRepository { - private readonly ConcurrentDictionary<(IBranch, string, SemanticVersionFormat), ILookup> + private readonly ConcurrentDictionary<(IBranch, string, SemanticVersionFormat), IReadOnlyList> taggedSemanticVersionsOfBranchCache = new(); - private readonly ConcurrentDictionary<(IBranch, string, SemanticVersionFormat), ILookup> + private readonly ConcurrentDictionary<(IBranch, string, SemanticVersionFormat), IReadOnlyList<(ICommit Key, SemanticVersionWithTag Value)>> taggedSemanticVersionsOfMergeTargetCache = new(); - private readonly ConcurrentDictionary<(string, SemanticVersionFormat), ILookup> + private readonly ConcurrentDictionary<(string, SemanticVersionFormat), IReadOnlyList> taggedSemanticVersionsCache = new(); private readonly ILog log = log.NotNull(); private readonly IGitRepository gitRepository = gitRepository.NotNull(); - private readonly IBranchRepository branchRepository = branchRepository.NotNull(); - - public ILookup GetAllTaggedSemanticVersions( - IGitVersionConfiguration configuration, EffectiveConfiguration effectiveConfiguration, - IBranch branch, string? label, DateTimeOffset? notOlderThan) - { - configuration.NotNull(); - effectiveConfiguration.NotNull(); - branch.NotNull(); - - IEnumerable<(ICommit Key, SemanticVersionWithTag Value)> GetElements() - { - var semanticVersionsOfBranch = GetTaggedSemanticVersionsOfBranch( - branch: branch, - tagPrefix: effectiveConfiguration.TagPrefix, - format: effectiveConfiguration.SemanticVersionFormat, - ignore: configuration.Ignore - ); - foreach (var grouping in semanticVersionsOfBranch) - { - if (grouping.Key.When > notOlderThan) continue; - - foreach (var semanticVersion in grouping) - { - if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) - { - yield return new(grouping.Key, semanticVersion); - } - } - } - - if (effectiveConfiguration.TrackMergeTarget) - { - var semanticVersionsOfMergeTarget = GetTaggedSemanticVersionsOfMergeTarget( - branch: branch, - tagPrefix: effectiveConfiguration.TagPrefix, - format: effectiveConfiguration.SemanticVersionFormat, - ignore: configuration.Ignore - ); - foreach (var grouping in semanticVersionsOfMergeTarget) - { - if (grouping.Key.When > notOlderThan) continue; - - foreach (var semanticVersion in grouping) - { - if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) - { - yield return new(grouping.Key, semanticVersion); - } - } - } - } - - if (effectiveConfiguration.TracksReleaseBranches) - { - var semanticVersionsOfReleaseBranches = GetTaggedSemanticVersionsOfReleaseBranches( - configuration: configuration, - tagPrefix: effectiveConfiguration.TagPrefix, - format: effectiveConfiguration.SemanticVersionFormat, - excludeBranches: branch - ); - foreach (var grouping in semanticVersionsOfReleaseBranches) - { - if (grouping.Key.When > notOlderThan) continue; - - foreach (var semanticVersion in grouping) - { - if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) - { - yield return new(grouping.Key, semanticVersion); - } - } - } - } - - if (!effectiveConfiguration.IsMainBranch && !effectiveConfiguration.IsReleaseBranch) - { - var semanticVersionsOfMainlineBranches = GetTaggedSemanticVersionsOfMainBranches( - configuration: configuration, - tagPrefix: effectiveConfiguration.TagPrefix, - format: effectiveConfiguration.SemanticVersionFormat, - excludeBranches: branch - ); - foreach (var grouping in semanticVersionsOfMainlineBranches) - { - if (grouping.Key.When > notOlderThan) continue; - - foreach (var semanticVersion in grouping) - { - if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) - { - yield return new(grouping.Key, semanticVersion); - } - } - } - } - } - - return GetElements().Distinct().OrderByDescending(element => element.Key.When) - .ToLookup(element => element.Key, element => element.Value); - } public ILookup GetTaggedSemanticVersionsOfBranch( IBranch branch, string? tagPrefix, SemanticVersionFormat format, IIgnoreConfiguration ignore) @@ -150,8 +45,7 @@ IEnumerable GetElements() var result = taggedSemanticVersionsOfBranchCache.GetOrAdd(new(branch, tagPrefix, format), _ => { isCached = false; - return GetElements().Distinct().OrderByDescending(element => element.Tag.Commit.When) - .ToLookup(element => element.Tag.Commit, element => element); + return GetElements().Distinct().OrderByDescending(element => element.Tag.Commit.When).ToList(); }); if (isCached) @@ -162,7 +56,7 @@ IEnumerable GetElements() ); } - return result; + return result.ToLookup(element => element.Tag.Commit, element => element); } public ILookup GetTaggedSemanticVersionsOfMergeTarget( @@ -192,8 +86,7 @@ public ILookup GetTaggedSemanticVersionsOfMerge var result = taggedSemanticVersionsOfMergeTargetCache.GetOrAdd(new(branch, tagPrefix, format), _ => { isCached = false; - return GetElements().Distinct().OrderByDescending(element => element.Key.When) - .ToLookup(element => element.Key, element => element.Value); + return GetElements().Distinct().OrderByDescending(element => element.Key.When).ToList(); }); if (isCached) @@ -204,59 +97,7 @@ public ILookup GetTaggedSemanticVersionsOfMerge ); } - return result; - } - - public ILookup GetTaggedSemanticVersionsOfMainBranches( - IGitVersionConfiguration configuration, string? tagPrefix, SemanticVersionFormat format, params IBranch[] excludeBranches) - { - configuration.NotNull(); - tagPrefix ??= string.Empty; - excludeBranches.NotNull(); - - IEnumerable GetElements() - { - using (this.log.IndentLog($"Getting tagged semantic versions of mainline branches. " + - $"TagPrefix: {tagPrefix} and Format: {format}")) - { - foreach (var mainlinemBranch in branchRepository.GetMainBranches(configuration, excludeBranches)) - { - foreach (var semanticVersion in GetTaggedSemanticVersionsOfBranch(mainlinemBranch, tagPrefix, format, configuration.Ignore).SelectMany(_ => _)) - { - yield return semanticVersion; - } - } - } - } - - return GetElements().Distinct().OrderByDescending(element => element.Tag.Commit.When) - .ToLookup(element => element.Tag.Commit, element => element); - } - - public ILookup GetTaggedSemanticVersionsOfReleaseBranches( - IGitVersionConfiguration configuration, string? tagPrefix, SemanticVersionFormat format, params IBranch[] excludeBranches) - { - configuration.NotNull(); - tagPrefix ??= string.Empty; - excludeBranches.NotNull(); - - IEnumerable GetElements() - { - using (this.log.IndentLog($"Getting tagged semantic versions of release branches. " + - $"TagPrefix: {tagPrefix} and Format: {format}")) - { - foreach (var releaseBranch in branchRepository.GetReleaseBranches(configuration, excludeBranches)) - { - foreach (var semanticVersion in GetTaggedSemanticVersionsOfBranch(releaseBranch, tagPrefix, format, configuration.Ignore).SelectMany(_ => _)) - { - yield return semanticVersion; - } - } - } - } - - return GetElements().Distinct().OrderByDescending(element => element.Tag.Commit.When) - .ToLookup(element => element.Tag.Commit, element => element); + return result.ToLookup(element => element.Key, element => element.Value); } public ILookup GetTaggedSemanticVersions( @@ -281,8 +122,7 @@ IEnumerable GetElements() var result = taggedSemanticVersionsCache.GetOrAdd(new(tagPrefix, format), _ => { isCached = false; - return GetElements().OrderByDescending(element => element.Tag.Commit.When) - .ToLookup(element => element.Tag.Commit, element => element); + return GetElements().OrderByDescending(element => element.Tag.Commit.When).ToList(); }); if (isCached) @@ -290,6 +130,6 @@ IEnumerable GetElements() this.log.Debug($"Returning cached tagged semantic versions. TagPrefix: {tagPrefix} and Format: {format}"); } - return result; + return result.ToLookup(element => element.Tag.Commit, element => element); } } diff --git a/src/GitVersion.Core/Core/TaggedSemanticVersionService.cs b/src/GitVersion.Core/Core/TaggedSemanticVersionService.cs new file mode 100644 index 0000000000..e7e8acffa9 --- /dev/null +++ b/src/GitVersion.Core/Core/TaggedSemanticVersionService.cs @@ -0,0 +1,247 @@ +using GitVersion.Configuration; +using GitVersion.Extensions; +using GitVersion.Git; + +namespace GitVersion.Core; + +internal sealed class TaggedSemanticVersionService( + ITaggedSemanticVersionRepository Repository, IBranchRepository BranchRepository) + : ITaggedSemanticVersionService +{ + private ITaggedSemanticVersionRepository Repository { get; } = Repository.NotNull(); + + private IBranchRepository BranchRepository { get; } = BranchRepository.NotNull(); + + public ILookup GetTaggedSemanticVersions( + IBranch branch, + IGitVersionConfiguration configuration, + string? label, + DateTimeOffset? notOlderThan, + TaggedSemanticVersions taggedSemanticVersion) + { + IEnumerable>> GetElements() + { + if (taggedSemanticVersion.HasFlag(TaggedSemanticVersions.OfBranch)) + { + yield return GetTaggedSemanticVersionsOfBranchInternal( + branch: branch, + tagPrefix: configuration.TagPrefix, + format: configuration.SemanticVersionFormat, + ignore: configuration.Ignore, + label: label, + notOlderThan: notOlderThan + ); + } + + if (taggedSemanticVersion.HasFlag(TaggedSemanticVersions.OfMergeTargets)) + { + yield return GetTaggedSemanticVersionsOfMergeTargetInternal( + branch: branch, + tagPrefix: configuration.TagPrefix, + format: configuration.SemanticVersionFormat, + ignore: configuration.Ignore, + label: label, + notOlderThan: notOlderThan + ); + } + + if (taggedSemanticVersion.HasFlag(TaggedSemanticVersions.OfMainBranches)) + { + yield return GetTaggedSemanticVersionsOfMainBranchesInternal( + configuration: configuration, + label: label, + notOlderThan: notOlderThan, + excludeBranches: branch + ); + } + + if (taggedSemanticVersion.HasFlag(TaggedSemanticVersions.OfReleaseBranches)) + { + yield return GetTaggedSemanticVersionsOfReleaseBranchesInternal( + configuration: configuration, + label: label, + notOlderThan: notOlderThan, + excludeBranches: branch + ); + } + } + + return GetElements().SelectMany(elements => elements).Distinct() + .OrderByDescending(element => element.Key.When) + .ToLookup(element => element.Key, element => element.Value); + } + + public ILookup GetTaggedSemanticVersionsOfBranch( + IBranch branch, + string? tagPrefix, + SemanticVersionFormat format, + IIgnoreConfiguration ignore, + string? label, + DateTimeOffset? notOlderThan) + { + var result = GetTaggedSemanticVersionsOfBranchInternal( + branch: branch, + tagPrefix: tagPrefix, + format: format, + ignore: ignore, + label: label, + notOlderThan: notOlderThan); + + return result.Distinct().OrderByDescending(element => element.Key.When) + .ToLookup(element => element.Key, element => element.Value); + } + + private IEnumerable> GetTaggedSemanticVersionsOfBranchInternal( + IBranch branch, + string? tagPrefix, + SemanticVersionFormat format, + IIgnoreConfiguration ignore, + string? label, + DateTimeOffset? notOlderThan) + { + var semanticVersionsOfBranch = Repository.GetTaggedSemanticVersionsOfBranch( + branch: branch, tagPrefix: tagPrefix, format: format, ignore: ignore + ); + foreach (var grouping in semanticVersionsOfBranch) + { + if (grouping.Key.When > notOlderThan) continue; + + foreach (var semanticVersion in grouping) + { + if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) + { + yield return new(grouping.Key, semanticVersion); + } + } + } + } + + public ILookup GetTaggedSemanticVersionsOfMergeTarget( + IBranch branch, + string? tagPrefix, + SemanticVersionFormat format, + IIgnoreConfiguration ignore, + string? label, + DateTimeOffset? notOlderThan) + { + var result = GetTaggedSemanticVersionsOfMergeTargetInternal( + branch: branch, + tagPrefix: tagPrefix, + format: format, + ignore: ignore, + label: label, + notOlderThan: notOlderThan); + + return result.Distinct() + .OrderByDescending(element => element.Key.When) + .ToLookup(element => element.Key, element => element.Value); + } + + private IEnumerable> GetTaggedSemanticVersionsOfMergeTargetInternal( + IBranch branch, + string? tagPrefix, + SemanticVersionFormat format, + IIgnoreConfiguration ignore, + string? label, + DateTimeOffset? notOlderThan) + { + var semanticVersionsOfMergeTarget = Repository.GetTaggedSemanticVersionsOfMergeTarget( + branch: branch, + tagPrefix: tagPrefix, + format: format, + ignore: ignore + ); + foreach (var grouping in semanticVersionsOfMergeTarget) + { + if (grouping.Key.When > notOlderThan) continue; + + foreach (var semanticVersion in grouping) + { + if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) + { + yield return new(grouping.Key, semanticVersion); + } + } + } + } + + public ILookup GetTaggedSemanticVersionsOfMainBranches( + IGitVersionConfiguration configuration, + DateTimeOffset? notOlderThan, + string? label, + params IBranch[] excludeBranches) + { + var result = GetTaggedSemanticVersionsOfMainBranchesInternal( + configuration: configuration, + notOlderThan: notOlderThan, + label: label, + excludeBranches: excludeBranches); + + return result.Distinct() + .OrderByDescending(element => element.Key.When) + .ToLookup(element => element.Key, element => element.Value); + } + + private IEnumerable> GetTaggedSemanticVersionsOfMainBranchesInternal( + IGitVersionConfiguration configuration, + DateTimeOffset? notOlderThan, + string? label, + params IBranch[] excludeBranches) + { + foreach (var releaseBranch in BranchRepository.GetMainBranches(configuration, excludeBranches)) + { + var taggedSemanticVersions = GetTaggedSemanticVersionsOfBranchInternal( + branch: releaseBranch, + tagPrefix: configuration.TagPrefix, + format: configuration.SemanticVersionFormat, + ignore: configuration.Ignore, + label: label, + notOlderThan: notOlderThan); + + foreach (var semanticVersion in taggedSemanticVersions) + { + yield return semanticVersion; + } + } + } + + public ILookup GetTaggedSemanticVersionsOfReleaseBranches( + IGitVersionConfiguration configuration, + DateTimeOffset? notOlderThan, + string? label, + params IBranch[] excludeBranches) + { + var result = GetTaggedSemanticVersionsOfReleaseBranchesInternal( + configuration: configuration, + notOlderThan: notOlderThan, + label: label, + excludeBranches: excludeBranches); + + return result.Distinct() + .OrderByDescending(element => element.Key.When) + .ToLookup(element => element.Key, element => element.Value); + } + + private IEnumerable> GetTaggedSemanticVersionsOfReleaseBranchesInternal( + IGitVersionConfiguration configuration, + DateTimeOffset? notOlderThan, + string? label, + params IBranch[] excludeBranches) + { + foreach (var releaseBranch in BranchRepository.GetReleaseBranches(configuration, excludeBranches)) + { + var taggedSemanticVersions = GetTaggedSemanticVersionsOfBranchInternal( + branch: releaseBranch, + tagPrefix: configuration.TagPrefix, + format: configuration.SemanticVersionFormat, + ignore: configuration.Ignore, + label: label, + notOlderThan: notOlderThan); + + foreach (var semanticVersion in taggedSemanticVersions) + { + yield return semanticVersion; + } + } + } +} diff --git a/src/GitVersion.Core/Core/TaggedSemanticVersions.cs b/src/GitVersion.Core/Core/TaggedSemanticVersions.cs new file mode 100644 index 0000000000..813ad55921 --- /dev/null +++ b/src/GitVersion.Core/Core/TaggedSemanticVersions.cs @@ -0,0 +1,17 @@ +namespace GitVersion.Core; + +[Flags] +internal enum TaggedSemanticVersions +{ + None = 0, + + OfBranch = 1, + + OfMergeTargets = 2, + + OfMainBranches = 4, + + OfReleaseBranches = 8, + + All = OfBranch | OfMergeTargets | OfMainBranches | OfReleaseBranches +} diff --git a/src/GitVersion.Core/GitVersionCoreModule.cs b/src/GitVersion.Core/GitVersionCoreModule.cs index 573e91f141..78be8603d6 100644 --- a/src/GitVersion.Core/GitVersionCoreModule.cs +++ b/src/GitVersion.Core/GitVersionCoreModule.cs @@ -19,6 +19,7 @@ public void RegisterTypes(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs index 692b4cbc4f..2839d46878 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionCalculators/NextVersionCalculator.cs @@ -14,7 +14,7 @@ internal class NextVersionCalculator( IEnumerable deploymentModeCalculators, IEnumerable versionStrategies, IEffectiveBranchConfigurationFinder effectiveBranchConfigurationFinder, - ITaggedSemanticVersionRepository taggedSemanticVersionRepository) + ITaggedSemanticVersionService taggedSemanticVersionService) : INextVersionCalculator { private readonly ILog log = log.NotNull(); @@ -35,8 +35,12 @@ public virtual SemanticVersion FindVersion() if (Context.IsCurrentCommitTagged && !someBranchRelatedPropertiesMightBeNotKnown && effectiveConfiguration.PreventIncrementWhenCurrentCommitTagged) { - var allTaggedSemanticVersions = taggedSemanticVersionRepository.GetAllTaggedSemanticVersions( - Context.Configuration, effectiveConfiguration, Context.CurrentBranch, null, Context.CurrentCommit.When + var allTaggedSemanticVersions = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: Context.CurrentBranch, + configuration: Context.Configuration, + label: null, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: effectiveConfiguration.GetTaggedSemanticVersion() ); var taggedSemanticVersionsOfCurrentCommit = allTaggedSemanticVersions[Context.CurrentCommit].ToList(); @@ -52,8 +56,12 @@ public virtual SemanticVersion FindVersion() if (Context.IsCurrentCommitTagged && someBranchRelatedPropertiesMightBeNotKnown && nextVersion.Configuration.PreventIncrementWhenCurrentCommitTagged) { - var allTaggedSemanticVersions = taggedSemanticVersionRepository.GetAllTaggedSemanticVersions( - Context.Configuration, nextVersion.Configuration, Context.CurrentBranch, null, Context.CurrentCommit.When + var allTaggedSemanticVersions = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: Context.CurrentBranch, + configuration: Context.Configuration, + label: null, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: nextVersion.Configuration.GetTaggedSemanticVersion() ); var taggedSemanticVersionsOfCurrentCommit = allTaggedSemanticVersions[Context.CurrentCommit].ToList(); @@ -71,11 +79,12 @@ public virtual SemanticVersion FindVersion() ); var ignore = Context.Configuration.Ignore; - var alternativeSemanticVersion = taggedSemanticVersionRepository.GetTaggedSemanticVersionsOfBranch( + var alternativeSemanticVersion = taggedSemanticVersionService.GetTaggedSemanticVersionsOfBranch( branch: nextVersion.BranchConfiguration.Branch, tagPrefix: Context.Configuration.TagPrefix, format: Context.Configuration.SemanticVersionFormat, - ignore: Context.Configuration.Ignore + ignore: Context.Configuration.Ignore, + notOlderThan: Context.CurrentCommit.When ).Where(element => element.Key.When <= Context.CurrentCommit.When && !(element.Key.When <= ignore.Before) && !ignore.Shas.Contains(element.Key.Sha) ).SelectMany(element => element).Max()?.Value; diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs index da116df3c7..bdc8e2d377 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/FallbacktVersionStrategy.cs @@ -12,12 +12,12 @@ namespace GitVersion.VersionCalculation; internal sealed class FallbackVersionStrategy( Lazy contextLazy, IIncrementStrategyFinder incrementStrategyFinder, - ITaggedSemanticVersionRepository taggedSemanticVersionRepository) + ITaggedSemanticVersionService taggedSemanticVersionService) : IVersionStrategy { private readonly Lazy contextLazy = contextLazy.NotNull(); private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull(); - private readonly ITaggedSemanticVersionRepository taggedSemanticVersionRepository = taggedSemanticVersionRepository.NotNull(); + private readonly ITaggedSemanticVersionService taggedSemanticVersionService = taggedSemanticVersionService.NotNull(); private GitVersionContext Context => contextLazy.Value; @@ -33,8 +33,12 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); - var baseVersionSource = this.taggedSemanticVersionRepository.GetAllTaggedSemanticVersions( - Context.Configuration, configuration.Value, Context.CurrentBranch, label, Context.CurrentCommit.When + var baseVersionSource = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: Context.CurrentBranch, + configuration: Context.Configuration, + label: label, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: configuration.Value.GetTaggedSemanticVersion() ).Select(element => element.Key).FirstOrDefault(); var increment = incrementStrategyFinder.DetermineIncrementedField( diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs index e29eb16ca4..11be4ab21c 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs @@ -11,11 +11,11 @@ namespace GitVersion.VersionCalculation; /// internal sealed class TaggedCommitVersionStrategy( Lazy contextLazy, - ITaggedSemanticVersionRepository taggedSemanticVersionRepository, + ITaggedSemanticVersionService taggedSemanticVersionService, IIncrementStrategyFinder incrementStrategyFinder) : IVersionStrategy { - private readonly ITaggedSemanticVersionRepository taggedSemanticVersionRepository = taggedSemanticVersionRepository.NotNull(); + private readonly ITaggedSemanticVersionService taggedSemanticVersionService = taggedSemanticVersionService.NotNull(); private readonly Lazy contextLazy = contextLazy.NotNull(); private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull(); @@ -31,13 +31,21 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur if (!Context.Configuration.VersionStrategy.HasFlag(VersionStrategies.TaggedCommit)) yield break; + var taggedSemanticVersions = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: Context.CurrentBranch, + configuration: Context.Configuration, + label: null, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: configuration.Value.GetTaggedSemanticVersion() + ).SelectMany(elements => elements).Distinct().ToArray(); + var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); - var taggedSemanticVersions = taggedSemanticVersionRepository - .GetAllTaggedSemanticVersions(Context.Configuration, configuration.Value, Context.CurrentBranch, label, Context.CurrentCommit.When) - .SelectMany(element => element) - .Distinct().ToArray(); - foreach (var semanticVersionWithTag in taggedSemanticVersions) + var maxTaggedSemanticVersion = taggedSemanticVersions + .Where(element => !element.Value.IsMatchForBranchSpecificLabel(label)).Max(); + + foreach (var semanticVersionWithTag + in taggedSemanticVersions.Where(element => element.Value.IsMatchForBranchSpecificLabel(label))) { var baseVersionSource = semanticVersionWithTag.Tag.Commit; var increment = incrementStrategyFinder.DetermineIncrementedField( @@ -54,7 +62,8 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur { Increment = increment, ForceIncrement = false, - Label = label + Label = label, + AlternativeSemanticVersion = maxTaggedSemanticVersion?.Value } }; } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TrunkBasedVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TrunkBasedVersionStrategy.cs index f5f4397775..c0f71e76de 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TrunkBasedVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TrunkBasedVersionStrategy.cs @@ -13,13 +13,13 @@ namespace GitVersion.VersionCalculation; internal sealed class TrunkBasedVersionStrategy( Lazy contextLazy, IRepositoryStore repositoryStore, - ITaggedSemanticVersionRepository taggedSemanticVersionRepository, + ITaggedSemanticVersionService taggedSemanticVersionService, IIncrementStrategyFinder incrementStrategyFinder) : IVersionStrategy { private volatile int iterationCounter; private readonly Lazy contextLazy = contextLazy.NotNull(); - private readonly ITaggedSemanticVersionRepository taggedSemanticVersionRepository = taggedSemanticVersionRepository.NotNull(); + private readonly ITaggedSemanticVersionService taggedSemanticVersionService = taggedSemanticVersionService.NotNull(); private readonly IRepositoryStore repositoryStore = repositoryStore.NotNull(); private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull(); @@ -78,10 +78,13 @@ public IEnumerable GetBaseVersions(EffectiveBranchConfiguration con var commitsInReverseOrder = configuration.Value.Ignore.Filter(Context.CurrentBranchCommits); - var taggedSemanticVersions = taggedSemanticVersionRepository.GetAllTaggedSemanticVersions( - Context.Configuration, configuration.Value, Context.CurrentBranch, null, Context.CurrentCommit.When + var taggedSemanticVersions = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: Context.CurrentBranch, + configuration: Context.Configuration, + label: null, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: configuration.Value.GetTaggedSemanticVersion() ); - var targetLabel = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); IterateOverCommitsRecursive( commitsInReverseOrder: commitsInReverseOrder, @@ -127,8 +130,12 @@ private bool IterateOverCommitsRecursive( { configuration = effectiveConfigurationWasBranchedFrom.Value; branchName = effectiveConfigurationWasBranchedFrom.Branch.Name; - taggedSemanticVersions = taggedSemanticVersionRepository.GetAllTaggedSemanticVersions( - Context.Configuration, effectiveConfigurationWasBranchedFrom.Value, effectiveConfigurationWasBranchedFrom.Branch, null, Context.CurrentCommit.When + taggedSemanticVersions = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: effectiveConfigurationWasBranchedFrom.Branch, + configuration: Context.Configuration, + label: null, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: effectiveConfigurationWasBranchedFrom.Value.GetTaggedSemanticVersion() ); } From 2cc7afb027cd3587174558033c19082cbbe0dee6 Mon Sep 17 00:00:00 2001 From: HHobeck Date: Sun, 14 Apr 2024 10:14:00 +0200 Subject: [PATCH 2/4] CHARSET: Fix file encoding. --- src/GitVersion.Core/Core/TaggedSemanticVersions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitVersion.Core/Core/TaggedSemanticVersions.cs b/src/GitVersion.Core/Core/TaggedSemanticVersions.cs index 813ad55921..898a70bd79 100644 --- a/src/GitVersion.Core/Core/TaggedSemanticVersions.cs +++ b/src/GitVersion.Core/Core/TaggedSemanticVersions.cs @@ -1,4 +1,4 @@ -namespace GitVersion.Core; +namespace GitVersion.Core; [Flags] internal enum TaggedSemanticVersions From ddb87d1644753d0c53b45befcab742e38f77b25e Mon Sep 17 00:00:00 2001 From: HHobeck Date: Sun, 14 Apr 2024 10:21:14 +0200 Subject: [PATCH 3/4] CHARSET: Fix file encoding. --- src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs b/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs index 4b1f5bbe86..0a2d51edb7 100644 --- a/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs +++ b/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs @@ -1,4 +1,4 @@ -using GitVersion.Configuration; +using GitVersion.Configuration; using GitVersion.Extensions; namespace GitVersion.Core; From 77523fefa5c3930f5b37030a6b9e43f5014c482c Mon Sep 17 00:00:00 2001 From: HHobeck Date: Mon, 15 Apr 2024 08:41:05 +0200 Subject: [PATCH 4/4] Fix integration test --- .../IntegrationTests/DocumentationSamples.cs | 6 ++-- .../FallbackVersionStrategyScenarios.cs | 31 +++++++++++++++++++ .../Core/EffectiveConfigurationExtensions.cs | 2 +- .../TaggedCommitVersionStrategy.cs | 16 +++++----- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs b/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs index e3480f25cf..9f1a2a895b 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs @@ -202,7 +202,7 @@ public void GitFlowMajorRelease() fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/2.0.0"); fixture.Checkout(MainBranch); - fixture.AssertFullSemver("2.0.0-4"); + fixture.AssertFullSemver("2.0.0-0"); fixture.ApplyTag("2.0.0"); fixture.AssertFullSemver("2.0.0"); @@ -291,7 +291,7 @@ public void GitFlowSupportMinorRelease() fixture.MergeNoFF("release/1.4.0"); fixture.SequenceDiagram.Destroy("release/1.4.0"); fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/1.4.0"); - fixture.AssertFullSemver("1.4.0-4"); + fixture.AssertFullSemver("1.4.0-0"); fixture.ApplyTag("1.4.0"); fixture.AssertFullSemver("1.4.0"); Console.WriteLine(fixture.SequenceDiagram.GetDiagram()); @@ -392,7 +392,7 @@ public void GitHubFlowMajorRelease() fixture.SequenceDiagram.Destroy("release/2.0.0"); fixture.SequenceDiagram.NoteOver("Release branches are deleted once merged", "release/2.0.0"); - fixture.AssertFullSemver("2.0.0-4"); + fixture.AssertFullSemver("2.0.0-0"); fixture.ApplyTag("2.0.0"); fixture.AssertFullSemver("2.0.0"); fixture.MakeACommit(); diff --git a/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs index 0ef417e9fa..b7bcf88f90 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/FallbackVersionStrategyScenarios.cs @@ -93,4 +93,35 @@ public void TakeTheLatestCommitAsBaseVersion(bool mode) // ✅ succeeds as expected fixture.AssertFullSemver("1.0.0-1+1", configuration); } + + [TestCase(false, "1.0.0-1+4")] + [TestCase(true, "1.0.0-1+2")] + public void TakeTheCommitBranchedFromAsBaseVersionWhenTracksReleaseBranchesIsTrue( + bool tracksReleaseBranches, string version) + { + var configuration = ConfigurationBuilder + .WithBranch("main", _ => _ + .WithIncrement(IncrementStrategy.Major) + .WithTrackMergeTarget(false) + .WithTracksReleaseBranches(tracksReleaseBranches) + ).Build(); + + using EmptyRepositoryFixture fixture = new("main"); + + fixture.MakeACommit("A"); + fixture.MakeACommit("B"); + fixture.BranchTo("release/foo"); + fixture.Checkout("main"); + fixture.MakeACommit("C"); + fixture.Checkout("release/foo"); + fixture.MakeACommit("D"); + fixture.ApplyTag("0.0.0"); + fixture.Checkout("main"); + fixture.MakeACommit("D"); + + // ✅ succeeds as expected + fixture.AssertFullSemver(version, configuration); + + fixture.Repository.DumpGraph(); + } } diff --git a/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs b/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs index 0a2d51edb7..c6a7efb553 100644 --- a/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs +++ b/src/GitVersion.Core/Core/EffectiveConfigurationExtensions.cs @@ -16,7 +16,7 @@ public static TaggedSemanticVersions GetTaggedSemanticVersion(this EffectiveConf taggedSemanticVersion |= TaggedSemanticVersions.OfMergeTargets; } - if (effectiveConfiguration.TrackMergeTarget) + if (effectiveConfiguration.TracksReleaseBranches) { taggedSemanticVersion |= TaggedSemanticVersions.OfReleaseBranches; } diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs index 11be4ab21c..35cf8075b9 100644 --- a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/TaggedCommitVersionStrategy.cs @@ -40,12 +40,15 @@ private IEnumerable GetBaseVersionsInternal(EffectiveBranchConfigur ).SelectMany(elements => elements).Distinct().ToArray(); var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); + var semanticVersionsWithTag = taggedSemanticVersionService.GetTaggedSemanticVersions( + branch: Context.CurrentBranch, + configuration: Context.Configuration, + label: label, + notOlderThan: Context.CurrentCommit.When, + taggedSemanticVersion: configuration.Value.GetTaggedSemanticVersion() + ).SelectMany(elements => elements).Distinct().ToArray(); - var maxTaggedSemanticVersion = taggedSemanticVersions - .Where(element => !element.Value.IsMatchForBranchSpecificLabel(label)).Max(); - - foreach (var semanticVersionWithTag - in taggedSemanticVersions.Where(element => element.Value.IsMatchForBranchSpecificLabel(label))) + foreach (var semanticVersionWithTag in semanticVersionsWithTag) { var baseVersionSource = semanticVersionWithTag.Tag.Commit; var increment = incrementStrategyFinder.DetermineIncrementedField( @@ -62,8 +65,7 @@ in taggedSemanticVersions.Where(element => element.Value.IsMatchForBranchSpecifi { Increment = increment, ForceIncrement = false, - Label = label, - AlternativeSemanticVersion = maxTaggedSemanticVersion?.Value + Label = label } }; }