diff --git a/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs index 64c5cd2eb2..288e98dc37 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/ReleaseBranchScenarios.cs @@ -671,4 +671,19 @@ public void FeatureOnReleaseFeatureBranchNotDeleted() fixture.AssertFullSemver("4.5.0-beta.2", configuration); } + + [TestCase("release/1.2.0", "1.2.0-beta.1+1", SemanticVersionFormat.Loose)] + [TestCase("release/1.2.0", "1.2.0-beta.1+1", SemanticVersionFormat.Strict)] + [TestCase("release/1.2", "1.2.0-beta.1+1", SemanticVersionFormat.Loose)] + [TestCase("release/1", "1.0.0-beta.1+1", SemanticVersionFormat.Loose)] + public void ShouldDetectVersionInReleaseBranch(string branchName, string expectedVersion, SemanticVersionFormat semanticVersionFormat) + { + var configuration = GitFlowConfigurationBuilder.New + .WithSemanticVersionFormat(semanticVersionFormat) + .Build(); + + using var fixture = new EmptyRepositoryFixture(branchName); + fixture.MakeACommit(); + fixture.AssertFullSemver(expectedVersion, configuration); + } } diff --git a/src/GitVersion.Core.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs index 6db52ed9f4..539138cd72 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/Strategies/ConfigNextVersionBaseVersionStrategyTests.cs @@ -19,20 +19,32 @@ public void ReturnsNullWhenNoNextVersionIsInConfig() baseVersion.ShouldBe(null); } - [TestCase("1.0.0", "1.0.0")] - [TestCase("2.12.654651698", "2.12.654651698")] - public void ConfigNextVersionTest(string nextVersion, string expectedVersion) + [TestCase("1.0.0", "1.0.0", SemanticVersionFormat.Strict)] + [TestCase("1.0.0", "1.0.0", SemanticVersionFormat.Loose)] + [TestCase("2.12.654651698", "2.12.654651698", SemanticVersionFormat.Strict)] + [TestCase("2.12.654651698", "2.12.654651698", SemanticVersionFormat.Loose)] + [TestCase("0.1", "0.1.0", SemanticVersionFormat.Loose)] + public void ConfigNextVersionTest(string nextVersion, string expectedVersion, SemanticVersionFormat versionFormat) { - var baseVersion = GetBaseVersion(new GitVersionConfiguration - { - NextVersion = nextVersion - }); + var baseVersion = GetBaseVersion(new GitVersionConfiguration { NextVersion = nextVersion, SemanticVersionFormat = versionFormat }); baseVersion.ShouldNotBeNull(); baseVersion.ShouldIncrement.ShouldBe(false); baseVersion.SemanticVersion.ToString().ShouldBe(expectedVersion); } + [TestCase("0.1", SemanticVersionFormat.Strict)] + public void ConfigNextVersionTestShouldFail(string nextVersion, SemanticVersionFormat versionFormat) + => + Should.Throw(() + => GetBaseVersion(new GitVersionConfiguration + { + NextVersion = nextVersion, + SemanticVersionFormat = versionFormat + })) + .Message.ShouldBe($"Failed to parse {nextVersion} into a Semantic Version"); + + private static BaseVersion? GetBaseVersion(GitVersionConfiguration? configuration = null) { var contextBuilder = new GitVersionContextBuilder(); diff --git a/src/GitVersion.Core/Configuration/Init/SetNextVersion.cs b/src/GitVersion.Core/Configuration/Init/SetNextVersion.cs index 979dadc236..620dd6b4f1 100644 --- a/src/GitVersion.Core/Configuration/Init/SetNextVersion.cs +++ b/src/GitVersion.Core/Configuration/Init/SetNextVersion.cs @@ -19,7 +19,7 @@ protected override StepResult HandleResult(string? result, Queue GetSourceBranches(IBranch branch, GitVersionConfiguration configuration, IEnumerable excludedBranches); - SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, bool handleDetachedBranch); + SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, SemanticVersionFormat versionFormat, bool handleDetachedBranch); - IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex); - IEnumerable<(ITag Tag, SemanticVersion Semver, ICommit Commit)> GetValidVersionTags(string? tagPrefixRegex, DateTimeOffset? olderThan = null); + IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex, SemanticVersionFormat versionFormat); + IEnumerable<(ITag Tag, SemanticVersion Semver, ICommit Commit)> GetValidVersionTags(string? tagPrefixRegex, SemanticVersionFormat versionFormat, DateTimeOffset? olderThan = null); bool IsCommitOnBranch(ICommit? baseVersionSource, IBranch branch, ICommit firstMatchingCommit); diff --git a/src/GitVersion.Core/Core/GitVersionContextFactory.cs b/src/GitVersion.Core/Core/GitVersionContextFactory.cs index 22c6469b02..543e67d3f1 100644 --- a/src/GitVersion.Core/Core/GitVersionContextFactory.cs +++ b/src/GitVersion.Core/Core/GitVersionContextFactory.cs @@ -33,7 +33,7 @@ public GitVersionContext Create(GitVersionOptions gitVersionOptions) currentBranch = branchForCommit ?? currentBranch; } - var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration.LabelPrefix, handleDetachedBranch: currentBranch.IsDetachedHead); + var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration.LabelPrefix, configuration.SemanticVersionFormat, handleDetachedBranch: currentBranch.IsDetachedHead); var numberOfUncommittedChanges = this.repositoryStore.GetNumberOfUncommittedChanges(); return new GitVersionContext(currentBranch, currentCommit, configuration, currentCommitTaggedVersion, numberOfUncommittedChanges); diff --git a/src/GitVersion.Core/Core/RepositoryStore.cs b/src/GitVersion.Core/Core/RepositoryStore.cs index 63b373c284..4e5fa2a062 100644 --- a/src/GitVersion.Core/Core/RepositoryStore.cs +++ b/src/GitVersion.Core/Core/RepositoryStore.cs @@ -219,24 +219,24 @@ public IEnumerable FindCommitBranchesWasBranchedFrom(IBranch branc } } - public SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, bool handleDetachedBranch) + public SemanticVersion? GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, SemanticVersionFormat versionFormat, bool handleDetachedBranch) => this.repository.Tags - .SelectMany(t => GetCurrentCommitSemanticVersions(commit, tagPrefix, t, handleDetachedBranch)) + .SelectMany(tag => GetCurrentCommitSemanticVersions(commit, tagPrefix, tag, versionFormat, handleDetachedBranch)) .Max(); - public IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex) + public IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex, SemanticVersionFormat versionFormat) { branch = branch.NotNull(); - if (this.semanticVersionTagsOnBranchCache.ContainsKey(branch)) + if (this.semanticVersionTagsOnBranchCache.TryGetValue(branch, out var onBranch)) { this.log.Debug($"Cache hit for version tags on branch '{branch.Name.Canonical}"); - return this.semanticVersionTagsOnBranchCache[branch]; + return onBranch; } using (this.log.IndentLog($"Getting version tags from branch '{branch.Name.Canonical}'.")) { - var tags = GetValidVersionTags(tagPrefixRegex); + var tags = GetValidVersionTags(tagPrefixRegex, versionFormat); var tagsBySha = tags.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.Semver)) ?? Enumerable.Empty()).ToList(); @@ -246,13 +246,13 @@ public IEnumerable GetVersionTagsOnBranch(IBranch branch, strin } } - public IEnumerable<(ITag Tag, SemanticVersion Semver, ICommit Commit)> GetValidVersionTags(string? tagPrefixRegex, DateTimeOffset? olderThan = null) + public IEnumerable<(ITag Tag, SemanticVersion Semver, ICommit Commit)> GetValidVersionTags(string? tagPrefixRegex, SemanticVersionFormat versionFormat, DateTimeOffset? olderThan = null) { var tags = new List<(ITag, SemanticVersion, ICommit)>(); foreach (var tag in this.repository.Tags) { - if (!SemanticVersion.TryParse(tag.Name.Friendly, tagPrefixRegex, out var semver)) + if (!SemanticVersion.TryParse(tag.Name.Friendly, tagPrefixRegex, out var semver, versionFormat)) continue; var commit = tag.PeeledTargetCommit(); @@ -290,7 +290,7 @@ public bool IsCommitOnBranch(ICommit? baseVersionSource, IBranch branch, ICommit private static bool IsReleaseBranch(INamedReference branch, IEnumerable> releaseBranchConfig) => releaseBranchConfig.Any(c => c.Value?.Regex != null && Regex.IsMatch(branch.Name.Friendly, c.Value.Regex)); - private IEnumerable GetCurrentCommitSemanticVersions(ICommit? commit, string? tagPrefix, ITag tag, bool handleDetachedBranch) + private IEnumerable GetCurrentCommitSemanticVersions(ICommit? commit, string? tagPrefix, ITag tag, SemanticVersionFormat versionFormat, bool handleDetachedBranch) { if (commit == null) return Array.Empty(); @@ -303,7 +303,7 @@ private IEnumerable GetCurrentCommitSemanticVersions(ICommit? c var tagName = tag.Name.Friendly; - return Equals(targetCommit, commitToCompare) && SemanticVersion.TryParse(tagName, tagPrefix, out var version) + return Equals(targetCommit, commitToCompare) && SemanticVersion.TryParse(tagName, tagPrefix, out var version, versionFormat) ? new[] { version } : Array.Empty(); } diff --git a/src/GitVersion.Core/MergeMessage.cs b/src/GitVersion.Core/MergeMessage.cs index 51be088bad..4068f5ff11 100644 --- a/src/GitVersion.Core/MergeMessage.cs +++ b/src/GitVersion.Core/MergeMessage.cs @@ -29,25 +29,25 @@ public MergeMessage(string? mergeMessage, GitVersionConfiguration configuration) foreach (var format in allFormats) { var match = format.Pattern.Match(mergeMessage); - if (match.Success) - { - FormatName = format.Name; - MergedBranch = match.Groups["SourceBranch"].Value; - - if (match.Groups["TargetBranch"].Success) - { - TargetBranch = match.Groups["TargetBranch"].Value; - } + if (!match.Success) + continue; - if (int.TryParse(match.Groups["PullRequestNumber"].Value, out var pullNumber)) - { - PullRequestNumber = pullNumber; - } + FormatName = format.Name; + MergedBranch = match.Groups["SourceBranch"].Value; - Version = ParseVersion(configuration.LabelPrefix); + if (match.Groups["TargetBranch"].Success) + { + TargetBranch = match.Groups["TargetBranch"].Value; + } - break; + if (int.TryParse(match.Groups["PullRequestNumber"].Value, out var pullNumber)) + { + PullRequestNumber = pullNumber; } + + Version = ParseVersion(configuration.LabelPrefix, configuration.SemanticVersionFormat); + + break; } } @@ -58,7 +58,7 @@ public MergeMessage(string? mergeMessage, GitVersionConfiguration configuration) public int? PullRequestNumber { get; } public SemanticVersion? Version { get; } - private SemanticVersion? ParseVersion(string? tagPrefix) + private SemanticVersion? ParseVersion(string? tagPrefix, SemanticVersionFormat versionFormat) { if (tagPrefix is null) return null; @@ -69,7 +69,7 @@ public MergeMessage(string? mergeMessage, GitVersionConfiguration configuration) var versionMatch = new Regex(@"^(? versionContext) public override IEnumerable GetBaseVersions(EffectiveBranchConfiguration configuration) { - var nextVersion = Context.Configuration.NextVersion; + var contextConfiguration = Context.Configuration; + var nextVersion = contextConfiguration.NextVersion; if (!nextVersion.IsNullOrEmpty() && !Context.IsCurrentCommitTagged) { - var semanticVersion = SemanticVersion.Parse(nextVersion, Context.Configuration.LabelPrefix); + var semanticVersion = SemanticVersion.Parse(nextVersion, contextConfiguration.LabelPrefix, contextConfiguration.SemanticVersionFormat); yield return new BaseVersion("NextVersion in GitVersion configuration file", false, semanticVersion, null, null); } } diff --git a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs index cf19efda8a..1d431f0c3d 100644 --- a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/TaggedCommitVersionStrategy.cs @@ -23,14 +23,14 @@ internal IEnumerable GetTaggedVersions(IBranch currentBranch, DateT { if (currentBranch is null) return Enumerable.Empty(); - var versionTags = this.repositoryStore.GetValidVersionTags(Context.Configuration.LabelPrefix, olderThan); - var versionTagsByCommit = versionTags.ToLookup(vt => vt.Item3.Id.Sha); + var versionTags = this.repositoryStore.GetValidVersionTags(Context.Configuration.LabelPrefix, Context.Configuration.SemanticVersionFormat, olderThan); + var versionTagsByCommit = versionTags.ToLookup(vt => vt.Commit.Id.Sha); var commitsOnBranch = currentBranch.Commits; if (commitsOnBranch == null) return Enumerable.Empty(); var versionTagsOnBranch = commitsOnBranch.SelectMany(commit => versionTagsByCommit[commit.Id.Sha]); - var versionTaggedCommits = versionTagsOnBranch.Select(t => new VersionTaggedCommit(t.Item3, t.Item2, t.Item1.Name.Friendly)); + var versionTaggedCommits = versionTagsOnBranch.Select(t => new VersionTaggedCommit(t.Commit, t.Semver, t.Tag.Name.Friendly)); var taggedVersions = versionTaggedCommits.Select(versionTaggedCommit => CreateBaseVersion(Context, versionTaggedCommit)).ToList(); var taggedVersionsOnCurrentCommit = taggedVersions.Where(version => !version.ShouldIncrement).ToList(); return taggedVersionsOnCurrentCommit.Any() ? taggedVersionsOnCurrentCommit : taggedVersions; diff --git a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/VersionInBranchNameVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/VersionInBranchNameVersionStrategy.cs index f6d9f920e6..de9c7147ed 100644 --- a/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/VersionInBranchNameVersionStrategy.cs +++ b/src/GitVersion.Core/VersionCalculation/BaseVersionCalculators/VersionInBranchNameVersionStrategy.cs @@ -19,24 +19,25 @@ public VersionInBranchNameVersionStrategy(IRepositoryStore repositoryStore, Lazy public override IEnumerable GetBaseVersions(EffectiveBranchConfiguration configuration) { string nameWithoutOrigin = NameWithoutOrigin(configuration.Branch); - if (Context.Configuration.IsReleaseBranch(nameWithoutOrigin)) + var contextConfiguration = Context.Configuration; + if (contextConfiguration.IsReleaseBranch(nameWithoutOrigin)) { - var versionInBranch = GetVersionInBranch(configuration.Branch.Name.Friendly, Context.Configuration.LabelPrefix); + var versionInBranch = GetVersionInBranch(configuration.Branch.Name.Friendly, contextConfiguration.LabelPrefix, contextConfiguration.SemanticVersionFormat); if (versionInBranch != null) { - var commitBranchWasBranchedFrom = this.repositoryStore.FindCommitBranchWasBranchedFrom(configuration.Branch, Context.Configuration); + var commitBranchWasBranchedFrom = this.repositoryStore.FindCommitBranchWasBranchedFrom(configuration.Branch, contextConfiguration); var branchNameOverride = Context.CurrentBranch.Name.Friendly.RegexReplace("[-/]" + versionInBranch.Item1, string.Empty); yield return new BaseVersion("Version in branch name", false, versionInBranch.Item2, commitBranchWasBranchedFrom.Commit, branchNameOverride); } } } - private static Tuple? GetVersionInBranch(string branchName, string? tagPrefixRegex) + private static Tuple? GetVersionInBranch(string branchName, string? tagPrefixRegex, SemanticVersionFormat versionFormat) { var branchParts = branchName.Split('/', '-'); foreach (var part in branchParts) { - if (SemanticVersion.TryParse(part, tagPrefixRegex, out var semanticVersion)) + if (SemanticVersion.TryParse(part, tagPrefixRegex, out var semanticVersion, versionFormat)) { return Tuple.Create(part, semanticVersion); } diff --git a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs index f846586bad..cd418552cc 100644 --- a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs @@ -130,7 +130,7 @@ private void UpdatePreReleaseTag(EffectiveBranchConfiguration configuration, Sem // TODO: Please update the pre release-tag in the IVersionStrategy implementation. var lastTag = this.repositoryStore - .GetVersionTagsOnBranch(Context.CurrentBranch, Context.Configuration.LabelPrefix) + .GetVersionTagsOnBranch(Context.CurrentBranch, Context.Configuration.LabelPrefix, Context.Configuration.SemanticVersionFormat) .FirstOrDefault(v => v.PreReleaseTag?.Name?.IsEquivalentTo(tagToUse) == true); if (lastTag != null && MajorMinorPatchEqual(lastTag, semanticVersion) && lastTag.HasPreReleaseTagWithLabel) diff --git a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs index 5045e8afec..91dd146914 100644 --- a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs +++ b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs @@ -133,9 +133,9 @@ public override int GetHashCode() return v1.CompareTo(v2) < 0; } - public static SemanticVersion Parse(string version, string? tagPrefixRegex, SemanticVersionFormat format = SemanticVersionFormat.Strict) + public static SemanticVersion Parse(string version, string? tagPrefixRegex, SemanticVersionFormat versionFormat = SemanticVersionFormat.Strict) { - if (!TryParse(version, tagPrefixRegex, out var semanticVersion, format)) + if (!TryParse(version, tagPrefixRegex, out var semanticVersion, versionFormat)) throw new WarningException($"Failed to parse {version} into a Semantic Version"); return semanticVersion;