diff --git a/source/OctoVersion.Core/OctoVersionInfo.cs b/source/OctoVersion.Core/OctoVersionInfo.cs index c13a99b..ea612fe 100644 --- a/source/OctoVersion.Core/OctoVersionInfo.cs +++ b/source/OctoVersion.Core/OctoVersionInfo.cs @@ -40,9 +40,19 @@ public OctoVersionInfo(SemanticVersion semanticVersion) : base( public string BuildMetadataWithPlus => string.IsNullOrWhiteSpace(BuildMetadata) ? string.Empty : $"+{InvalidBuildMetadataCharacters.Replace(BuildMetadata, "-")}"; public string FullSemVer => $"{MajorMinorPatch}{PreReleaseTagWithDash}"; public string InformationalVersion => $"{MajorMinorPatch}{PreReleaseTagWithDash}{BuildMetadataWithPlus}"; - string NuGetCompatiblePreReleaseWithDash => PreReleaseTagWithDash.Substring(0, Math.Min(PreReleaseTagWithDash.Length, 20)); public string NuGetVersion => $"{MajorMinorPatch}{NuGetCompatiblePreReleaseWithDash}"; + string NuGetCompatiblePreReleaseWithDash + { + get + { + var truncated = PreReleaseTagWithDash.Substring(0, Math.Min(PreReleaseTagWithDash.Length, 20)); + + //a trailing dot is an empty pre-release identifier, which is not a valid version + return truncated.TrimEnd('.'); + } + } + public override string ToString() { return FullSemVer; diff --git a/source/OctoVersion.Tests/WhenStringifyingAnOctoVersionInfo.cs b/source/OctoVersion.Tests/WhenStringifyingAnOctoVersionInfo.cs index a15fc98..bdcb19a 100644 --- a/source/OctoVersion.Tests/WhenStringifyingAnOctoVersionInfo.cs +++ b/source/OctoVersion.Tests/WhenStringifyingAnOctoVersionInfo.cs @@ -44,6 +44,13 @@ public class WhenStringifyingAnOctoVersionInfo "dependabot/npm_and_yarn/source/TentacleArmy.Web/ini-1.3.6", "Branch.dependabot/npm_and_yarn/source/TentacleArmy.Web/ini-1.3.6.Sha.069392d9d2d37ddb6009998b92e70963badcc666"); + //the NuGet-compatible pre-release is 20 characters, which lands this one exactly on a dot + static readonly OctoVersionInfo VersionWhereTheNuGetTruncationLandsOnADot = new(1, + 1, + 47, + "renovate-microsoft.aspnetcore.mvc.newtonsoftjson-10.x", + "Branch.renovate-microsoft.aspnetcore.mvc.newtonsoftjson-10.x.Sha.72529493c8ccfae2784cd604b7784294b03f388d"); + //xunit is blurgh - IEnumerable of object[]? ick. public static IEnumerable PreReleaseTagWithDashTestCases() { @@ -54,6 +61,7 @@ public static IEnumerable PreReleaseTagWithDashTestCases() yield return new object[] { VersionWithPreReleaseTagAndBuildMetadata, "-pre", "it should append the pre-release tag, but not the build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagAndBuildMetadata, "-mark-genericDocumentStore", "it should add the pre-release tag, and ignore the build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagWithSlashesAndBuildMetadata, "-dependabot-npm-and-yarn-source-TentacleArmy.Web-ini-1.3.6", "it should add the pre-release tag, and ignore the build metadata" }; + yield return new object[] { VersionWhereTheNuGetTruncationLandsOnADot, "-renovate-microsoft.aspnetcore.mvc.newtonsoftjson-10.x", "it should add the pre-release tag untruncated" }; } [Theory] @@ -108,6 +116,7 @@ public static IEnumerable FullSemVerTestCases() yield return new object[] { VersionWithPreReleaseTagAndBuildMetadata, "1.2.3-pre", "it should return the major.minor.patch and pre-release but not the build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagAndBuildMetadata, "2021.1.3-mark-genericDocumentStore", "it should return the major.minor.patch and pre-release but not the build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagWithSlashesAndBuildMetadata, "2021.1.3-dependabot-npm-and-yarn-source-TentacleArmy.Web-ini-1.3.6", "it should return the major.minor.patch and pre-release but not the build metadata" }; + yield return new object[] { VersionWhereTheNuGetTruncationLandsOnADot, "1.1.47-renovate-microsoft.aspnetcore.mvc.newtonsoftjson-10.x", "it should return the major.minor.patch and the untruncated pre-release" }; } [Theory] @@ -126,6 +135,7 @@ public static IEnumerable NuGetVersionTestCases() yield return new object[] { VersionWithPreReleaseTagAndBuildMetadata, "1.2.3-pre", "it should return the major.minor.patch and pre-release but not the build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagAndBuildMetadata, "2021.1.3-mark-genericDocumen", "it should return the major.minor.patch and trim the pre-release to 20 chars" }; yield return new object[] { VersionWithLongPreReleaseTagWithSlashesAndBuildMetadata, "2021.1.3-dependabot-npm-and-", "it should return the major.minor.patch and trim the pre-release to 20 chars" }; + yield return new object[] { VersionWhereTheNuGetTruncationLandsOnADot, "1.1.47-renovate-microsoft", "a trimmed pre-release must not end with a dot" }; } [Theory] @@ -144,6 +154,7 @@ public static IEnumerable InformationalVersionTestCases() yield return new object[] { VersionWithPreReleaseTagAndBuildMetadata, "1.2.3-pre+build", "it should return the major.minor.patch and pre-release and build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagAndBuildMetadata, "2021.1.3-mark-genericDocumentStore+Branch.mark-genericDocumentStore.Sha.fb13016f3a21d7c2058fb74ab25f19e5311c6550", "it should return the major.minor.patch and pre-release and build metadata" }; yield return new object[] { VersionWithLongPreReleaseTagWithSlashesAndBuildMetadata, "2021.1.3-dependabot-npm-and-yarn-source-TentacleArmy.Web-ini-1.3.6+Branch.dependabot-npm-and-yarn-source-TentacleArmy.Web-ini-1.3.6.Sha.069392d9d2d37ddb6009998b92e70963badcc666", "it should return the major.minor.patch and pre-release and build metadata" }; + yield return new object[] { VersionWhereTheNuGetTruncationLandsOnADot, "1.1.47-renovate-microsoft.aspnetcore.mvc.newtonsoftjson-10.x+Branch.renovate-microsoft.aspnetcore.mvc.newtonsoftjson-10.x.Sha.72529493c8ccfae2784cd604b7784294b03f388d", "it should return the major.minor.patch and pre-release and build metadata" }; } [Theory]