Skip to content

Commit f36fb9b

Browse files
authored
Merge pull request #323 from firegiant/318-semver1-warning
Emit a warning when SemVer 2.0 format version is used with explicit SemVer 1.0
2 parents 99df816 + 1a71472 commit f36fb9b

File tree

4 files changed

+59
-34
lines changed

4 files changed

+59
-34
lines changed

src/NerdBank.GitVersioning.Tests/NerdBank.GitVersioning.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<IsTestProject>true</IsTestProject>
1010
</PropertyGroup>
1111
<ItemGroup>
12-
<Compile Include="..\Nerdbank.GitVersioning\SemanticVersionExtensions.cs" />
12+
<Compile Include="..\Shared\**\*.cs" LinkBase="Shared" />
1313
</ItemGroup>
1414
<ItemGroup>
1515
<EmbeddedResource Include="..\Nerdbank.GitVersioning.Tasks\build\Nerdbank.GitVersioning.targets">

src/NerdBank.GitVersioning/VersionOracle.cs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@
1414
/// </summary>
1515
public class VersionOracle
1616
{
17-
/// <summary>
18-
/// A regex that matches on numeric identifiers for prerelease or build metadata.
19-
/// </summary>
20-
private static readonly Regex NumericIdentifierRegex = new Regex(@"(?<![\w-])(\d+)(?![\w-])");
21-
2217
/// <summary>
2318
/// The 0.0 version.
2419
/// </summary>
@@ -178,7 +173,7 @@ public IEnumerable<string> BuildMetadataWithCommitId
178173
/// <summary>
179174
/// Gets the version options used to initialize this instance.
180175
/// </summary>
181-
private VersionOptions VersionOptions { get; }
176+
public VersionOptions VersionOptions { get; }
182177

183178
/// <summary>
184179
/// Gets the version string to use for the <see cref="System.Reflection.AssemblyVersionAttribute"/>.
@@ -427,7 +422,7 @@ public IDictionary<string, string> CloudBuildVersionVars
427422
private string SemVer2BuildMetadata =>
428423
(this.PublicRelease ? string.Empty : this.GitCommitIdShortForNonPublicPrereleaseTag) + FormatBuildMetadata(this.BuildMetadata);
429424

430-
private string PrereleaseVersionSemVer1 => MakePrereleaseSemVer1Compliant(this.PrereleaseVersion, this.SemVer1NumericIdentifierPadding);
425+
private string PrereleaseVersionSemVer1 => SemanticVersionExtensions.MakePrereleaseSemVer1Compliant(this.PrereleaseVersion, this.SemVer1NumericIdentifierPadding);
431426

432427
private string GitCommitIdShortForNonPublicPrereleaseTag => (string.IsNullOrEmpty(this.PrereleaseVersion) ? "-" : ".") + this.GitCommitIdShort;
433428

@@ -464,32 +459,6 @@ private static Version GetAssemblyVersion(Version version, VersionOptions versio
464459
/// <returns>The specified string, with macros substituted for actual values.</returns>
465460
private string ReplaceMacros(string prereleaseOrBuildMetadata) => prereleaseOrBuildMetadata?.Replace("{height}", this.VersionHeightWithOffset.ToString(CultureInfo.InvariantCulture));
466461

467-
/// <summary>
468-
/// Converts a semver 2 compliant "-beta.5" prerelease tag to a semver 1 compatible one.
469-
/// </summary>
470-
/// <param name="prerelease">The semver 2 prerelease tag, including its leading hyphen.</param>
471-
/// <param name="paddingSize">The minimum number of digits to use for any numeric identifier.</param>
472-
/// <returns>A semver 1 compliant prerelease tag. For example "-beta-0005".</returns>
473-
private static string MakePrereleaseSemVer1Compliant(string prerelease, int paddingSize)
474-
{
475-
if (string.IsNullOrEmpty(prerelease))
476-
{
477-
return prerelease;
478-
}
479-
480-
string paddingFormatter = "{0:" + new string('0', paddingSize) + "}";
481-
482-
string semver1 = prerelease;
483-
484-
// Identify numeric identifiers and pad them.
485-
Assumes.True(prerelease.StartsWith("-"));
486-
semver1 = "-" + NumericIdentifierRegex.Replace(semver1.Substring(1), m => string.Format(CultureInfo.InvariantCulture, paddingFormatter, int.Parse(m.Groups[1].Value)));
487-
488-
semver1 = semver1.Replace('.', '-');
489-
490-
return semver1;
491-
}
492-
493462
private static int CalculateVersionHeight(string relativeRepoProjectDirectory, LibGit2Sharp.Commit headCommit, VersionOptions committedVersion, VersionOptions workingVersion)
494463
{
495464
var headCommitVersion = committedVersion?.Version?.Version ?? Version0;

src/Nerdbank.GitVersioning.Tasks/GetBuildVersion.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ protected override bool ExecuteInner()
212212
oracle.BuildMetadata.AddRange(this.BuildMetadata);
213213
}
214214

215+
if (IsMisconfiguredPrereleaseAndSemVer1(oracle))
216+
{
217+
this.Log.LogWarning("The 'nugetPackageVersion' is explicitly set to 'semVer': 1 but the prerelease version '{0}' is not SemVer1 compliant. Change the 'nugetPackageVersion'.'semVer' value to 2 or change the 'version' member to follow SemVer1 rules (e.g.: '{1}').", oracle.PrereleaseVersion, GetSemVer1WithoutPaddingOrBuildMetadata(oracle));
218+
}
219+
215220
this.PublicRelease = oracle.PublicRelease;
216221
this.Version = oracle.Version.ToString();
217222
this.AssemblyVersion = oracle.AssemblyVersion.ToString();
@@ -267,5 +272,23 @@ protected override bool ExecuteInner()
267272
return false;
268273
}
269274
}
275+
276+
/// <summary>
277+
/// Gets the SemVer v1 format without padding or the build metadata.
278+
/// </summary>
279+
private static string GetSemVer1WithoutPaddingOrBuildMetadata(VersionOracle oracle)
280+
{
281+
Requires.NotNull(oracle, nameof(oracle));
282+
return $"{oracle.Version.ToStringSafe(3)}{SemanticVersionExtensions.MakePrereleaseSemVer1Compliant(oracle.PrereleaseVersion, 0)}";
283+
}
284+
285+
/// <summary>
286+
/// Gets a value indicating whether the user wants SemVer v1 compliance yet specified a non-v1 compliant prerelease tag.
287+
/// </summary>
288+
private static bool IsMisconfiguredPrereleaseAndSemVer1(VersionOracle oracle)
289+
{
290+
Requires.NotNull(oracle, nameof(oracle));
291+
return oracle.VersionOptions?.NuGetPackageVersion?.SemVer == 1 && oracle.PrereleaseVersion != SemanticVersionExtensions.MakePrereleaseSemVer1Compliant(oracle.PrereleaseVersion, 0);
292+
}
270293
}
271294
}

