mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix [semver] type to pass semver.org tests (#21401)
* Fix `[semver]` type to pass semver.org tests * fix test to split per OS specific newline * replace all regex with semver.org ones adding new one for build label, update tests --------- Co-authored-by: Steve Lee (POWERSHELL HE/HIM) (from Dev Box) <slee@ntdev.microsoft.com>
This commit is contained in:
@@ -335,8 +335,9 @@ namespace System.Management.Automation
|
||||
public sealed class SemanticVersion : IComparable, IComparable<SemanticVersion>, IEquatable<SemanticVersion>
|
||||
{
|
||||
private const string VersionSansRegEx = @"^(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?$";
|
||||
private const string LabelRegEx = @"^((?<preLabel>[0-9A-Za-z][0-9A-Za-z\-\.]*))?(\+(?<buildLabel>[0-9A-Za-z][0-9A-Za-z\-\.]*))?$";
|
||||
private const string LabelUnitRegEx = @"^[0-9A-Za-z][0-9A-Za-z\-\.]*$";
|
||||
private const string LabelRegEx = @"^(?<preLabel>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+(?<buildLabel>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$";
|
||||
private const string LabelUnitRegEx = @"^((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)$";
|
||||
private const string BuildUnitRegEx = @"^([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)$";
|
||||
private const string PreLabelPropertyName = "PSSemVerPreReleaseLabel";
|
||||
private const string BuildLabelPropertyName = "PSSemVerBuildLabel";
|
||||
private const string TypeNameForVersionWithLabel = "System.Version#IncludeLabel";
|
||||
@@ -370,7 +371,7 @@ namespace System.Management.Automation
|
||||
/// <param name="buildLabel">The build metadata for the version.</param>
|
||||
/// <exception cref="FormatException">
|
||||
/// If <paramref name="preReleaseLabel"/> don't match 'LabelUnitRegEx'.
|
||||
/// If <paramref name="buildLabel"/> don't match 'LabelUnitRegEx'.
|
||||
/// If <paramref name="buildLabel"/> don't match 'BuildUnitRegEx'.
|
||||
/// </exception>
|
||||
public SemanticVersion(int major, int minor, int patch, string preReleaseLabel, string buildLabel)
|
||||
: this(major, minor, patch)
|
||||
@@ -387,7 +388,7 @@ namespace System.Management.Automation
|
||||
|
||||
if (!string.IsNullOrEmpty(buildLabel))
|
||||
{
|
||||
if (!Regex.IsMatch(buildLabel, LabelUnitRegEx))
|
||||
if (!Regex.IsMatch(buildLabel, BuildUnitRegEx))
|
||||
{
|
||||
throw new FormatException(nameof(buildLabel));
|
||||
}
|
||||
@@ -410,7 +411,7 @@ namespace System.Management.Automation
|
||||
public SemanticVersion(int major, int minor, int patch, string label)
|
||||
: this(major, minor, patch)
|
||||
{
|
||||
// We presume the SymVer :
|
||||
// We presume the SemVer :
|
||||
// 1) major.minor.patch-label
|
||||
// 2) 'label' starts with letter or digit.
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
@@ -447,7 +448,7 @@ namespace System.Management.Automation
|
||||
throw PSTraceSource.NewArgumentException(nameof(minor));
|
||||
}
|
||||
|
||||
if (patch < 0)
|
||||
if (patch < 0)
|
||||
{
|
||||
throw PSTraceSource.NewArgumentException(nameof(patch));
|
||||
}
|
||||
@@ -568,12 +569,12 @@ namespace System.Management.Automation
|
||||
public int Patch { get; }
|
||||
|
||||
/// <summary>
|
||||
/// PreReleaseLabel position in the SymVer string 'major.minor.patch-PreReleaseLabel+BuildLabel'.
|
||||
/// PreReleaseLabel position in the SemVer string 'major.minor.patch-PreReleaseLabel+BuildLabel'.
|
||||
/// </summary>
|
||||
public string PreReleaseLabel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// BuildLabel position in the SymVer string 'major.minor.patch-PreReleaseLabel+BuildLabel'.
|
||||
/// BuildLabel position in the SemVer string 'major.minor.patch-PreReleaseLabel+BuildLabel'.
|
||||
/// </summary>
|
||||
public string BuildLabel { get; }
|
||||
|
||||
@@ -643,7 +644,7 @@ namespace System.Management.Automation
|
||||
string preLabel = null;
|
||||
string buildLabel = null;
|
||||
|
||||
// We parse the SymVer 'version' string 'major.minor.patch-PreReleaseLabel+BuildLabel'.
|
||||
// We parse the SemVer 'version' string 'major.minor.patch-PreReleaseLabel+BuildLabel'.
|
||||
var dashIndex = version.IndexOf('-');
|
||||
var plusIndex = version.IndexOf('+');
|
||||
|
||||
@@ -729,7 +730,7 @@ namespace System.Management.Automation
|
||||
}
|
||||
|
||||
if (preLabel != null && !Regex.IsMatch(preLabel, LabelUnitRegEx) ||
|
||||
(buildLabel != null && !Regex.IsMatch(buildLabel, LabelUnitRegEx)))
|
||||
(buildLabel != null && !Regex.IsMatch(buildLabel, BuildUnitRegEx)))
|
||||
{
|
||||
result.SetFailure(ParseFailureKind.FormatException);
|
||||
return false;
|
||||
@@ -804,7 +805,7 @@ namespace System.Management.Automation
|
||||
|
||||
/// <summary>
|
||||
/// Implement <see cref="IComparable{T}.CompareTo"/>.
|
||||
/// Meets SymVer 2.0 p.11 https://semver.org/
|
||||
/// Meets SemVer 2.0 p.11 https://semver.org/
|
||||
/// </summary>
|
||||
public int CompareTo(SemanticVersion value)
|
||||
{
|
||||
@@ -820,7 +821,7 @@ namespace System.Management.Automation
|
||||
if (Patch != value.Patch)
|
||||
return Patch > value.Patch ? 1 : -1;
|
||||
|
||||
// SymVer 2.0 standard requires to ignore 'BuildLabel' (Build metadata).
|
||||
// SemVer 2.0 standard requires to ignore 'BuildLabel' (Build metadata).
|
||||
return ComparePreLabel(this.PreReleaseLabel, value.PreReleaseLabel);
|
||||
}
|
||||
|
||||
@@ -837,7 +838,7 @@ namespace System.Management.Automation
|
||||
/// </summary>
|
||||
public bool Equals(SemanticVersion other)
|
||||
{
|
||||
// SymVer 2.0 standard requires to ignore 'BuildLabel' (Build metadata).
|
||||
// SemVer 2.0 standard requires to ignore 'BuildLabel' (Build metadata).
|
||||
return other != null &&
|
||||
(Major == other.Major) && (Minor == other.Minor) && (Patch == other.Patch) &&
|
||||
string.Equals(PreReleaseLabel, other.PreReleaseLabel, StringComparison.Ordinal);
|
||||
@@ -906,7 +907,7 @@ namespace System.Management.Automation
|
||||
|
||||
private static int ComparePreLabel(string preLabel1, string preLabel2)
|
||||
{
|
||||
// Symver 2.0 standard p.9
|
||||
// SemVer 2.0 standard p.9
|
||||
// Pre-release versions have a lower precedence than the associated normal version.
|
||||
// Comparing each dot separated identifier from left to right
|
||||
// until a difference is found as follows:
|
||||
|
||||
@@ -267,4 +267,105 @@ Describe "SemanticVersion api tests" -Tags 'CI' {
|
||||
{ $PSVersionTable.PSVersion | Format-Table | Out-String } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Semver official tests' {
|
||||
BeforeAll {
|
||||
$valid = @'
|
||||
0.0.4
|
||||
1.2.3
|
||||
10.20.30
|
||||
1.1.2-prerelease+meta
|
||||
1.1.2+meta
|
||||
1.1.2+meta-valid
|
||||
1.0.0-alpha
|
||||
1.0.0-beta
|
||||
1.0.0-alpha.beta
|
||||
1.0.0-alpha.beta.1
|
||||
1.0.0-alpha.1
|
||||
1.0.0-alpha0.valid
|
||||
1.0.0-alpha.0valid
|
||||
1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay
|
||||
1.0.0-rc.1+build.1
|
||||
2.0.0-rc.1+build.123
|
||||
1.2.3-beta
|
||||
10.2.3-DEV-SNAPSHOT
|
||||
1.2.3-SNAPSHOT-123
|
||||
1.0.0
|
||||
2.0.0
|
||||
1.1.7
|
||||
2.0.0+build.1848
|
||||
2.0.1-alpha.1227
|
||||
1.0.0-alpha+beta
|
||||
1.2.3----RC-SNAPSHOT.12.9.1--.12+788
|
||||
1.2.3----R-S.12.9.1--.12+meta
|
||||
1.2.3----RC-SNAPSHOT.12.9.1--.12
|
||||
1.0.0+0.build.1-rc.10000aaa-kk-0.1
|
||||
1.0.0-0A.is.legal
|
||||
'@
|
||||
|
||||
$validVersions = @()
|
||||
foreach ($version in $valid.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)) {
|
||||
$validVersions += @{version = $version}
|
||||
}
|
||||
|
||||
$invalid = @'
|
||||
1
|
||||
1.2
|
||||
1.2.3-0123
|
||||
1.2.3-0123.0123
|
||||
1.1.2+.123
|
||||
+invalid
|
||||
-invalid
|
||||
-invalid+invalid
|
||||
-invalid.01
|
||||
alpha
|
||||
alpha.beta
|
||||
alpha.beta.1
|
||||
alpha.1
|
||||
alpha+beta
|
||||
alpha_beta
|
||||
alpha.
|
||||
alpha..
|
||||
beta
|
||||
1.0.0-alpha_beta
|
||||
-alpha.
|
||||
1.0.0-alpha..
|
||||
1.0.0-alpha..1
|
||||
1.0.0-alpha...1
|
||||
1.0.0-alpha....1
|
||||
1.0.0-alpha.....1
|
||||
1.0.0-alpha......1
|
||||
1.0.0-alpha.......1
|
||||
01.1.1
|
||||
1.01.1
|
||||
1.1.01
|
||||
1.2
|
||||
1.2.3.DEV
|
||||
1.2-SNAPSHOT
|
||||
1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788
|
||||
1.2-RC-SNAPSHOT
|
||||
-1.0.3-gamma+b7718
|
||||
+justmeta
|
||||
9.8.7+meta+meta
|
||||
9.8.7-whatever+meta+meta
|
||||
99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12
|
||||
'@
|
||||
|
||||
$invalidVersions = @()
|
||||
foreach ($version in $invalid.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)) {
|
||||
$invalidVersions += @{version = $version}
|
||||
}
|
||||
}
|
||||
|
||||
It 'Should parse valid versions: <version>' -TestCases $validVersions {
|
||||
param($version)
|
||||
$v = [semver]"$version"
|
||||
$v.ToString() | Should -Be $version
|
||||
}
|
||||
|
||||
It 'Should not parse invalid versions: <version>' -TestCases $invalidVersions {
|
||||
{ [semver]"$version" } | Should -Throw
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user