Skip to content

Commit

Permalink
Merge pull request #2880 from chris-codeflow/feature/Improve-ToString
Browse files Browse the repository at this point in the history
Improve SemanticVersion.ToString implementation
  • Loading branch information
asbjornu committed Oct 15, 2021
2 parents e0b0ff7 + de8cbcf commit db23e17
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 176 deletions.
241 changes: 77 additions & 164 deletions src/GitVersion.Core.Tests/VersionCalculation/SemanticVersionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace GitVersion.Core.Tests;
[TestFixture]
public class SemanticVersionTests : TestBase
{

[TestCase("1.2.3", 1, 2, 3, null, null, null, null, null, null, null, null)]
[TestCase("1.2", 1, 2, 0, null, null, null, null, null, null, "1.2.0", null)]
[TestCase("1.2.3-beta", 1, 2, 3, "beta", null, null, null, null, null, null, null)]
Expand Down Expand Up @@ -79,183 +78,97 @@ public void VersionSorting()
}

[Test]
public void ToStringJTests()
public void ToStringWithInvalidFormatTest()
{
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString("j"));
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3-beta.4", null).ToString("j"));
var fullSemVer = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3", fullSemVer.ToString("j"));
var semVer = BuildSemVer(1, 2, 3, "rc", 1, 1);
Should.Throw<FormatException>(() => semVer.ToString("invalid"));
}
[Test]
public void ToStringSTests()

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3-beta.4")]
[TestCase(1, 2, 3, "beta", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-beta.4")]
[TestCase(1, 2, 3, "", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-4")]
public string ToStringTests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString("s"));
Assert.AreEqual("1.2.3-beta.4", SemanticVersion.Parse("1.2.3-beta.4", null).ToString("s"));
var fullSemVer = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-beta.4", fullSemVer.ToString("s"));
var fullSemVerNoPreReleaseName = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-4", fullSemVerNoPreReleaseName.ToString("s"));
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString();
}
[Test]
public void ToStringLTests()

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3-beta.4")]
[TestCase(1, 2, 3, "beta", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-beta.4")]
[TestCase(1, 2, 3, "", 4, 10, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-4")]
public string ToStringWithSFormatTests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString("l"));
Assert.AreEqual("1.2.3-beta4", SemanticVersion.Parse("1.2.3-beta.4", null).ToString("l"));
var fullSemVer = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-beta4", fullSemVer.ToString("l"));
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString("s");
}
[Test]
public void ToStringLpTests()

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3")]
public string ToStringWithFormatJTests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString("lp"));
Assert.AreEqual("1.2.3-beta0004", SemanticVersion.Parse("1.2.3-beta.4", null).ToString("lp"));
var fullSemVer = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-beta0004", fullSemVer.ToString("lp"));
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString("j");
}
[Test]
public void ToStringTests()

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3-beta4")]
[TestCase(1, 2, 3, "beta", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-beta4")]
public string ToStringWithFormatLTests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString());
Assert.AreEqual("1.2.3-beta.4", SemanticVersion.Parse("1.2.3-beta.4", null).ToString());
Assert.AreEqual("1.2.3-beta.4", SemanticVersion.Parse("1.2.3-beta.4+5", null).ToString());
var fullSemVer = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-beta.4", fullSemVer.ToString());
var fullSemVerNoPreReleaseName = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-4", fullSemVerNoPreReleaseName.ToString());
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString("l");
}
[Test]
public void ToStringFTests()

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3-beta0004")]
[TestCase(1, 2, 3, "beta", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-beta0004")]
public string ToStringWithFormatLpTests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString("f"));
Assert.AreEqual("1.2.3-beta.4", SemanticVersion.Parse("1.2.3-beta.4", null).ToString("f"));
Assert.AreEqual("1.2.3-beta.4+5", SemanticVersion.Parse("1.2.3-beta.4+5", null).ToString("f"));
var fullSemVer = new SemanticVersion
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-beta.4+5", fullSemVer.ToString("f"));
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString("lp");
}
[Test]
public void ToStringITests()

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3-beta.4")]
[TestCase(1, 2, 3, "beta", 4, 5, null, null, null, ExpectedResult = "1.2.3-beta.4+5")]
[TestCase(1, 2, 3, "", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-4+5")]
public string ToStringWithFormatFTests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
Assert.AreEqual("1.2.3-beta.4", SemanticVersion.Parse("1.2.3-beta.4", null).ToString("i"));
Assert.AreEqual("1.2.3", SemanticVersion.Parse("1.2.3", null).ToString("i"));
Assert.AreEqual("1.2.3-beta.4+5", SemanticVersion.Parse("1.2.3-beta.4+5", null).ToString("i"));
var fullSemVer = new SemanticVersion
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString("f");
}

[TestCase(1, 2, 3, null, null, null, null, null, null, ExpectedResult = "1.2.3")]
[TestCase(1, 2, 3, "beta", 4, null, null, null, null, ExpectedResult = "1.2.3-beta.4")]
[TestCase(1, 2, 3, "beta", 4, 5, null, null, null, ExpectedResult = "1.2.3-beta.4+5")]
[TestCase(1, 2, 3, "beta", 4, 5, "theBranch", "theSha", "theOtherMetaData", ExpectedResult = "1.2.3-beta.4+5.Branch.theBranch.Sha.theSha.theOtherMetaData")]
public string ToStringWithFormatITests(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName, string sha, string otherMetadata)
{
var semVer = BuildSemVer(major, minor, patch, preReleaseName, preReleaseVersion, buildCount, branchName, sha, otherMetadata);
return semVer.ToString("i");
}

private static SemanticVersion BuildSemVer(int major, int minor, int patch, string preReleaseName, int preReleaseVersion, int? buildCount, string branchName = null, string sha = null, string otherMetadata = null)
{
var semVer = new SemanticVersion(major, minor, patch);
if (preReleaseName != null)
{
Major = 1,
Minor = 2,
Patch = 3,
PreReleaseTag = new SemanticVersionPreReleaseTag("beta", 4),
BuildMetaData = new SemanticVersionBuildMetaData
semVer.PreReleaseTag = new SemanticVersionPreReleaseTag(preReleaseName, preReleaseVersion);
}
if (buildCount.HasValue)
{
semVer.BuildMetaData = new SemanticVersionBuildMetaData
{
Sha = "theSha",
Branch = "TheBranch",
CommitsSinceTag = 5,
OtherMetaData = "TheOtherMetaData"
}
};
Assert.AreEqual("1.2.3-beta.4+5.Branch.TheBranch.Sha.theSha.TheOtherMetaData", fullSemVer.ToString("i"));
CommitsSinceTag = buildCount.Value,
Sha = sha,
Branch = branchName,
OtherMetaData = otherMetadata
};
}

return semVer;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.RegularExpressions;
using GitVersion.Extensions;

Expand Down Expand Up @@ -221,18 +222,20 @@ public int CompareTo(SemanticVersion? value, bool includePrerelease)
return 0;
}

public override string ToString() => ToString(null);
public override string ToString() => ToString("s");

public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture);