src/NerdBank.GitVersioning/SemanticVersionExtensions.cs renamed to src/Shared/SemanticVersionExtensions.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
namespace Nerdbank.GitVersioning
22
{
33
using System;
4+
using System.Globalization;
5+
using System.Text.RegularExpressions;
46
using Validation;
57

68
/// <summary>
79
/// Extension methods for <see cref="SemanticVersion"/>
810
/// </summary>
911
internal static class SemanticVersionExtensions
1012
{
13+
/// <summary>
14+
/// A regex that matches on numeric identifiers for prerelease or build metadata.
15+
/// </summary>
16+
private static readonly Regex NumericIdentifierRegex = new Regex(@"(?<![\w-])(\d+)(?![\w-])");
17+
1118
/// <summary>
1219
/// Gets a new semantic with the specified version component (major/minor) incremented.
1320
/// </summary>
@@ -107,5 +114,31 @@ internal static SemanticVersion WithoutPrepreleaseTags(this SemanticVersion vers
107114
{
108115
return new SemanticVersion(version.Version, null, version.BuildMetadata);
109116
}
117+
118+
/// <summary>
119+
/// Converts a semver 2 compliant "-beta.5" prerelease tag to a semver 1 compatible one.
120+
/// </summary>
121+
/// <param name="prerelease">The semver 2 prerelease tag, including its leading hyphen.</param>
122+
/// <param name="paddingSize">The minimum number of digits to use for any numeric identifier.</param>
123+
/// <returns>A semver 1 compliant prerelease tag. For example "-beta-0005".</returns>
124+
internal static string MakePrereleaseSemVer1Compliant(string prerelease, int paddingSize)
125+
{
126+
if (string.IsNullOrEmpty(prerelease))
127+
{
128+
return prerelease;
129+
}
130+
131+
string paddingFormatter = "{0:" + new string('0', paddingSize) + "}";
132+
133+
string semver1 = prerelease;
134+
135+
// Identify numeric identifiers and pad them.
136+
Assumes.True(prerelease.StartsWith("-"));
137+
semver1 = "-" + NumericIdentifierRegex.Replace(semver1.Substring(1), m => string.Format(CultureInfo.InvariantCulture, paddingFormatter, int.Parse(m.Groups[1].Value)));
138+
139+
semver1 = semver1.Replace('.', '-');
140+
141+
return semver1;
142+
}
110143
}
111144
}

0 commit comments

Comments
 (0)