diff --git a/src/GitVersion.Core.Tests/IntegrationTests/DevelopScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/DevelopScenarios.cs index 05be889d5f..da95be489c 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/DevelopScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/DevelopScenarios.cs @@ -44,8 +44,8 @@ public void WhenDevelopHasMultipleCommitsSpecifyNonExistingCommitId() public void WhenDevelopBranchedFromTaggedCommitOnMainVersionDoesNotChange() { using var fixture = new EmptyRepositoryFixture(); - fixture.Repository.MakeATaggedCommit("1.0.0"); - Commands.Checkout(fixture.Repository, fixture.Repository.CreateBranch("develop")); + fixture.MakeATaggedCommit("1.0.0"); + fixture.BranchTo("develop"); fixture.AssertFullSemver("1.0.0"); } diff --git a/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs b/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs index aea9c00cbb..1def653a52 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/DocumentationSamples.cs @@ -136,7 +136,7 @@ public void GitFlowMinorRelease() // Make a commit after a tag should bump up the beta fixture.MakeACommit(); - fixture.AssertFullSemver("1.3.0-beta.2+2"); + fixture.AssertFullSemver("1.3.0-beta.2+1"); // Complete release fixture.Checkout(MainBranch); @@ -191,7 +191,7 @@ public void GitFlowMajorRelease() // Make a commit after a tag should bump up the beta fixture.MakeACommit(); - fixture.AssertFullSemver("2.0.0-beta.2+2"); + fixture.AssertFullSemver("2.0.0-beta.2+1"); // Complete release fixture.Checkout(MainBranch); @@ -380,11 +380,11 @@ public void GitHubFlowMajorRelease() // test that the CommitsSinceVersionSource should still return commit count var version = fixture.GetVersion(); - version.CommitsSinceVersionSource.ShouldBe("2"); + version.CommitsSinceVersionSource.ShouldBe("0"); // Make a commit after a tag should bump up the beta fixture.MakeACommit(); - fixture.AssertFullSemver("2.0.0-beta.2+3"); + fixture.AssertFullSemver("2.0.0-beta.2+1"); // Complete release fixture.Checkout(MainBranch); diff --git a/src/GitVersion.Core.Tests/IntegrationTests/HotfixBranchScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/HotfixBranchScenarios.cs index 435352e285..ab7217bf6b 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/HotfixBranchScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/HotfixBranchScenarios.cs @@ -25,7 +25,7 @@ public void PatchLatestReleaseExample() fixture.Repository.ApplyTag("1.2.1-beta.1"); fixture.AssertFullSemver("1.2.1-beta.1"); fixture.Repository.MakeACommit(); - fixture.AssertFullSemver("1.2.1-beta.2+3"); + fixture.AssertFullSemver("1.2.1-beta.2+1"); // Merge hotfix branch to main Commands.Checkout(fixture.Repository, MainBranch); diff --git a/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs index 8c2708fbbb..81f5f6b038 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/MainScenarios.cs @@ -330,7 +330,7 @@ public void PreventDecrementationOfVersionsOnTheDevelopmentBranch() fixture.MergeNoFF("develop"); // ✅ succeeds as expected - fixture.AssertFullSemver("1.0.0-beta.2+2", configurationBuilder.Build()); + fixture.AssertFullSemver("1.0.0-beta.2+3", configurationBuilder.Build()); fixture.Checkout("develop"); diff --git a/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs index da92c67631..86763aae65 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/OtherBranchScenarios.cs @@ -53,9 +53,9 @@ public void ShouldNotGetVersionFromFeatureBranchIfNotMerged() fixture.MakeATaggedCommit("1.0.1-feature.1"); fixture.Checkout(MainBranch); fixture.BranchTo("develop"); - fixture.Repository.MakeACommit(); + fixture.MakeACommit(); - fixture.AssertFullSemver("1.0.0-alpha.1", configuration); + fixture.AssertFullSemver("1.0.0-alpha.2", configuration); fixture.Repository.DumpGraph(); } diff --git a/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs index 4433d469d2..25e36b726f 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs @@ -2,6 +2,7 @@ using GitVersion.Configuration; using GitVersion.Core.Tests.Helpers; using GitVersion.Helpers; +using GitVersion.VersionCalculation; using LibGit2Sharp; namespace GitVersion.Core.Tests.IntegrationTests; @@ -163,13 +164,38 @@ public void EnsureTrackMergeTargetStrategyWhichWillLookForTaggedMergecommits(boo fixture.Repository.DumpGraph(); } + [Test] + public void EnsurePreReleaseTagLabelWillBeConsideredIfCurrentBranchIsRelease() + { + var configuration = GitHubFlowConfigurationBuilder.New.Build(); + + using var fixture = new EmptyRepositoryFixture("release/2.0.0"); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("2.0.0-beta.1+1", configuration); + + fixture.ApplyTag("2.0.0-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver("2.0.0-beta.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("2.0.0-beta.2+1", configuration); + } + [TestCase(1)] [TestCase(2)] + [TestCase(3)] public void EnsurePreReleaseTagLabelWillBeConsideredIfNoLabelIsDefined(long patchNumber) { var configuration = GitHubFlowConfigurationBuilder.New .WithLabel(null) .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) .WithLabel(null).WithIncrement(IncrementStrategy.Patch) ).Build(); @@ -227,4 +253,659 @@ public void EnsurePreReleaseTagLabelWillBeConsideredIfNoLabelIsDefined(long patc fixture.Repository.DumpGraph(); } + + [Test] + public void EnsurePreReleaseTagLabelWithInitialTagForPatchNumberOneWillBeConsideredIfNoLabelIsDefined() + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithLabel(null) + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel(null).WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeATaggedCommit("1.0.0"); + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("1.0.1+1", configuration); + + fixture.ApplyTag($"1.0.1-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+3", configuration); + + fixture.MakeATaggedCommit($"1.0.1-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+4", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+5", configuration); + + fixture.MakeATaggedCommit($"1.0.1-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+6", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1+7", configuration); + + fixture.ApplyTag($"1.0.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.2+1", configuration); + + fixture.Repository.DumpGraph(); + } + + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWithInitialTagForPatchNumberTwoAndThreeWillBeConsideredIfNoLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithLabel(null) + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel(null).WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeATaggedCommit("1.0.0"); + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("1.0.1+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+2", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.2+1", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.3+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber + 1}+1", configuration); + + fixture.Repository.DumpGraph(); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWillBeConsideredIfLabelIsEmpty(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel(string.Empty).WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("0.0.1+1", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+3", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+4", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+5", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+6", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}+7", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber + 1}+1", configuration); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWithInitialTagWillBeConsideredIfLabelIsEmpty(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel(string.Empty).WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeATaggedCommit("1.0.0"); + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("1.0.1+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+3", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+4", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+5", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+6", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}+7", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber + 1}+1", configuration); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWillBeConsideredIfAlphaLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithLabel(null) + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel("alpha").WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("0.0.1-alpha.1+1", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.2+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.2+2", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.2+3", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.2+4", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.2+5", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-alpha.2+6", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber + 1}-alpha.1+1", configuration); + + fixture.Repository.DumpGraph(); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWithInitialTagWillBeConsideredIfAlphaLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithLabel(null) + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel("alpha").WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeATaggedCommit("1.0.0"); + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("1.0.1-alpha.1+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+2", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+3", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+4", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+5", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-alpha.2+6", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber + 1}-alpha.1+1", configuration); + + fixture.Repository.DumpGraph(); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWillBeConsideredIfBetaLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel("beta").WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("0.0.1-beta.1+1", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.1+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.1+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.1+3", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.2+1", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-beta.3+1", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber + 1}-beta.1+1", configuration); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWithInitialTagWillBeConsideredIfBetaLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel("beta").WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeATaggedCommit("1.0.0"); + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("1.0.1-beta.1+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.1+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.1+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.1+3", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.2+1", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-beta.3+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber + 1}-beta.1+1", configuration); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWillBeConsideredIfGammaLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel("gamma").WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("0.0.1-gamma.1+1", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+3", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+4", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+5", configuration); + + fixture.MakeATaggedCommit($"0.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+6", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}-gamma.1+7", configuration); + + fixture.ApplyTag($"0.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"0.0.{patchNumber + 1}-gamma.1+1", configuration); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void EnsurePreReleaseTagLabelWithInitialTagWillBeConsideredIfGammaLabelIsDefined(long patchNumber) + { + var configuration = GitHubFlowConfigurationBuilder.New + .WithBranch("main", branchBuilder => branchBuilder + .WithVersioningMode(VersioningMode.ContinuousDelivery) + .WithLabel("gamma").WithIncrement(IncrementStrategy.Patch) + ).Build(); + + using var fixture = new EmptyRepositoryFixture("main"); + + fixture.MakeATaggedCommit("1.0.0"); + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver("1.0.1-gamma.1+1", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}-alpha.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+1", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+2", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+3", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.1"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+4", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+5", configuration); + + fixture.MakeATaggedCommit($"1.0.{patchNumber}-beta.2"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+6", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}-gamma.1+7", configuration); + + fixture.ApplyTag($"1.0.{patchNumber}"); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber}", configuration); + + fixture.MakeACommit(); + + // ✅ succeeds as expected + fixture.AssertFullSemver($"1.0.{patchNumber + 1}-gamma.1+1", configuration); + } } diff --git a/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs index bf56382be8..8023c895b6 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs @@ -290,7 +290,7 @@ public void WhenMergingReleaseBackToDevShouldNotResetBetaVersion() fixture.Repository.MakeCommits(1); - fixture.AssertFullSemver("2.0.0-beta.2+2"); + fixture.AssertFullSemver("2.0.0-beta.2+1"); //merge down to develop fixture.Checkout("develop"); @@ -298,9 +298,9 @@ public void WhenMergingReleaseBackToDevShouldNotResetBetaVersion() //but keep working on the release fixture.Checkout("release-2.0.0"); - fixture.AssertFullSemver("2.0.0-beta.2+2"); + fixture.AssertFullSemver("2.0.0-beta.2+1"); fixture.MakeACommit(); - fixture.AssertFullSemver("2.0.0-beta.2+3"); + fixture.AssertFullSemver("2.0.0-beta.2+2"); } [Test] diff --git a/src/GitVersion.Core.Tests/IntegrationTests/SupportBranchScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/SupportBranchScenarios.cs index c7a34df067..d43aff23d8 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/SupportBranchScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/SupportBranchScenarios.cs @@ -85,7 +85,7 @@ public void WhenSupportIsBranchedFromMainWithSpecificTag() fixture.MakeACommit(); fixture.BranchTo("support/1"); - fixture.AssertFullSemver("1.4.0+1", configuration); + fixture.AssertFullSemver("1.4.0+2", configuration); } [Test] @@ -101,6 +101,6 @@ public void WhenSupportIsBranchedFromMainWithSpecificTagOnCommit() fixture.ApplyTag("1.4.0-rc"); fixture.BranchTo("support/1"); - fixture.AssertFullSemver("1.4.0+0", configuration); + fixture.AssertFullSemver("1.4.0+1", configuration); } } diff --git a/src/GitVersion.Core.Tests/IntegrationTests/VersionInTagScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/VersionInTagScenarios.cs index 5e194224a8..e78ff17810 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/VersionInTagScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/VersionInTagScenarios.cs @@ -16,7 +16,7 @@ public void TagPreReleaseWeightIsNotConfigured_HeadIsATaggedCommit_WeightedPreRe .Build(); // Act - using var fixture = new BaseGitFlowRepositoryFixture("1.0.0"); + using var fixture = new EmptyRepositoryFixture("main"); fixture.MakeATaggedCommit("1.1.0"); var version = fixture.GetVersion(configuration); @@ -34,7 +34,7 @@ public void LabelPreReleaseWeightIsConfigured_HeadIsATaggedCommit_WeightedPreRel .Build(); // Act - using var fixture = new BaseGitFlowRepositoryFixture("1.0.0"); + using var fixture = new EmptyRepositoryFixture("main"); fixture.MakeATaggedCommit("1.1.0"); var version = fixture.GetVersion(configuration); @@ -61,6 +61,9 @@ public void LabelPreReleaseWeightIsConfigured_GitFlowReleaseIsFinished_WeightedP fixture.BranchTo("release/1.1.0"); fixture.MakeACommit("Release commit 1"); fixture.AssertFullSemver("1.1.0-beta.1", configuration); + + fixture.Checkout("main"); + fixture.MergeNoFF("release/1.1.0"); fixture.ApplyTag("1.1.0"); var version = fixture.GetVersion(configuration); @@ -86,6 +89,9 @@ public void TagPreReleaseWeightIsNotConfigured_GitFlowReleaseIsFinished_Weighted fixture.BranchTo("release/1.1.0"); fixture.MakeACommit("Release commit 1"); fixture.AssertFullSemver("1.1.0-beta.1", configuration); + + fixture.Checkout("main"); + fixture.MergeNoFF("release/1.1.0"); fixture.ApplyTag("1.1.0"); var version = fixture.GetVersion(configuration); diff --git a/src/GitVersion.Core.Tests/VersionCalculation/NextVersionCalculatorTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/NextVersionCalculatorTests.cs index 1a3b66200b..a6375f4daf 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/NextVersionCalculatorTests.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/NextVersionCalculatorTests.cs @@ -239,19 +239,18 @@ public void PreReleaseNumberShouldBeScopeToPreReleaseLabelInContinuousDelivery() .Build(); using var fixture = new EmptyRepositoryFixture(); - fixture.Repository.MakeACommit(); + fixture.MakeACommit(); - fixture.Repository.CreateBranch("feature/test"); - Commands.Checkout(fixture.Repository, "feature/test"); - fixture.Repository.MakeATaggedCommit("0.1.0-test.1"); - fixture.Repository.MakeACommit(); + fixture.BranchTo("feature/test"); + fixture.MakeATaggedCommit("0.1.0-test.1"); + fixture.MakeACommit(); fixture.AssertFullSemver("0.1.0-test.2+1", configuration); - Commands.Checkout(fixture.Repository, MainBranch); + fixture.Checkout("main"); fixture.Repository.Merge("feature/test", Generate.SignatureNow()); - fixture.AssertFullSemver("0.1.0-beta.1+1", configuration); // just one commit no fast forward merge here. + fixture.AssertFullSemver("0.1.0-beta.1+3", configuration); } [Test] @@ -457,7 +456,7 @@ public void ShouldIgnorePreReleaseVersionInMainlineMode() null ); var mainlineVersionCalculatorMock = Substitute.For(); - mainlineVersionCalculatorMock.FindMainlineModeVersion(Arg.Any()).Returns(lowerVersion.SemanticVersion); + mainlineVersionCalculatorMock.FindMainlineModeVersion(Arg.Any()).Returns(lowerVersion.SemanticVersion); var versionStrategies = new IVersionStrategy[] { new TestVersionStrategy(preReleaseVersion, lowerVersion) }; var unitUnderTest = new NextVersionCalculator(Substitute.For(), mainlineVersionCalculatorMock, repositoryStoreMock, new(context), versionStrategies, effectiveBranchConfigurationFinderMock, incrementStrategyFinderMock); diff --git a/src/GitVersion.Core.Tests/VersionCalculation/TestMainlineVersionCalculator.cs b/src/GitVersion.Core.Tests/VersionCalculation/TestMainlineVersionCalculator.cs index aa69a47ab4..35b99d16a8 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/TestMainlineVersionCalculator.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/TestMainlineVersionCalculator.cs @@ -8,7 +8,7 @@ public class TestMainlineVersionCalculator : IMainlineVersionCalculator public TestMainlineVersionCalculator(SemanticVersionBuildMetaData metaData) => this.metaData = metaData; - public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion) => throw new NotImplementedException(); + public SemanticVersion FindMainlineModeVersion(NextVersion nextVersion) => throw new NotImplementedException(); public SemanticVersionBuildMetaData CreateVersionBuildMetaData(ICommit? baseVersionSource) => this.metaData; } diff --git a/src/GitVersion.Core/Configuration/ConfigurationExtensions.cs b/src/GitVersion.Core/Configuration/ConfigurationExtensions.cs index cd57a02bc1..c176e3b19c 100644 --- a/src/GitVersion.Core/Configuration/ConfigurationExtensions.cs +++ b/src/GitVersion.Core/Configuration/ConfigurationExtensions.cs @@ -1,6 +1,5 @@ using System.Text.RegularExpressions; using GitVersion.Extensions; -using GitVersion.Logging; namespace GitVersion.Configuration; @@ -60,11 +59,11 @@ public static bool IsReleaseBranch(this IGitVersionConfiguration configuration, => configuration.GetBranchConfiguration(branchName).IsReleaseBranch ?? false; public static string? GetBranchSpecificLabel( - this EffectiveConfiguration configuration, ILog log, ReferenceName branchName, string? branchNameOverride) - => GetBranchSpecificLabel(configuration, log, branchName.WithoutOrigin, branchNameOverride); + this EffectiveConfiguration configuration, ReferenceName branchName, string? branchNameOverride) + => GetBranchSpecificLabel(configuration, branchName.WithoutOrigin, branchNameOverride); public static string? GetBranchSpecificLabel( - this EffectiveConfiguration configuration, ILog log, string? branchName, string? branchNameOverride) + this EffectiveConfiguration configuration, string? branchName, string? branchNameOverride) { configuration.NotNull(); @@ -76,10 +75,7 @@ public static bool IsReleaseBranch(this IGitVersionConfiguration configuration, if (label?.Contains(ConfigurationConstants.BranchNamePlaceholder) == true) { - log.Info("Using branch name to calculate version tag"); - var value = branchNameOverride ?? branchName; - if (!configuration.BranchPrefixToTrim.IsNullOrWhiteSpace()) { var branchNameTrimmed = value?.RegexReplace( diff --git a/src/GitVersion.Core/Configuration/EffectiveBranchConfiguration.cs b/src/GitVersion.Core/Configuration/EffectiveBranchConfiguration.cs index dbafef5173..66e4cbb53a 100644 --- a/src/GitVersion.Core/Configuration/EffectiveBranchConfiguration.cs +++ b/src/GitVersion.Core/Configuration/EffectiveBranchConfiguration.cs @@ -16,5 +16,10 @@ public EffectiveBranchConfiguration(IBranch branch, EffectiveConfiguration value } public NextVersion CreateNextVersion(BaseVersion baseVersion, SemanticVersion incrementedVersion) - => new(incrementedVersion.NotNull(), baseVersion.NotNull(), new(Branch, Value)); + { + incrementedVersion.NotNull(); + baseVersion.NotNull(); + + return new NextVersion(incrementedVersion, baseVersion, new EffectiveBranchConfiguration(Branch, Value)); + } } diff --git a/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs b/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs index e01256f5fb..3f65ea59bc 100644 --- a/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs +++ b/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs @@ -41,8 +41,16 @@ public interface IRepositoryStore SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, SemanticVersionFormat versionFormat, bool handleDetachedBranch); - IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex, SemanticVersionFormat versionFormat); - IEnumerable GetSemanticVersionFromTags(string? tagPrefixRegex, SemanticVersionFormat semanticVersionFormat); + IEnumerable GetVersionTagsOnBranch( + IBranch branch, string? labelPrefix, SemanticVersionFormat semanticVersionFormat + ); + + IReadOnlyList GetTaggedSemanticVersions(string? labelPrefix, SemanticVersionFormat format); + + IReadOnlyList GetTaggedSemanticVersionsOnBranch( + IBranch branch, string? labelPrefix, SemanticVersionFormat format + ); + bool IsCommitOnBranch(ICommit? baseVersionSource, IBranch branch, ICommit firstMatchingCommit); int GetNumberOfUncommittedChanges(); diff --git a/src/GitVersion.Core/Core/RepositoryStore.cs b/src/GitVersion.Core/Core/RepositoryStore.cs index b6e6d8db5f..6dfd6690bc 100644 --- a/src/GitVersion.Core/Core/RepositoryStore.cs +++ b/src/GitVersion.Core/Core/RepositoryStore.cs @@ -10,7 +10,10 @@ public class RepositoryStore : IRepositoryStore { private readonly ILog log; private readonly IGitRepository repository; - private readonly Dictionary> semanticVersionTagsOnBranchCache = new(); + + private IReadOnlyList? taggedSemanticVersionsCache; + private readonly Dictionary> taggedSemanticVersionsOnBranchCache = new(); + private readonly MergeBaseFinder mergeBaseFinder; public RepositoryStore(ILog log, IGitRepository repository) @@ -249,39 +252,80 @@ public IEnumerable FindCommitBranchesWasBranchedFrom(IBranch branc .SelectMany(tag => GetCurrentCommitSemanticVersions(commit, tagPrefix, tag, versionFormat, handleDetachedBranch)) .Max(); - public IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex, SemanticVersionFormat versionFormat) + public IEnumerable GetVersionTagsOnBranch( + IBranch branch, string? labelPrefix, SemanticVersionFormat semanticVersionFormat) { branch = branch.NotNull(); - if (this.semanticVersionTagsOnBranchCache.TryGetValue(branch, out var onBranch)) + if (this.taggedSemanticVersionsOnBranchCache.TryGetValue(branch, out var onBranch)) { this.log.Debug($"Cache hit for version tags on branch '{branch.Name.Canonical}"); - return onBranch; + return onBranch.Select(element => element.Value); } using (this.log.IndentLog($"Getting version tags from branch '{branch.Name.Canonical}'.")) { - var semanticVersions = GetSemanticVersionFromTags(tagPrefixRegex, versionFormat); + var semanticVersions = GetTaggedSemanticVersions(labelPrefix, semanticVersionFormat); var tagsBySha = semanticVersions.Where(t => t.Tag.TargetSha != null).ToLookup(t => t.Tag.TargetSha, t => t); - var versionTags = (branch.Commits?.SelectMany(c => tagsBySha[c.Sha].Select(t => t.Value)) ?? Enumerable.Empty()).ToList(); + var versionTags = (branch.Commits?.SelectMany(c => tagsBySha[c.Sha].Select(t => t)) + ?? Enumerable.Empty()).ToList(); - this.semanticVersionTagsOnBranchCache.Add(branch, versionTags); - return versionTags; + this.taggedSemanticVersionsOnBranchCache.Add(branch, versionTags); + return versionTags.Select(element => element.Value); } } - public IEnumerable GetSemanticVersionFromTags(string? tagPrefixRegex, SemanticVersionFormat semanticVersionFormat) + public IReadOnlyList GetTaggedSemanticVersions(string? labelPrefix, SemanticVersionFormat format) { - foreach (var tag in this.repository.Tags) + if (this.taggedSemanticVersionsCache != null) + { + this.log.Debug($"Returning cached tagged semantic versions. LabelPrefix: {labelPrefix} and Format: {format}"); + return this.taggedSemanticVersionsCache; + } + + using (this.log.IndentLog($"Getting tagged semantic versions. LabelPrefix: {labelPrefix} and Format: {format}")) { - if (SemanticVersion.TryParse(tag.Name.Friendly, tagPrefixRegex, out var semanticVersion, semanticVersionFormat)) + this.taggedSemanticVersionsCache = GetTaggedSemanticVersionsInternal().ToList(); + return this.taggedSemanticVersionsCache; + } + + IEnumerable GetTaggedSemanticVersionsInternal() + { + foreach (var tag in this.repository.Tags) { - yield return new SemanticVersionWithTag(semanticVersion, tag); + if (SemanticVersion.TryParse(tag.Name.Friendly, labelPrefix, out var semanticVersion, format)) + { + yield return new SemanticVersionWithTag(semanticVersion, tag); + } } } } + public IReadOnlyList GetTaggedSemanticVersionsOnBranch( + IBranch branch, string? labelPrefix, SemanticVersionFormat format) + { + branch = branch.NotNull(); + + if (this.taggedSemanticVersionsOnBranchCache.TryGetValue(branch, out var onBranch)) + { + this.log.Debug($"Returning cached tagged semantic versions from '{branch.Name.Canonical}'. LabelPrefix: {labelPrefix} and Format: {format}"); + return onBranch; + } + + using (this.log.IndentLog($"Getting tagged semantic versions from '{branch.Name.Canonical}'. LabelPrefix: {labelPrefix} and Format: {format}")) + { + var semanticVersions = GetTaggedSemanticVersions(labelPrefix, format); + var tagsBySha = semanticVersions.Where(t => t.Tag.TargetSha != null).ToLookup(t => t.Tag.TargetSha, t => t); + + var versionTags = (branch.Commits?.SelectMany(c => tagsBySha[c.Sha].Select(t => t)) + ?? Enumerable.Empty()).ToList(); + + this.taggedSemanticVersionsOnBranchCache.Add(branch, versionTags); + return versionTags; + } + } + public IEnumerable GetCommitLog(ICommit? baseVersionSource, ICommit? currentCommit) { var filter = new CommitFilter { IncludeReachableFrom = currentCommit, ExcludeReachableFrom = baseVersionSource, SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time }; diff --git a/src/GitVersion.Core/PublicAPI.Unshipped.txt b/src/GitVersion.Core/PublicAPI.Unshipped.txt index 67659f8d81..4826882af1 100644 --- a/src/GitVersion.Core/PublicAPI.Unshipped.txt +++ b/src/GitVersion.Core/PublicAPI.Unshipped.txt @@ -87,11 +87,12 @@ GitVersion.Common.IRepositoryStore.GetMainlineCommitLog(GitVersion.ICommit? base GitVersion.Common.IRepositoryStore.GetMergeBaseCommits(GitVersion.ICommit? mergeCommit, GitVersion.ICommit? mergedHead, GitVersion.ICommit? findMergeBase) -> System.Collections.Generic.IEnumerable! GitVersion.Common.IRepositoryStore.GetNumberOfUncommittedChanges() -> int GitVersion.Common.IRepositoryStore.GetReleaseBranches(System.Collections.Generic.IEnumerable>! releaseBranchConfig) -> System.Collections.Generic.IEnumerable! -GitVersion.Common.IRepositoryStore.GetSemanticVersionFromTags(string? tagPrefixRegex, GitVersion.SemanticVersionFormat semanticVersionFormat) -> System.Collections.Generic.IEnumerable! GitVersion.Common.IRepositoryStore.GetSourceBranches(GitVersion.IBranch! branch, GitVersion.Configuration.IGitVersionConfiguration! configuration, params GitVersion.IBranch![]! excludedBranches) -> System.Collections.Generic.IEnumerable! GitVersion.Common.IRepositoryStore.GetSourceBranches(GitVersion.IBranch! branch, GitVersion.Configuration.IGitVersionConfiguration! configuration, System.Collections.Generic.IEnumerable! excludedBranches) -> System.Collections.Generic.IEnumerable! +GitVersion.Common.IRepositoryStore.GetTaggedSemanticVersions(string? labelPrefix, GitVersion.SemanticVersionFormat format) -> System.Collections.Generic.IReadOnlyList! +GitVersion.Common.IRepositoryStore.GetTaggedSemanticVersionsOnBranch(GitVersion.IBranch! branch, string? labelPrefix, GitVersion.SemanticVersionFormat format) -> System.Collections.Generic.IReadOnlyList! GitVersion.Common.IRepositoryStore.GetTargetBranch(string? targetBranchName) -> GitVersion.IBranch! -GitVersion.Common.IRepositoryStore.GetVersionTagsOnBranch(GitVersion.IBranch! branch, string? tagPrefixRegex, GitVersion.SemanticVersionFormat versionFormat) -> System.Collections.Generic.IEnumerable! +GitVersion.Common.IRepositoryStore.GetVersionTagsOnBranch(GitVersion.IBranch! branch, string? labelPrefix, GitVersion.SemanticVersionFormat semanticVersionFormat) -> System.Collections.Generic.IEnumerable! GitVersion.Common.IRepositoryStore.IsCommitOnBranch(GitVersion.ICommit? baseVersionSource, GitVersion.IBranch! branch, GitVersion.ICommit! firstMatchingCommit) -> bool GitVersion.Configuration.BranchConfiguration GitVersion.Configuration.BranchConfiguration.CommitMessageIncrementing.get -> GitVersion.VersionCalculation.CommitMessageIncrementMode? @@ -750,11 +751,12 @@ GitVersion.RepositoryStore.GetMainlineCommitLog(GitVersion.ICommit? baseVersionS GitVersion.RepositoryStore.GetMergeBaseCommits(GitVersion.ICommit? mergeCommit, GitVersion.ICommit? mergedHead, GitVersion.ICommit? findMergeBase) -> System.Collections.Generic.IEnumerable! GitVersion.RepositoryStore.GetNumberOfUncommittedChanges() -> int GitVersion.RepositoryStore.GetReleaseBranches(System.Collections.Generic.IEnumerable>! releaseBranchConfig) -> System.Collections.Generic.IEnumerable! -GitVersion.RepositoryStore.GetSemanticVersionFromTags(string? tagPrefixRegex, GitVersion.SemanticVersionFormat semanticVersionFormat) -> System.Collections.Generic.IEnumerable! GitVersion.RepositoryStore.GetSourceBranches(GitVersion.IBranch! branch, GitVersion.Configuration.IGitVersionConfiguration! configuration, params GitVersion.IBranch![]! excludedBranches) -> System.Collections.Generic.IEnumerable! GitVersion.RepositoryStore.GetSourceBranches(GitVersion.IBranch! branch, GitVersion.Configuration.IGitVersionConfiguration! configuration, System.Collections.Generic.IEnumerable! excludedBranches) -> System.Collections.Generic.IEnumerable! +GitVersion.RepositoryStore.GetTaggedSemanticVersions(string? labelPrefix, GitVersion.SemanticVersionFormat format) -> System.Collections.Generic.IReadOnlyList! +GitVersion.RepositoryStore.GetTaggedSemanticVersionsOnBranch(GitVersion.IBranch! branch, string? labelPrefix, GitVersion.SemanticVersionFormat format) -> System.Collections.Generic.IReadOnlyList! GitVersion.RepositoryStore.GetTargetBranch(string? targetBranchName) -> GitVersion.IBranch! -GitVersion.RepositoryStore.GetVersionTagsOnBranch(GitVersion.IBranch! branch, string? tagPrefixRegex, GitVersion.SemanticVersionFormat versionFormat) -> System.Collections.Generic.IEnumerable! +GitVersion.RepositoryStore.GetVersionTagsOnBranch(GitVersion.IBranch! branch, string? labelPrefix, GitVersion.SemanticVersionFormat semanticVersionFormat) -> System.Collections.Generic.IEnumerable! GitVersion.RepositoryStore.IsCommitOnBranch(GitVersion.ICommit? baseVersionSource, GitVersion.IBranch! branch, GitVersion.ICommit! firstMatchingCommit) -> bool GitVersion.RepositoryStore.RepositoryStore(GitVersion.Logging.ILog! log, GitVersion.IGitRepository! repository) -> void GitVersion.SemanticVersion @@ -762,9 +764,10 @@ GitVersion.SemanticVersion.BuildMetaData -> GitVersion.SemanticVersionBuildMetaD GitVersion.SemanticVersion.CompareTo(GitVersion.SemanticVersion? value) -> int GitVersion.SemanticVersion.CompareTo(GitVersion.SemanticVersion? value, bool includePrerelease) -> int GitVersion.SemanticVersion.Equals(GitVersion.SemanticVersion? obj) -> bool -GitVersion.SemanticVersion.HasPreReleaseTagWithLabel.get -> bool -GitVersion.SemanticVersion.IncrementVersion(GitVersion.VersionField incrementStrategy) -> GitVersion.SemanticVersion! +GitVersion.SemanticVersion.IncrementVersion(GitVersion.VersionField incrementStrategy, string? label) -> GitVersion.SemanticVersion! GitVersion.SemanticVersion.IsEmpty() -> bool +GitVersion.SemanticVersion.IsLabeledWith(string! value) -> bool +GitVersion.SemanticVersion.IsMatchForBranchSpecificLabel(string? value) -> bool GitVersion.SemanticVersion.Major -> long GitVersion.SemanticVersion.Minor -> long GitVersion.SemanticVersion.Patch -> long @@ -847,12 +850,18 @@ GitVersion.Settings.NoNormalize -> bool GitVersion.Settings.OnlyTrackedBranches -> bool GitVersion.Settings.Settings() -> void GitVersion.VersionCalculation.BaseVersion +GitVersion.VersionCalculation.BaseVersion.BaseVersion(GitVersion.VersionCalculation.BaseVersion! baseVersion) -> void GitVersion.VersionCalculation.BaseVersion.BaseVersion(string! source, bool shouldIncrement, GitVersion.SemanticVersion! semanticVersion, GitVersion.ICommit? baseVersionSource, string? branchNameOverride) -> void GitVersion.VersionCalculation.BaseVersion.BaseVersionSource.get -> GitVersion.ICommit? +GitVersion.VersionCalculation.BaseVersion.BaseVersionSource.init -> void GitVersion.VersionCalculation.BaseVersion.BranchNameOverride.get -> string? +GitVersion.VersionCalculation.BaseVersion.BranchNameOverride.init -> void GitVersion.VersionCalculation.BaseVersion.SemanticVersion.get -> GitVersion.SemanticVersion! +GitVersion.VersionCalculation.BaseVersion.SemanticVersion.init -> void GitVersion.VersionCalculation.BaseVersion.ShouldIncrement.get -> bool +GitVersion.VersionCalculation.BaseVersion.ShouldIncrement.init -> void GitVersion.VersionCalculation.BaseVersion.Source.get -> string! +GitVersion.VersionCalculation.BaseVersion.Source.init -> void GitVersion.VersionCalculation.Caching.GitVersionCache GitVersion.VersionCalculation.Caching.GitVersionCache.GetCacheDirectory() -> string! GitVersion.VersionCalculation.Caching.GitVersionCache.GitVersionCache(GitVersion.IFileSystem! fileSystem, GitVersion.Logging.ILog! log, GitVersion.IGitRepositoryInfo! repositoryInfo) -> void @@ -885,7 +894,7 @@ GitVersion.VersionCalculation.IIncrementStrategyFinder.DetermineIncrementedField GitVersion.VersionCalculation.IIncrementStrategyFinder.GetIncrementForCommits(GitVersion.Configuration.IGitVersionConfiguration! configuration, System.Collections.Generic.IEnumerable! commits) -> GitVersion.VersionField? GitVersion.VersionCalculation.IMainlineVersionCalculator GitVersion.VersionCalculation.IMainlineVersionCalculator.CreateVersionBuildMetaData(GitVersion.ICommit? baseVersionSource) -> GitVersion.SemanticVersionBuildMetaData! -GitVersion.VersionCalculation.IMainlineVersionCalculator.FindMainlineModeVersion(GitVersion.VersionCalculation.BaseVersion! baseVersion) -> GitVersion.SemanticVersion! +GitVersion.VersionCalculation.IMainlineVersionCalculator.FindMainlineModeVersion(GitVersion.VersionCalculation.NextVersion! nextVersion) -> GitVersion.SemanticVersion! GitVersion.VersionCalculation.IncrementStrategyFinder.GetIncrementForCommits(GitVersion.Configuration.IGitVersionConfiguration! configuration, System.Collections.Generic.IEnumerable! commits) -> GitVersion.VersionField? GitVersion.VersionCalculation.INextVersionCalculator GitVersion.VersionCalculation.INextVersionCalculator.FindVersion() -> GitVersion.VersionCalculation.NextVersion! @@ -1076,8 +1085,8 @@ static GitVersion.Configuration.BranchConfigurationBuilder.New.get -> GitVersion static GitVersion.Configuration.ConfigurationExtensions.FindGitDir(this string! path) -> (string! GitDirectory, string! WorkingTreeDirectory)? static GitVersion.Configuration.ConfigurationExtensions.GetBranchConfiguration(this GitVersion.Configuration.IGitVersionConfiguration! configuration, GitVersion.IBranch! branch) -> GitVersion.Configuration.IBranchConfiguration! static GitVersion.Configuration.ConfigurationExtensions.GetBranchConfiguration(this GitVersion.Configuration.IGitVersionConfiguration! configuration, GitVersion.ReferenceName! branchName) -> GitVersion.Configuration.IBranchConfiguration! -static GitVersion.Configuration.ConfigurationExtensions.GetBranchSpecificLabel(this GitVersion.Configuration.EffectiveConfiguration! configuration, GitVersion.Logging.ILog! log, GitVersion.ReferenceName! branchName, string? branchNameOverride) -> string? -static GitVersion.Configuration.ConfigurationExtensions.GetBranchSpecificLabel(this GitVersion.Configuration.EffectiveConfiguration! configuration, GitVersion.Logging.ILog! log, string? branchName, string? branchNameOverride) -> string? +static GitVersion.Configuration.ConfigurationExtensions.GetBranchSpecificLabel(this GitVersion.Configuration.EffectiveConfiguration! configuration, GitVersion.ReferenceName! branchName, string? branchNameOverride) -> string? +static GitVersion.Configuration.ConfigurationExtensions.GetBranchSpecificLabel(this GitVersion.Configuration.EffectiveConfiguration! configuration, string? branchName, string? branchNameOverride) -> string? static GitVersion.Configuration.ConfigurationExtensions.GetEffectiveConfiguration(this GitVersion.Configuration.IGitVersionConfiguration! configuration, GitVersion.IBranch! branch) -> GitVersion.Configuration.EffectiveConfiguration! static GitVersion.Configuration.ConfigurationExtensions.GetFallbackBranchConfiguration(this GitVersion.Configuration.IGitVersionConfiguration! configuration) -> GitVersion.Configuration.IBranchConfiguration! static GitVersion.Configuration.ConfigurationExtensions.GetReleaseBranchConfiguration(this GitVersion.Configuration.IGitVersionConfiguration! configuration) -> System.Collections.Generic.List>! @@ -1199,6 +1208,7 @@ static readonly GitVersion.Helpers.StringComparerUtils.IgnoreCaseComparer -> Sys static readonly GitVersion.Helpers.StringComparerUtils.OsDependentComparer -> System.StringComparer! static readonly GitVersion.Helpers.StringComparerUtils.OsDependentComparison -> System.StringComparison static readonly GitVersion.Logging.Disposable.Empty -> System.IDisposable! +static readonly GitVersion.SemanticVersion.Empty -> GitVersion.SemanticVersion! virtual GitVersion.Agents.BuildAgentBase.CanApplyToCurrentContext() -> bool virtual GitVersion.Agents.BuildAgentBase.GetCurrentBranch(bool usingDynamicRepos) -> string? virtual GitVersion.Agents.BuildAgentBase.IsDefault.get -> bool @@ -1226,4 +1236,3 @@ virtual GitVersion.Configuration.BranchConfigurationBuilder.WithTracksReleaseBra virtual GitVersion.Configuration.BranchConfigurationBuilder.WithVersioningMode(GitVersion.VersionCalculation.VersioningMode? value) -> GitVersion.Configuration.BranchConfigurationBuilder! virtual GitVersion.VersionCalculation.EffectiveBranchConfigurationFinder.GetConfigurations(GitVersion.IBranch! branch, GitVersion.Configuration.IGitVersionConfiguration! configuration) -> System.Collections.Generic.IEnumerable! virtual GitVersion.VersionCalculation.NextVersionCalculator.FindVersion() -> GitVersion.VersionCalculation.NextVersion! -virtual GitVersion.VersionCalculation.TaggedCommitVersionStrategy.FormatSource(GitVersion.SemanticVersionWithTag! semanticVersion) -> string! diff --git a/src/GitVersion.Core/VersionCalculation/Abstractions/IMainlineVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/Abstractions/IMainlineVersionCalculator.cs index 7c230aec39..9001a1cbdf 100644 --- a/src/GitVersion.Core/VersionCalculation/Abstractions/IMainlineVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/Abstractions/IMainlineVersionCalculator.cs @@ -2,6 +2,7 @@ namespace GitVersion.VersionCalculation; public interface IMainlineVersionCalculator { - SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion); + SemanticVersion FindMainlineModeVersion(NextVersion nextVersion); + SemanticVersionBuildMetaData CreateVersionBuildMetaData(ICommit? baseVersionSource); } diff --git a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/BaseVersion.cs b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/BaseVersion.cs index 2c9cfabe3b..be6decd2d9 100644 --- a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/BaseVersion.cs +++ b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/BaseVersion.cs @@ -1,3 +1,5 @@ +using GitVersion.Extensions; + namespace GitVersion.VersionCalculation; public class BaseVersion @@ -11,15 +13,26 @@ public BaseVersion(string source, bool shouldIncrement, SemanticVersion semantic BranchNameOverride = branchNameOverride; } - public string Source { get; } + public BaseVersion(BaseVersion baseVersion) + { + baseVersion.NotNull(); + + Source = baseVersion.Source; + ShouldIncrement = baseVersion.ShouldIncrement; + SemanticVersion = baseVersion.SemanticVersion; + BaseVersionSource = baseVersion.BaseVersionSource; + BranchNameOverride = baseVersion.BranchNameOverride; + } + + public string Source { get; init; } - public bool ShouldIncrement { get; } + public bool ShouldIncrement { get; init; } - public SemanticVersion SemanticVersion { get; } + public SemanticVersion SemanticVersion { get; init; } - public ICommit? BaseVersionSource { get; } + public ICommit? BaseVersionSource { get; init; } - public string? BranchNameOverride { get; } + public string? BranchNameOverride { get; init; } public override string ToString() { diff --git a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs index b00ce20b34..d833285561 100644 --- a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs @@ -9,7 +9,7 @@ namespace GitVersion.VersionCalculation; /// BaseVersionSource is the tag's commit. /// Increments if the tag is not the current commit. /// -public class TaggedCommitVersionStrategy : VersionStrategyBase +public sealed class TaggedCommitVersionStrategy : VersionStrategyBase { private readonly IRepositoryStore repositoryStore; @@ -17,13 +17,7 @@ public TaggedCommitVersionStrategy(IRepositoryStore repositoryStore, Lazy this.repositoryStore = repositoryStore.NotNull(); public override IEnumerable GetBaseVersions(EffectiveBranchConfiguration configuration) - { - var taggedVersions = GetSemanticVersions(configuration) - .Select(versionTaggedCommit => CreateBaseVersion(Context, versionTaggedCommit)) - .ToList(); - var taggedVersionsOnCurrentCommit = taggedVersions.Where(version => !version.ShouldIncrement).ToList(); - return taggedVersionsOnCurrentCommit.Any() ? taggedVersionsOnCurrentCommit : taggedVersions; - } + => GetSemanticVersions(configuration).Select(element => CreateBaseVersion(configuration, element)); private IEnumerable GetSemanticVersions(EffectiveBranchConfiguration configuration) { @@ -31,7 +25,9 @@ private IEnumerable GetSemanticVersions(EffectiveBranchC var olderThan = Context.CurrentCommit?.When; - var semanticVersions = this.repositoryStore.GetSemanticVersionFromTags( + var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null); + + var semanticVersions = this.repositoryStore.GetTaggedSemanticVersions( Context.Configuration.LabelPrefix, Context.Configuration.SemanticVersionFormat ).ToList(); ILookup semanticVersionsByCommit = semanticVersions.ToLookup(element => element.Tag.Commit.Id.Sha); @@ -43,7 +39,7 @@ private IEnumerable GetSemanticVersions(EffectiveBranchC { foreach (var semanticVersion in semanticVersionsByCommit[commit.Id.Sha]) { - if (commit.When <= olderThan) + if (commit.When <= olderThan && semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) { if (alreadyReturnedValues.Add(semanticVersion)) yield return semanticVersion; } @@ -58,7 +54,8 @@ private IEnumerable GetSemanticVersions(EffectiveBranchC if (semanticVersion.Tag.Commit.When > olderThan) continue; var parentCommits = semanticVersion.Tag.Commit.Parents ?? Array.Empty(); - if (parentCommits.Any(element => commitsOnCurrentBranchByCommit.Contains(element.Id.Sha))) + if (parentCommits.Any(element => commitsOnCurrentBranchByCommit.Contains(element.Id.Sha)) + && semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) { if (alreadyReturnedValues.Add(semanticVersion)) yield return semanticVersion; } @@ -68,28 +65,38 @@ private IEnumerable GetSemanticVersions(EffectiveBranchC if (configuration.Value.TracksReleaseBranches) { - var mainBranches = this.repositoryStore.FindMainlineBranches(Context.Configuration); - foreach (var mainBranche in mainBranches) + foreach (var mainBranche in this.repositoryStore.FindMainlineBranches(Context.Configuration)) { - var commitsOnMainBranch = mainBranche.Commits?.ToArray() ?? Array.Empty(); - foreach (var commit in commitsOnMainBranch) + foreach (var commit in mainBranche.Commits?.ToArray() ?? Array.Empty()) { foreach (var semanticVersion in semanticVersionsByCommit[commit.Id.Sha]) { - if (alreadyReturnedValues.Add(semanticVersion)) yield return semanticVersion; + if (semanticVersion.Value.IsMatchForBranchSpecificLabel(label)) + { + if (alreadyReturnedValues.Add(semanticVersion)) yield return semanticVersion; + } } } } } } - private BaseVersion CreateBaseVersion(GitVersionContext context, SemanticVersionWithTag semanticVersion) + private BaseVersion CreateBaseVersion(EffectiveBranchConfiguration configuration, SemanticVersionWithTag semanticVersion) { var tagCommit = semanticVersion.Tag.Commit; - var shouldUpdateVersion = tagCommit.Sha != context.CurrentCommit?.Sha; - var baseVersion = new BaseVersion(FormatSource(semanticVersion), shouldUpdateVersion, semanticVersion.Value, tagCommit, null); - return baseVersion; - } + var shouldUpdateVersion = tagCommit.Sha != Context.CurrentCommit?.Sha; - protected virtual string FormatSource(SemanticVersionWithTag semanticVersion) => $"Git tag '{semanticVersion.Tag.Name.Friendly}'"; + if (!shouldUpdateVersion && !configuration.Value.Label.IsNullOrEmpty() && !semanticVersion.Value.PreReleaseTag.HasTag()) + { + return new BaseVersion( + $"Git tag '{semanticVersion.Tag.Name.Friendly}'", true, semanticVersion.Value, tagCommit, null + ); + } + else + { + return new BaseVersion( + $"Git tag '{semanticVersion.Tag.Name.Friendly}'", shouldUpdateVersion, semanticVersion.Value, tagCommit, null + ); + } + } } diff --git a/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs index 42c1ad714d..226e1311bd 100644 --- a/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs @@ -21,8 +21,10 @@ public MainlineVersionCalculator(ILog log, IRepositoryStore repositoryStore, Laz this.incrementStrategyFinder = incrementStrategyFinder.NotNull(); } - public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion) + public SemanticVersion FindMainlineModeVersion(NextVersion nextVersion) { + var baseVersion = nextVersion.BaseVersion; + if (baseVersion.SemanticVersion.PreReleaseTag.HasTag()) { throw new NotSupportedException("Mainline development mode doesn't yet support pre-release tags on main"); @@ -52,8 +54,7 @@ public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion) var mainlineCommitLog = this.repositoryStore.GetMainlineCommitLog(baseVersion.BaseVersionSource, mainlineTip).ToList(); var directCommits = new List(mainlineCommitLog.Count); - var nextVersion = Context.Configuration.NextVersion; - if (nextVersion.IsNullOrEmpty()) + if (Context.Configuration.NextVersion.IsNullOrEmpty()) { // Scans commit log in reverse, aggregating merge commits foreach (var commit in mainlineCommitLog) @@ -69,17 +70,22 @@ public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion) mainlineVersion = IncrementForEachCommit(directCommits, mainlineVersion, mainline); } - mainlineVersion.BuildMetaData = CreateVersionBuildMetaData(mergeBase); + var baseVersionBuildMetaData = CreateVersionBuildMetaData(mergeBase); // branches other than main always get a bump for the act of branching - if (!Context.CurrentBranch.Equals(mainline) && nextVersion.IsNullOrEmpty()) + if (!Context.CurrentBranch.Equals(mainline) && Context.Configuration.NextVersion.IsNullOrEmpty()) { var branchIncrement = FindMessageIncrement(null, Context.CurrentCommit, mergeBase, mainlineCommitLog); this.log.Info($"Performing {branchIncrement} increment for current branch "); - mainlineVersion = mainlineVersion.IncrementVersion(branchIncrement); + mainlineVersion = mainlineVersion.IncrementVersion(branchIncrement, null); } - return mainlineVersion; + + return new SemanticVersion(mainlineVersion) + { + PreReleaseTag = new SemanticVersionPreReleaseTag(nextVersion.IncrementedVersion.PreReleaseTag), + BuildMetaData = baseVersionBuildMetaData + }; } } @@ -127,14 +133,14 @@ private SemanticVersion AggregateMergeCommitIncrement(ICommit commit, List directCommit { var directCommitIncrement = this.incrementStrategyFinder.GetIncrementForCommits(Context.Configuration, new[] { directCommit }) ?? FindDefaultIncrementForBranch(Context, mainline); - mainlineVersion = mainlineVersion.IncrementVersion(directCommitIncrement); + mainlineVersion = mainlineVersion.IncrementVersion(directCommitIncrement, null); this.log.Info($"Direct commit on main {directCommit} incremented base versions {directCommitIncrement}, now {mainlineVersion}"); } diff --git a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs index 0411eda268..201f537f73 100644 --- a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs @@ -40,78 +40,84 @@ public virtual NextVersion FindVersion() this.log.Info($"Running against branch: {Context.CurrentBranch} ({Context.CurrentCommit?.ToString() ?? "-"})"); if (Context.IsCurrentCommitTagged) { - this.log.Info($"Current commit is tagged with version {Context.CurrentCommitTaggedVersion}, " + "version calculation is for metadata only."); + this.log.Info($"Current commit is tagged with version {Context.CurrentCommitTaggedVersion}, version calculation is for meta data only."); } var nextVersion = Calculate(Context.CurrentBranch, Context.Configuration); - var baseVersion = nextVersion.BaseVersion; - var preReleaseTagName = nextVersion.Configuration.GetBranchSpecificLabel( - this.log, Context.CurrentBranch.Name, baseVersion.BranchNameOverride - ); - SemanticVersion semver; + SemanticVersion semanticVersion; if (nextVersion.Configuration.VersioningMode == VersioningMode.Mainline) { - semver = this.mainlineVersionCalculator.FindMainlineModeVersion(baseVersion); + semanticVersion = this.mainlineVersionCalculator.FindMainlineModeVersion(nextVersion); } else { - var baseVersionBuildMetaData = this.mainlineVersionCalculator.CreateVersionBuildMetaData(baseVersion.BaseVersionSource); + semanticVersion = FindOtherModeVersion(nextVersion); + } - semver = baseVersionBuildMetaData.Sha != nextVersion.IncrementedVersion.BuildMetaData.Sha - ? nextVersion.IncrementedVersion - : baseVersion.SemanticVersion; + if (semanticVersion.CompareTo(Context.CurrentCommitTaggedVersion) == 0) + { + // Will always be 0, don't bother with the +0 on tags + semanticVersion.BuildMetaData.CommitsSinceTag = null; + } - semver.BuildMetaData = baseVersionBuildMetaData; + return new(semanticVersion, nextVersion.BaseVersion, new(nextVersion.Branch, nextVersion.Configuration)); + } - var lastPrefixedSemver = this.repositoryStore - .GetVersionTagsOnBranch(Context.CurrentBranch, Context.Configuration.LabelPrefix, Context.Configuration.SemanticVersionFormat) - .Where(v => MajorMinorPatchEqual(v, semver) && v.PreReleaseTag.HasTag()) - .FirstOrDefault(v => v.PreReleaseTag.Name.IsEquivalentTo(preReleaseTagName)); + private SemanticVersion FindOtherModeVersion(NextVersion nextVersion) + { + //// + // TODO: Please do a refactoring and move the logic from IMainlineVersionCalculator::CreateVersionBuildMetaData to some where else (Reason: Separation of concern violation). + var baseVersionBuildMetaData = this.mainlineVersionCalculator.CreateVersionBuildMetaData( + nextVersion.BaseVersion.BaseVersionSource + ); + // - if (lastPrefixedSemver != null) - { - semver.PreReleaseTag = lastPrefixedSemver.PreReleaseTag; - } - } + var label = nextVersion.Configuration.GetBranchSpecificLabel( + Context.CurrentBranch.Name, nextVersion.BaseVersion.BranchNameOverride + ); + + //// + // TODO: We need to decide whether or not to calculate the upcoming semantic version or the previous one because of tagging. Actually this should be part of the branch configuration system. + var takeIncrementedVersion = baseVersionBuildMetaData.Sha != nextVersion.BaseVersion.BaseVersionSource?.Sha + || Context.CurrentCommitTaggedVersion == null + || !Context.CurrentCommitTaggedVersion.IsMatchForBranchSpecificLabel(label); + // - if (Context.CurrentCommitTaggedVersion is null || Context.CurrentCommitTaggedVersion?.HasPreReleaseTagWithLabel == true) + if (takeIncrementedVersion) { - if (!string.IsNullOrEmpty(preReleaseTagName) - && Context.CurrentCommitTaggedVersion?.PreReleaseTag.Name == preReleaseTagName) + //// + // TODO: We need to consider somehow the IGitVersionConfiguration::Ignore property here!! + var semanticVersionWithTag = this.repositoryStore.GetTaggedSemanticVersionsOnBranch( + nextVersion.Branch, Context.Configuration.LabelPrefix, Context.Configuration.SemanticVersionFormat + ).FirstOrDefault(); + // + + if (semanticVersionWithTag?.Value.CompareTo(nextVersion.IncrementedVersion, false) > 0) { - semver.PreReleaseTag = Context.CurrentCommitTaggedVersion.PreReleaseTag; - } - else if (preReleaseTagName == string.Empty) - { - semver.PreReleaseTag = new SemanticVersionPreReleaseTag(); + return new SemanticVersion(semanticVersionWithTag.Value) + { + PreReleaseTag = new SemanticVersionPreReleaseTag(nextVersion.IncrementedVersion.PreReleaseTag), + BuildMetaData = baseVersionBuildMetaData + }; } - else if (preReleaseTagName != null) + else { - long? number; - if (semver.PreReleaseTag.Name == preReleaseTagName) + return new SemanticVersion(nextVersion.IncrementedVersion) { - number = semver.PreReleaseTag.Number + 1; - } - else - { - number = 1; - } - semver.PreReleaseTag = new SemanticVersionPreReleaseTag(preReleaseTagName, number); + BuildMetaData = baseVersionBuildMetaData + }; } } - - if (semver.CompareTo(Context.CurrentCommitTaggedVersion) == 0) + else { - // Will always be 0, don't bother with the +0 on tags - semver.BuildMetaData.CommitsSinceTag = null; + return new SemanticVersion(nextVersion.BaseVersion.SemanticVersion) + { + BuildMetaData = baseVersionBuildMetaData + }; } - - return new(semver, baseVersion, new(nextVersion.Branch, nextVersion.Configuration)); } - private static bool MajorMinorPatchEqual(SemanticVersion version, SemanticVersion other) => version.CompareTo(other, false) == 0; - private NextVersion Calculate(IBranch branch, IGitVersionConfiguration configuration) { using (log.IndentLog("Calculating the base versions")) @@ -154,11 +160,11 @@ static NextVersion CompareVersions( else { IEnumerable filteredVersions = nextVersions; - if (!maxVersion.IncrementedVersion.HasPreReleaseTagWithLabel) + if (!maxVersion.IncrementedVersion.PreReleaseTag.HasTag()) { // If the maximal version has no pre-release tag defined than we want to determine just the latest previous // base source which are not coming from pre-release tag. - filteredVersions = filteredVersions.Where(v => !v.BaseVersion.SemanticVersion.HasPreReleaseTagWithLabel); + filteredVersions = filteredVersions.Where(v => !v.BaseVersion.SemanticVersion.PreReleaseTag.HasTag()); } var versions = filteredVersions as NextVersion[] ?? filteredVersions.ToArray(); @@ -199,51 +205,68 @@ IEnumerable GetNextVersionsInternal() { var atLeastOneBaseVersionReturned = false; - foreach (var effectiveBranchConfiguration in effectiveBranchConfigurationFinder.GetConfigurations(branch, configuration)) + var effectiveConfigurations = new List(); + foreach (var effectiveConfiguration in effectiveBranchConfigurationFinder.GetConfigurations(branch, configuration)) { foreach (var versionStrategy in this.versionStrategies) { - foreach (var baseVersion in versionStrategy.GetBaseVersions(effectiveBranchConfiguration)) + foreach (var baseVersion in versionStrategy.GetBaseVersions(effectiveConfiguration)) { log.Info(baseVersion.ToString()); + if (IncludeVersion(baseVersion, configuration.Ignore)) { - var incrementedVersion = GetIncrementedVersion(effectiveBranchConfiguration, baseVersion); - if (effectiveBranchConfiguration.Value.VersioningMode == VersioningMode.Mainline - && incrementedVersion.PreReleaseTag.HasTag()) + var label = effectiveConfiguration.Value.GetBranchSpecificLabel( + Context.CurrentBranch.Name, baseVersion.BranchNameOverride + ); + if (effectiveConfiguration.Value.Label != label) + log.Info("Using current branch name to calculate version tag"); + + var incrementedVersion = GetIncrementedVersion(effectiveConfiguration, baseVersion, label); + if (incrementedVersion.IsMatchForBranchSpecificLabel(label)) { - continue; + yield return effectiveConfiguration.CreateNextVersion(baseVersion, incrementedVersion); + atLeastOneBaseVersionReturned = true; } - - yield return effectiveBranchConfiguration.CreateNextVersion(baseVersion, incrementedVersion); - atLeastOneBaseVersionReturned = true; } } } + effectiveConfigurations.Add(effectiveConfiguration); } if (!atLeastOneBaseVersionReturned) { - foreach (var effectiveBranchConfiguration in effectiveBranchConfigurationFinder.GetConfigurations(branch, configuration)) + foreach (var effectiveConfiguration in effectiveConfigurations) { - var baseVersion = new BaseVersion("Fallback base version", true, new SemanticVersion(), null, null); - var incrementedVersion = GetIncrementedVersion(effectiveBranchConfiguration, baseVersion); - yield return effectiveBranchConfiguration.CreateNextVersion(baseVersion, incrementedVersion); + var baseVersion = new BaseVersion("Fallback base version", true, SemanticVersion.Empty, null, null); + + var label = effectiveConfiguration.Value.GetBranchSpecificLabel( + Context.CurrentBranch.Name, baseVersion.BranchNameOverride + ); + if (effectiveConfiguration.Value.Label != label) + log.Info("Using current branch name to calculate version tag"); + + var incrementedVersion = GetIncrementedVersion(effectiveConfiguration, baseVersion, label); + if (incrementedVersion.IsMatchForBranchSpecificLabel(label)) + { + yield return effectiveConfiguration.CreateNextVersion(baseVersion, incrementedVersion); + } } + + if (effectiveConfigurations.Count == 0) + throw new GitVersionException("No base versions determined on the current branch."); } } } - private SemanticVersion GetIncrementedVersion(EffectiveBranchConfiguration effectiveBranchConfiguration, BaseVersion baseVersion) + private SemanticVersion GetIncrementedVersion(EffectiveBranchConfiguration configuration, BaseVersion baseVersion, string? label) { var incrementStrategy = incrementStrategyFinder.DetermineIncrementedField( context: Context, baseVersion: baseVersion, - configuration: effectiveBranchConfiguration.Value + configuration: configuration.Value ); - return incrementStrategy == VersionField.None - ? baseVersion.SemanticVersion - : baseVersion.SemanticVersion.IncrementVersion(incrementStrategy); + return baseVersion.SemanticVersion.IncrementVersion(incrementStrategy, label); } private bool IncludeVersion(BaseVersion baseVersion, IIgnoreConfiguration ignoreConfiguration) diff --git a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs index 90a8fa60e8..c8d6a31201 100644 --- a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs +++ b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs @@ -7,7 +7,7 @@ namespace GitVersion; public class SemanticVersion : IFormattable, IComparable, IEquatable { - private static readonly SemanticVersion Empty = new(); + public static readonly SemanticVersion Empty = new(); // uses the git-semver spec https://github.com/semver/semver/blob/master/semver.md private static readonly Regex ParseSemVerStrict = new( @@ -24,7 +24,10 @@ public class SemanticVersion : IFormattable, IComparable, IEqua public SemanticVersionPreReleaseTag PreReleaseTag; public SemanticVersionBuildMetaData BuildMetaData; - public bool HasPreReleaseTagWithLabel => this.PreReleaseTag.HasTag(); + public bool IsLabeledWith(string value) => PreReleaseTag.HasTag() && PreReleaseTag.Name.IsEquivalentTo(value); + + public bool IsMatchForBranchSpecificLabel(string? value) + => PreReleaseTag.Name == string.Empty || value is null || IsLabeledWith(value); public SemanticVersion(long major = 0, long minor = 0, long patch = 0) { @@ -300,9 +303,10 @@ public string ToString(string? format, IFormatProvider? formatProvider) } } - public SemanticVersion IncrementVersion(VersionField incrementStrategy) + public SemanticVersion IncrementVersion(VersionField incrementStrategy, string? label) { var incremented = new SemanticVersion(this); + if (!incremented.PreReleaseTag.HasTag()) { switch (incrementStrategy) @@ -325,11 +329,17 @@ public SemanticVersion IncrementVersion(VersionField incrementStrategy) throw new ArgumentOutOfRangeException(nameof(incrementStrategy)); } } - else if (incremented.PreReleaseTag.Number != null) + + if (incremented.PreReleaseTag.HasTag() && incremented.PreReleaseTag.Number != null) { incremented.PreReleaseTag.Number++; } + if (!PreReleaseTag.HasTag() && !label.IsNullOrEmpty()) + { + incremented.PreReleaseTag = new SemanticVersionPreReleaseTag(label, 1); + } + return incremented; } } diff --git a/src/GitVersion.Core/VersionCalculation/VariableProvider.cs b/src/GitVersion.Core/VersionCalculation/VariableProvider.cs index 4fc6d1319c..477b920d73 100644 --- a/src/GitVersion.Core/VersionCalculation/VariableProvider.cs +++ b/src/GitVersion.Core/VersionCalculation/VariableProvider.cs @@ -27,7 +27,7 @@ public VersionVariables GetVariablesFor(SemanticVersion semanticVersion, Effecti // Continuous Deployment always requires a pre-release tag unless the commit is tagged if (!semanticVersion.PreReleaseTag.HasTag()) { - var label = configuration.GetBranchSpecificLabel(this.log, semanticVersion.BuildMetaData.Branch, null); + var label = configuration.GetBranchSpecificLabel(semanticVersion.BuildMetaData.Branch, null); semanticVersion.PreReleaseTag.Name = label ?? string.Empty; if (semanticVersion.PreReleaseTag.Name.IsNullOrEmpty()) {