/// <summary>
/// <para>s - Default SemVer [1.2.3-beta.4+5]</para>
/// <para>s - Default SemVer [1.2.3-beta.4]</para>
/// <para>f - Full SemVer [1.2.3-beta.4+5]</para>
/// <para>i - Informational SemVer [1.2.3-beta.4+5.Branch.main.BranchType.main.Sha.000000]</para>
/// <para>j - Just the SemVer part [1.2.3]</para>
/// <para>t - SemVer with the tag [1.2.3-beta.4]</para>
/// <para>l - Legacy SemVer tag for systems which do not support SemVer 2.0 properly [1.2.3-beta4]</para>
/// <para>lp - Legacy SemVer tag for systems which do not support SemVer 2.0 properly (padded) [1.2.3-beta0004]</para>
/// </summary>
public string ToString(string? format, IFormatProvider? formatProvider = null)
public string ToString(string format, IFormatProvider formatProvider)
{
if (format.IsNullOrEmpty())
format = "s";
Expand Down Expand Up @@ -271,7 +274,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null)
return !buildMetadata.IsNullOrEmpty() ? $"{ToString("s")}+{buildMetadata}" : ToString("s");
}
default:
throw new ArgumentException($"Unrecognised format '{format}'", nameof(format));
throw new FormatException($"Unknown format '{format}'.");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Globalization;
using System.Text.RegularExpressions;
using GitVersion.Extensions;
using GitVersion.Helpers;
Expand Down Expand Up @@ -59,15 +60,17 @@ public SemanticVersionBuildMetaData(SemanticVersionBuildMetaData? buildMetaData)

