From 9b197506d475f106415e0b08b0b3b180d947e92b Mon Sep 17 00:00:00 2001 From: Alexander Pykavy Date: Fri, 6 Jan 2023 16:31:20 +0100 Subject: [PATCH] Change SemanticVersion's PreReleaseTag and BuildMetaData to a non-nullable type Because they are always set in SemanticVersion's constructor. They can be null only if explicitly set by the client of the class and there are plans to forbid this functionality. --- .../SemanticVersionTests.cs | 2 - .../VersionCalculation/VersionSourceTests.cs | 3 -- .../AssemblyVersionsGeneratorExtensions.cs | 4 +- .../MainlineVersionCalculator.cs | 2 +- .../NextVersionCalculator.cs | 10 ++--- .../SemanticVersioning/SemanticVersion.cs | 20 ++++----- .../SemanticVersionFormatValues.cs | 28 ++++++------- .../VersionCalculation/VariableProvider.cs | 41 +++++++++---------- 8 files changed, 51 insertions(+), 59 deletions(-) diff --git a/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs index 61abe024ed..ed00bbd4b7 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs @@ -51,11 +51,9 @@ public void ValidateVersionParsing( Assert.AreEqual(major, version.Major); Assert.AreEqual(minor, version.Minor); Assert.AreEqual(patch, version.Patch); - version.PreReleaseTag.ShouldNotBeNull(); Assert.AreEqual(tag, version.PreReleaseTag.Name); Assert.AreEqual(tagNumber, version.PreReleaseTag.Number); - version.BuildMetaData.ShouldNotBeNull(); Assert.AreEqual(numberOfBuilds, version.BuildMetaData.CommitsSinceTag); Assert.AreEqual(branchName, version.BuildMetaData.Branch); Assert.AreEqual(sha, version.BuildMetaData.Sha); diff --git a/src/GitVersion.Core.Tests/VersionCalculation/VersionSourceTests.cs b/src/GitVersion.Core.Tests/VersionCalculation/VersionSourceTests.cs index f9edfaf6e3..6fc2e508c9 100644 --- a/src/GitVersion.Core.Tests/VersionCalculation/VersionSourceTests.cs +++ b/src/GitVersion.Core.Tests/VersionCalculation/VersionSourceTests.cs @@ -26,7 +26,6 @@ public void VersionSourceSha() var nextVersion = nextVersionCalculator.FindVersion(); - nextVersion.IncrementedVersion.BuildMetaData.ShouldNotBeNull(); nextVersion.IncrementedVersion.BuildMetaData.VersionSourceSha.ShouldBeNull(); nextVersion.IncrementedVersion.BuildMetaData.CommitsSinceVersionSource.ShouldBe(3); } @@ -41,7 +40,6 @@ public void VersionSourceShaOneCommit() var nextVersion = nextVersionCalculator.FindVersion(); - nextVersion.IncrementedVersion.BuildMetaData.ShouldNotBeNull(); nextVersion.IncrementedVersion.BuildMetaData.VersionSourceSha.ShouldBeNull(); nextVersion.IncrementedVersion.BuildMetaData.CommitsSinceVersionSource.ShouldBe(1); } @@ -62,7 +60,6 @@ public void VersionSourceShaUsingTag() var nextVersion = nextVersionCalculator.FindVersion(); - nextVersion.IncrementedVersion.BuildMetaData.ShouldNotBeNull(); nextVersion.IncrementedVersion.BuildMetaData.VersionSourceSha.ShouldBe(secondCommit.Sha); nextVersion.IncrementedVersion.BuildMetaData.CommitsSinceVersionSource.ShouldBe(1); } diff --git a/src/GitVersion.Core/Extensions/AssemblyVersionsGeneratorExtensions.cs b/src/GitVersion.Core/Extensions/AssemblyVersionsGeneratorExtensions.cs index 8f9a7486ae..1ef7f96637 100644 --- a/src/GitVersion.Core/Extensions/AssemblyVersionsGeneratorExtensions.cs +++ b/src/GitVersion.Core/Extensions/AssemblyVersionsGeneratorExtensions.cs @@ -8,7 +8,7 @@ public static class AssemblyVersionsGeneratorExtensions AssemblyVersioningScheme.Major => $"{sv.Major}.0.0.0", AssemblyVersioningScheme.MajorMinor => $"{sv.Major}.{sv.Minor}.0.0", AssemblyVersioningScheme.MajorMinorPatch => $"{sv.Major}.{sv.Minor}.{sv.Patch}.0", - AssemblyVersioningScheme.MajorMinorPatchTag => $"{sv.Major}.{sv.Minor}.{sv.Patch}.{sv.PreReleaseTag?.Number ?? 0}", + AssemblyVersioningScheme.MajorMinorPatchTag => $"{sv.Major}.{sv.Minor}.{sv.Patch}.{sv.PreReleaseTag.Number ?? 0}", AssemblyVersioningScheme.None => null, _ => throw new ArgumentException($"Unexpected value ({scheme}).", nameof(scheme)) }; @@ -19,7 +19,7 @@ public static class AssemblyVersionsGeneratorExtensions AssemblyFileVersioningScheme.Major => $"{sv.Major}.0.0.0", AssemblyFileVersioningScheme.MajorMinor => $"{sv.Major}.{sv.Minor}.0.0", AssemblyFileVersioningScheme.MajorMinorPatch => $"{sv.Major}.{sv.Minor}.{sv.Patch}.0", - AssemblyFileVersioningScheme.MajorMinorPatchTag => $"{sv.Major}.{sv.Minor}.{sv.Patch}.{sv.PreReleaseTag?.Number ?? 0}", + AssemblyFileVersioningScheme.MajorMinorPatchTag => $"{sv.Major}.{sv.Minor}.{sv.Patch}.{sv.PreReleaseTag.Number ?? 0}", AssemblyFileVersioningScheme.None => null, _ => throw new ArgumentException($"Unexpected value ({scheme}).", nameof(scheme)) }; diff --git a/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs index 237a1d48e0..e177b90732 100644 --- a/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/MainlineVersionCalculator.cs @@ -23,7 +23,7 @@ public MainlineVersionCalculator(ILog log, IRepositoryStore repositoryStore, Laz public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion) { - if (baseVersion.SemanticVersion.PreReleaseTag?.HasTag() == true) + if (baseVersion.SemanticVersion.PreReleaseTag.HasTag() == true) { throw new NotSupportedException("Mainline development mode doesn't yet support pre-release tags on main"); } diff --git a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs index 81cbd2a7f3..0a6d9a4d7d 100644 --- a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs @@ -60,7 +60,7 @@ public virtual NextVersion FindVersion() { var baseVersionBuildMetaData = this.mainlineVersionCalculator.CreateVersionBuildMetaData(baseVersion.BaseVersionSource); - if (baseVersionBuildMetaData.Sha != nextVersion.IncrementedVersion.BuildMetaData?.Sha) + if (baseVersionBuildMetaData.Sha != nextVersion.IncrementedVersion.BuildMetaData.Sha) { semver = nextVersion.IncrementedVersion; } @@ -73,8 +73,8 @@ public virtual NextVersion FindVersion() var lastPrefixedSemver = this.repositoryStore .GetVersionTagsOnBranch(Context.CurrentBranch, Context.Configuration.LabelPrefix) - .Where(v => MajorMinorPatchEqual(v, semver) && v.PreReleaseTag?.HasTag() == true) - .FirstOrDefault(v => v.PreReleaseTag?.Name?.IsEquivalentTo(preReleaseTagName) == true); + .Where(v => MajorMinorPatchEqual(v, semver) && v.PreReleaseTag.HasTag() == true) + .FirstOrDefault(v => v.PreReleaseTag.Name?.IsEquivalentTo(preReleaseTagName) == true); if (lastPrefixedSemver != null) { @@ -95,7 +95,7 @@ public virtual NextVersion FindVersion() { long? number; - if (semver.PreReleaseTag?.Name == preReleaseTagName) + if (semver.PreReleaseTag.Name == preReleaseTagName) { number = semver.PreReleaseTag.Number + 1; } @@ -227,7 +227,7 @@ private IEnumerable GetNextVersions(IBranch branch, GitVersionConfi if (configuration.VersioningMode == VersioningMode.Mainline) { - if (!(incrementedVersion.PreReleaseTag?.HasTag() != true)) + if (!(incrementedVersion.PreReleaseTag.HasTag() != true)) { continue; } diff --git a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs index 5045e8afec..d1d8c57275 100644 --- a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs +++ b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersion.cs @@ -21,10 +21,10 @@ public class SemanticVersion : IFormattable, IComparable, IEqua public long Major; public long Minor; public long Patch; - public SemanticVersionPreReleaseTag? PreReleaseTag; - public SemanticVersionBuildMetaData? BuildMetaData; + public SemanticVersionPreReleaseTag PreReleaseTag; + public SemanticVersionBuildMetaData BuildMetaData; - public bool HasPreReleaseTagWithLabel => PreReleaseTag?.HasTag() == true; + public bool HasPreReleaseTagWithLabel => PreReleaseTag.HasTag() == true; public SemanticVersion(long major = 0, long minor = 0, long patch = 0) { @@ -76,8 +76,8 @@ public override int GetHashCode() var hashCode = this.Major.GetHashCode(); hashCode = (hashCode * 397) ^ this.Minor.GetHashCode(); hashCode = (hashCode * 397) ^ this.Patch.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.PreReleaseTag != null ? this.PreReleaseTag.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (this.BuildMetaData != null ? this.BuildMetaData.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ this.PreReleaseTag.GetHashCode(); + hashCode = (hashCode * 397) ^ this.BuildMetaData.GetHashCode(); return hashCode; } } @@ -278,18 +278,18 @@ public string ToString(string? format, IFormatProvider? formatProvider) case "j": return $"{this.Major}.{this.Minor}.{this.Patch}"; case "s": - return this.PreReleaseTag?.HasTag() == true ? $"{ToString("j")}-{this.PreReleaseTag}" : ToString("j"); + return this.PreReleaseTag.HasTag() == true ? $"{ToString("j")}-{this.PreReleaseTag}" : ToString("j"); case "t": - return this.PreReleaseTag?.HasTag() == true ? $"{ToString("j")}-{this.PreReleaseTag.ToString("t")}" : ToString("j"); + return this.PreReleaseTag.HasTag() == true ? $"{ToString("j")}-{this.PreReleaseTag.ToString("t")}" : ToString("j"); case "f": { - var buildMetadata = this.BuildMetaData?.ToString(); + var buildMetadata = this.BuildMetaData.ToString(); return !buildMetadata.IsNullOrEmpty() ? $"{ToString("s")}+{buildMetadata}" : ToString("s"); } case "i": { - var buildMetadata = this.BuildMetaData?.ToString("f"); + var buildMetadata = this.BuildMetaData.ToString("f"); return !buildMetadata.IsNullOrEmpty() ? $"{ToString("s")}+{buildMetadata}" : ToString("s"); } @@ -301,7 +301,7 @@ public string ToString(string? format, IFormatProvider? formatProvider) public SemanticVersion IncrementVersion(VersionField incrementStrategy) { var incremented = new SemanticVersion(this); - if (incremented.PreReleaseTag?.HasTag() != true) + if (incremented.PreReleaseTag.HasTag() != true) { switch (incrementStrategy) { diff --git a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersionFormatValues.cs b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersionFormatValues.cs index f6385088c6..e451ead9f3 100644 --- a/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersionFormatValues.cs +++ b/src/GitVersion.Core/VersionCalculation/SemanticVersioning/SemanticVersionFormatValues.cs @@ -23,19 +23,19 @@ public SemanticVersionFormatValues(SemanticVersion semver, EffectiveConfiguratio public string? PreReleaseTag => this.semver.PreReleaseTag; - public string? PreReleaseTagWithDash => this.semver.PreReleaseTag?.HasTag() == true ? "-" + this.semver.PreReleaseTag : null; + public string? PreReleaseTagWithDash => this.semver.PreReleaseTag.HasTag() == true ? "-" + this.semver.PreReleaseTag : null; - public string? PreReleaseLabel => this.semver.PreReleaseTag?.HasTag() == true ? this.semver.PreReleaseTag.Name : null; + public string? PreReleaseLabel => this.semver.PreReleaseTag.HasTag() == true ? this.semver.PreReleaseTag.Name : null; - public string? PreReleaseLabelWithDash => this.semver.PreReleaseTag?.HasTag() == true ? "-" + this.semver.PreReleaseTag.Name : null; + public string? PreReleaseLabelWithDash => this.semver.PreReleaseTag.HasTag() == true ? "-" + this.semver.PreReleaseTag.Name : null; - public string? PreReleaseNumber => this.semver.PreReleaseTag?.HasTag() == true ? this.semver.PreReleaseTag.Number.ToString() : null; + public string? PreReleaseNumber => this.semver.PreReleaseTag.HasTag() == true ? this.semver.PreReleaseTag.Number.ToString() : null; public string WeightedPreReleaseNumber => GetWeightedPreReleaseNumber(); public string? BuildMetaData => this.semver.BuildMetaData; - public string? FullBuildMetaData => this.semver.BuildMetaData?.ToString("f"); + public string? FullBuildMetaData => this.semver.BuildMetaData.ToString("f"); public string MajorMinorPatch => $"{this.semver.Major}.{this.semver.Minor}.{this.semver.Patch}"; @@ -47,28 +47,28 @@ public SemanticVersionFormatValues(SemanticVersion semver, EffectiveConfiguratio public string FullSemVer => this.semver.ToString("f"); - public string? BranchName => this.semver.BuildMetaData?.Branch; + public string? BranchName => this.semver.BuildMetaData.Branch; - public string? EscapedBranchName => this.semver.BuildMetaData?.Branch?.RegexReplace("[^a-zA-Z0-9-]", "-"); + public string? EscapedBranchName => this.semver.BuildMetaData.Branch?.RegexReplace("[^a-zA-Z0-9-]", "-"); - public string? Sha => this.semver.BuildMetaData?.Sha; + public string? Sha => this.semver.BuildMetaData.Sha; - public string? ShortSha => this.semver.BuildMetaData?.ShortSha; + public string? ShortSha => this.semver.BuildMetaData.ShortSha; - public string? CommitDate => this.semver.BuildMetaData?.CommitDate?.UtcDateTime.ToString(this.configuration.CommitDateFormat, CultureInfo.InvariantCulture); + public string? CommitDate => this.semver.BuildMetaData.CommitDate?.UtcDateTime.ToString(this.configuration.CommitDateFormat, CultureInfo.InvariantCulture); public string InformationalVersion => this.semver.ToString("i"); - public string? VersionSourceSha => this.semver.BuildMetaData?.VersionSourceSha; + public string? VersionSourceSha => this.semver.BuildMetaData.VersionSourceSha; - public string? CommitsSinceVersionSource => this.semver.BuildMetaData?.CommitsSinceVersionSource?.ToString(CultureInfo.InvariantCulture); + public string? CommitsSinceVersionSource => this.semver.BuildMetaData.CommitsSinceVersionSource?.ToString(CultureInfo.InvariantCulture); - public string? UncommittedChanges => this.semver.BuildMetaData?.UncommittedChanges.ToString(CultureInfo.InvariantCulture); + public string? UncommittedChanges => this.semver.BuildMetaData.UncommittedChanges.ToString(CultureInfo.InvariantCulture); private string GetWeightedPreReleaseNumber() { var weightedPreReleaseNumber = - this.semver.PreReleaseTag?.HasTag() == true ? (this.semver.PreReleaseTag.Number + this.configuration.PreReleaseWeight).ToString() : null; + this.semver.PreReleaseTag.HasTag() == true ? (this.semver.PreReleaseTag.Number + this.configuration.PreReleaseWeight).ToString() : null; return weightedPreReleaseNumber.IsNullOrEmpty() ? $"{this.configuration.LabelPreReleaseWeight}" diff --git a/src/GitVersion.Core/VersionCalculation/VariableProvider.cs b/src/GitVersion.Core/VersionCalculation/VariableProvider.cs index b7e645501d..3057da61bb 100644 --- a/src/GitVersion.Core/VersionCalculation/VariableProvider.cs +++ b/src/GitVersion.Core/VersionCalculation/VariableProvider.cs @@ -25,9 +25,9 @@ public VersionVariables GetVariablesFor(SemanticVersion semanticVersion, Effecti { semanticVersion = new SemanticVersion(semanticVersion); // Continuous Deployment always requires a pre-release tag unless the commit is tagged - if (semanticVersion.PreReleaseTag != null && semanticVersion.PreReleaseTag.HasTag() != true) + if (semanticVersion.PreReleaseTag.HasTag() != true) { - semanticVersion.PreReleaseTag.Name = configuration.GetBranchSpecificTag(this.log, semanticVersion.BuildMetaData?.Branch, null); + semanticVersion.PreReleaseTag.Name = configuration.GetBranchSpecificTag(this.log, semanticVersion.BuildMetaData.Branch, null); if (semanticVersion.PreReleaseTag.Name.IsNullOrEmpty()) { // TODO: Why do we manipulating the semantic version here in the VariableProvider? The method name is GET not MANIPULATE. @@ -38,14 +38,14 @@ public VersionVariables GetVariablesFor(SemanticVersion semanticVersion, Effecti } // Evaluate tag number pattern and append to prerelease tag, preserving build metadata - var appendTagNumberPattern = !configuration.LabelNumberPattern.IsNullOrEmpty() && semanticVersion.PreReleaseTag?.HasTag() == true; + var appendTagNumberPattern = !configuration.LabelNumberPattern.IsNullOrEmpty() && semanticVersion.PreReleaseTag.HasTag() == true; if (appendTagNumberPattern) { - if (semanticVersion.BuildMetaData?.Branch != null && configuration.LabelNumberPattern != null) + if (semanticVersion.BuildMetaData.Branch != null && configuration.LabelNumberPattern != null) { var match = Regex.Match(semanticVersion.BuildMetaData.Branch, configuration.LabelNumberPattern); var numberGroup = match.Groups["number"]; - if (numberGroup.Success && semanticVersion.PreReleaseTag != null) + if (numberGroup.Success) { // TODO: Why do we manipulating the semantic version here in the VariableProvider? The method name is GET not MANIPULATE. // What is about the separation of concern and single-responsibility principle? @@ -101,29 +101,26 @@ public VersionVariables GetVariablesFor(SemanticVersion semanticVersion, Effecti private static void PromoteNumberOfCommitsToTagNumber(SemanticVersion semanticVersion) { - if (semanticVersion.PreReleaseTag != null && semanticVersion.BuildMetaData != null) + // For continuous deployment the commits since tag gets promoted to the pre-release number + if (!semanticVersion.BuildMetaData.CommitsSinceTag.HasValue) { - // For continuous deployment the commits since tag gets promoted to the pre-release number - if (!semanticVersion.BuildMetaData.CommitsSinceTag.HasValue) + semanticVersion.PreReleaseTag.Number = null; + semanticVersion.BuildMetaData.CommitsSinceVersionSource = 0; + } + else + { + // Number of commits since last tag should be added to PreRelease number if given. Remember to deduct automatic version bump. + if (semanticVersion.PreReleaseTag.Number.HasValue) { - semanticVersion.PreReleaseTag.Number = null; - semanticVersion.BuildMetaData.CommitsSinceVersionSource = 0; + semanticVersion.PreReleaseTag.Number += semanticVersion.BuildMetaData.CommitsSinceTag - 1; } else { - // Number of commits since last tag should be added to PreRelease number if given. Remember to deduct automatic version bump. - if (semanticVersion.PreReleaseTag.Number.HasValue) - { - semanticVersion.PreReleaseTag.Number += semanticVersion.BuildMetaData.CommitsSinceTag - 1; - } - else - { - semanticVersion.PreReleaseTag.Number = semanticVersion.BuildMetaData.CommitsSinceTag; - semanticVersion.PreReleaseTag.PromotedFromCommits = true; - } - semanticVersion.BuildMetaData.CommitsSinceVersionSource = semanticVersion.BuildMetaData.CommitsSinceTag.Value; - semanticVersion.BuildMetaData.CommitsSinceTag = null; // why is this set to null ? + semanticVersion.PreReleaseTag.Number = semanticVersion.BuildMetaData.CommitsSinceTag; + semanticVersion.PreReleaseTag.PromotedFromCommits = true; } + semanticVersion.BuildMetaData.CommitsSinceVersionSource = semanticVersion.BuildMetaData.CommitsSinceTag.Value; + semanticVersion.BuildMetaData.CommitsSinceTag = null; // why is this set to null ? } }