public override int GetHashCode() => EqualityHelper.GetHashCode(this);

public override string ToString() => ToString(null);
public override string ToString() => ToString("b");

public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture);

/// <summary>
/// <para>b - Formats just the build number</para>
/// <para>s - Formats the build number and the Git Sha</para>
/// <para>f - Formats the full build metadata</para>
/// <para>p - Formats the padded build number. Can specify an integer for padding, default is 4. (i.e., p5)</para>
/// </summary>
public string ToString(string? format, IFormatProvider? formatProvider = null)
public string ToString(string format, IFormatProvider formatProvider)
{
if (formatProvider != null)
{
Expand Down Expand Up @@ -100,7 +103,7 @@ public string ToString(string? format, IFormatProvider? formatProvider = null)
"b" => this.CommitsSinceTag.ToString(),
"s" => $"{this.CommitsSinceTag}{(this.Sha.IsNullOrEmpty() ? null : ".Sha." + this.Sha)}".TrimStart('.'),
"f" => $"{this.CommitsSinceTag}{(this.Branch.IsNullOrEmpty() ? null : ".Branch." + FormatMetaDataPart(this.Branch))}{(this.Sha.IsNullOrEmpty() ? null : ".Sha." + this.Sha)}{(this.OtherMetaData.IsNullOrEmpty() ? null : "." + FormatMetaDataPart(this.OtherMetaData))}".TrimStart('.'),
_ => throw new ArgumentException("Unrecognised format", nameof(format))
_ => throw new FormatException($"Unknown format '{format}'.")
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Globalization;
using System.Text.RegularExpressions;
using GitVersion.Extensions;
using GitVersion.Helpers;
Expand Down Expand Up @@ -93,23 +94,24 @@ public int CompareTo(SemanticVersionPreReleaseTag? other)
return -1;
}


var nameComparison = StringComparerUtils.IgnoreCaseComparer.Compare(Name, other?.Name);
if (nameComparison != 0)
return nameComparison;

return Nullable.Compare(Number, other?.Number);
}

public override string? ToString() => ToString(null);
public override string ToString() => ToString("t");

public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture);

/// <summary>
/// Default formats:
/// <para>t - SemVer 2.0 formatted tag [beta.1]</para>
/// <para>l - Legacy SemVer tag with the tag number padded. [beta1]</para>
/// <para>lp - Legacy SemVer tag with the tag number padded. [beta0001]. Can specify an integer to control padding (i.e., lp5)</para>
/// </summary>
public string? ToString(string? format, IFormatProvider? formatProvider = null)
public string ToString(string format, IFormatProvider formatProvider)
{
if (formatProvider != null)
{
Expand Down Expand Up @@ -139,9 +141,9 @@ public int CompareTo(SemanticVersionPreReleaseTag? other)

return format switch
{
"t" => (Number.HasValue ? Name.IsNullOrEmpty() ? $"{Number}" : $"{Name}.{Number}" : Name),
"t" => (Number.HasValue ? Name.IsNullOrEmpty() ? $"{Number}" : $"{Name}.{Number}" : Name ?? string.Empty),
"l" => (Number.HasValue ? FormatLegacy(GetLegacyName(), Number.Value.ToString()) : FormatLegacy(GetLegacyName())),
_ => throw new ArgumentException("Unknown format", nameof(format))
_ => throw new FormatException($"Unknown format '{format}'.")
};
}

Expand Down

0 comments on commit db23e17

Please sign in to comment.