Sync eng/common directory with azure-sdk-tools repository for Tools PR 935 (#559)
This commit is contained in:
parent
b46a544a7b
commit
fa63edb51f
@ -4,102 +4,244 @@ Parses a semver version string into its components and supports operations aroun
|
||||
|
||||
See https://azure.github.io/azure-sdk/policies_releases.html#package-versioning
|
||||
|
||||
Example: 1.2.3-preview.4
|
||||
Example: 1.2.3-beta.4
|
||||
Components: Major.Minor.Patch-PrereleaseLabel.PrereleaseNumber
|
||||
|
||||
Note: A builtin Powershell version of SemVer exists in 'System.Management.Automation'. At this time, it does not parsing of PrereleaseNumber. It's name is also type accelerated to 'SemVer'.
|
||||
#>
|
||||
|
||||
class AzureEngSemanticVersion {
|
||||
[int] $Major
|
||||
[int] $Minor
|
||||
[int] $Patch
|
||||
[string] $PrereleaseLabel
|
||||
[int] $PrereleaseNumber
|
||||
[bool] $IsPrerelease
|
||||
[string] $RawVersion
|
||||
# Regex inspired but simplified from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||
static [string] $SEMVER_REGEX = "(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-?(?<prelabel>[a-zA-Z-]*)(?:\.?(?<prenumber>0|[1-9]\d*)))?"
|
||||
[int] $Major
|
||||
[int] $Minor
|
||||
[int] $Patch
|
||||
[string] $PrereleaseLabelSeparator
|
||||
[string] $PrereleaseLabel
|
||||
[string] $PrereleaseNumberSeparator
|
||||
[int] $PrereleaseNumber
|
||||
[bool] $IsPrerelease
|
||||
[string] $RawVersion
|
||||
[bool] $IsSemVerFormat
|
||||
[string] $DefaultPrereleaseLabel
|
||||
# Regex inspired but simplified from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
||||
static [string] $SEMVER_REGEX = "(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:(?<presep>-?)(?<prelabel>[a-zA-Z-]*)(?<prenumsep>\.?)(?<prenumber>0|[1-9]\d*))?"
|
||||
|
||||
static [AzureEngSemanticVersion] ParseVersionString([string] $versionString)
|
||||
static [AzureEngSemanticVersion] ParseVersionString([string] $versionString)
|
||||
{
|
||||
$version = [AzureEngSemanticVersion]::new($versionString)
|
||||
|
||||
if (!$version.IsSemVerFormat) {
|
||||
return $null
|
||||
}
|
||||
return $version
|
||||
}
|
||||
|
||||
static [AzureEngSemanticVersion] ParsePythonVersionString([string] $versionString)
|
||||
{
|
||||
$version = [AzureEngSemanticVersion]::ParseVersionString($versionString)
|
||||
|
||||
if (!$version) {
|
||||
return $null
|
||||
}
|
||||
|
||||
$version.SetupPythonConventions()
|
||||
return $version
|
||||
}
|
||||
|
||||
AzureEngSemanticVersion([string] $versionString)
|
||||
{
|
||||
if ($versionString -match "^$([AzureEngSemanticVersion]::SEMVER_REGEX)$")
|
||||
{
|
||||
try {
|
||||
return [AzureEngSemanticVersion]::new($versionString)
|
||||
}
|
||||
catch {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
AzureEngSemanticVersion([string] $versionString){
|
||||
if ($versionString -match "^$([AzureEngSemanticVersion]::SEMVER_REGEX)$") {
|
||||
if ($null -eq $matches['prelabel']) {
|
||||
# artifically provide these values for non-prereleases to enable easy sorting of them later than prereleases.
|
||||
$prelabel = "zzz"
|
||||
$prenumber = 999;
|
||||
$isPre = $false;
|
||||
}
|
||||
else {
|
||||
$prelabel = $matches["prelabel"]
|
||||
$prenumber = [int]$matches["prenumber"]
|
||||
$isPre = $true;
|
||||
}
|
||||
$this.IsSemVerFormat = $true
|
||||
$this.RawVersion = $versionString
|
||||
$this.Major = [int]$matches.Major
|
||||
$this.Minor = [int]$matches.Minor
|
||||
$this.Patch = [int]$matches.Patch
|
||||
|
||||
$this.Major = [int]$matches.Major
|
||||
$this.Minor = [int]$matches.Minor
|
||||
$this.Patch = [int]$matches.Patch
|
||||
$this.PrereleaseLabel = $prelabel
|
||||
$this.PrereleaseNumber = $prenumber
|
||||
$this.IsPrerelease = $isPre
|
||||
$this.RawVersion = $versionString
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Invalid version string: '$versionString'"
|
||||
}
|
||||
$this.SetupDefaultConventions()
|
||||
|
||||
if ($null -eq $matches['prelabel'])
|
||||
{
|
||||
# artifically provide these values for non-prereleases to enable easy sorting of them later than prereleases.
|
||||
$this.PrereleaseLabel = "zzz"
|
||||
$this.PrereleaseNumber = 999
|
||||
$this.IsPrerelease = $false
|
||||
}
|
||||
else
|
||||
{
|
||||
$this.PrereleaseLabel = $matches["prelabel"]
|
||||
$this.PrereleaseLabelSeparator = $matches["presep"]
|
||||
$this.PrereleaseNumber = [int]$matches["prenumber"]
|
||||
$this.PrereleaseNumberSeparator = $matches["prenumsep"]
|
||||
$this.IsPrerelease = $true
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this.RawVersion = $versionString
|
||||
$this.IsSemVerFormat = $false
|
||||
}
|
||||
}
|
||||
|
||||
# If a prerelease label exists, it must be 'beta', and similar semantics used in our release guidelines
|
||||
# See https://azure.github.io/azure-sdk/policies_releases.html#package-versioning
|
||||
[bool] HasValidPrereleaseLabel()
|
||||
{
|
||||
if ($this.IsPrerelease -eq $true) {
|
||||
if ($this.PrereleaseLabel -ne $this.DefaultPrereleaseLabel) {
|
||||
Write-Host "Unexpected pre-release identifier '$($this.PrereleaseLabel)', should be '$($this.DefaultPrereleaseLabel)'"
|
||||
return $false;
|
||||
}
|
||||
if ($this.PrereleaseNumber -lt 1)
|
||||
{
|
||||
Write-Host "Unexpected pre-release version '$($this.PrereleaseNumber)', should be >= '1'"
|
||||
return $false;
|
||||
}
|
||||
}
|
||||
return $true;
|
||||
}
|
||||
|
||||
[string] ToString()
|
||||
{
|
||||
$versionString = "{0}.{1}.{2}" -F $this.Major, $this.Minor, $this.Patch
|
||||
|
||||
if ($this.IsPrerelease)
|
||||
{
|
||||
$versionString += $this.PrereleaseLabelSeparator + $this.PrereleaseLabel + $this.PrereleaseNumberSeparator + $this.PrereleaseNumber
|
||||
}
|
||||
return $versionString;
|
||||
}
|
||||
|
||||
[void] IncrementAndSetToPrerelease() {
|
||||
if ($this.IsPrerelease -eq $false)
|
||||
{
|
||||
$this.PrereleaseLabel = $this.DefaultPrereleaseLabel
|
||||
$this.PrereleaseNumber = 1
|
||||
$this.Minor++
|
||||
$this.Patch = 0
|
||||
$this.IsPrerelease = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$this.PrereleaseNumber++
|
||||
}
|
||||
}
|
||||
|
||||
[void] SetupPythonConventions()
|
||||
{
|
||||
# Python uses no separators and "b" for beta so this sets up the the object to work with those conventions
|
||||
$this.PrereleaseLabelSeparator = $this.PrereleaseNumberSeparator = ""
|
||||
$this.DefaultPrereleaseLabel = "b"
|
||||
}
|
||||
|
||||
[void] SetupDefaultConventions()
|
||||
{
|
||||
# Use the default common conventions
|
||||
$this.PrereleaseLabelSeparator = "-"
|
||||
$this.PrereleaseNumberSeparator = "."
|
||||
$this.DefaultPrereleaseLabel = "beta"
|
||||
}
|
||||
|
||||
static [string[]] SortVersionStrings([string[]] $versionStrings)
|
||||
{
|
||||
$versions = $versionStrings | ForEach-Object { [AzureEngSemanticVersion]::ParseVersionString($_) }
|
||||
$sortedVersions = [AzureEngSemanticVersion]::SortVersions($versions)
|
||||
return ($sortedVersions | ForEach-Object { $_.ToString() })
|
||||
}
|
||||
|
||||
static [AzureEngSemanticVersion[]] SortVersions([AzureEngSemanticVersion[]] $versions)
|
||||
{
|
||||
return ($versions | Sort-Object -Property Major, Minor, Patch, PrereleaseLabel, PrereleaseNumber -Descending)
|
||||
}
|
||||
|
||||
static [void] QuickTests()
|
||||
{
|
||||
$versions = @(
|
||||
"1.0.1",
|
||||
"2.0.0",
|
||||
"2.0.0-alpha.20200920",
|
||||
"2.0.0-beta.2",
|
||||
"1.0.10",
|
||||
"2.0.0-beta.1",
|
||||
"2.0.0-beta.10",
|
||||
"1.0.0",
|
||||
"1.0.0b2",
|
||||
"1.0.2")
|
||||
|
||||
$expectedSort = @(
|
||||
"2.0.0",
|
||||
"2.0.0-beta.10",
|
||||
"2.0.0-beta.2",
|
||||
"2.0.0-beta.1",
|
||||
"2.0.0-alpha.20200920",
|
||||
"1.0.10",
|
||||
"1.0.2",
|
||||
"1.0.1",
|
||||
"1.0.0",
|
||||
"1.0.0b2")
|
||||
|
||||
$sort = [AzureEngSemanticVersion]::SortVersionStrings($versions)
|
||||
|
||||
for ($i = 0; $i -lt $expectedSort.Count; $i++)
|
||||
{
|
||||
if ($sort[$i] -ne $expectedSort[$i]) {
|
||||
Write-Host "Error: Incorrect sort:"
|
||||
Write-Host "Expected: "
|
||||
Write-Host $expectedSort
|
||||
Write-Host "Actual:"
|
||||
Write-Host $sort
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# If a prerelease label exists, it must be 'preview', and similar semantics used in our release guidelines
|
||||
# See https://azure.github.io/azure-sdk/policies_releases.html#package-versioning
|
||||
[bool] HasValidPrereleaseLabel(){
|
||||
if ($this.IsPrerelease -eq $true) {
|
||||
if ($this.PrereleaseLabel -ne 'preview') {
|
||||
Write-Error "Unexpected pre-release identifier '$this.PrereleaseLabel', should be 'preview'"
|
||||
return $false;
|
||||
}
|
||||
if ($this.PrereleaseNumber -lt 1)
|
||||
{
|
||||
Write-Error "Unexpected pre-release version '$this.PrereleaseNumber', should be >= '1'"
|
||||
return $false;
|
||||
}
|
||||
}
|
||||
return $true;
|
||||
$devVerString = "1.2.3-alpha.20200828.1"
|
||||
$devVerNew = [AzureEngSemanticVersion]::new($devVerString)
|
||||
if (!$devVerNew -or $devVerNew.IsSemVerFormat -ne $false) {
|
||||
Write-Host "Error: Didn't expect daily dev version to match our semver regex because of the extra .r"
|
||||
}
|
||||
$devVerparse = [AzureEngSemanticVersion]::ParseVersionString($devVerString)
|
||||
if ($devVerparse) {
|
||||
Write-Host "Error: Didn't expect daily dev version to parse because of the extra .r"
|
||||
}
|
||||
|
||||
[string] ToString(){
|
||||
if ($this.IsPrerelease -eq $false)
|
||||
{
|
||||
$versionString = "{0}.{1}.{2}" -F $this.Major, $this.Minor, $this.Patch
|
||||
}
|
||||
else
|
||||
{
|
||||
$versionString = "{0}.{1}.{2}-{3}.{4}" -F $this.Major, $this.Minor, $this.Patch, $this.PrereleaseLabel, $this.PrereleaseNumber
|
||||
}
|
||||
return $versionString;
|
||||
}
|
||||
|
||||
[void] IncrementAndSetToPrerelease(){
|
||||
if ($this.IsPrerelease -eq $false)
|
||||
{
|
||||
$this.PrereleaseLabel = 'preview'
|
||||
$this.PrereleaseNumber = 1
|
||||
$this.Minor++
|
||||
$this.Patch = 0
|
||||
$this.IsPrerelease = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$this.PrereleaseNumber++
|
||||
}
|
||||
$gaVerString = "1.2.3"
|
||||
$gaVer = [AzureEngSemanticVersion]::ParseVersionString($gaVerString)
|
||||
if ($gaVer.Major -ne 1 -or $gaVer.Minor -ne 2 -or $gaVer.Patch -ne 3) {
|
||||
Write-Host "Error: Didn't correctly parse ga version string $gaVerString"
|
||||
}
|
||||
if ($gaVerString -ne $gaVer.ToString()) {
|
||||
Write-Host "Error: Ga string did not correctly round trip with ToString"
|
||||
}
|
||||
$gaVer.IncrementAndSetToPrerelease()
|
||||
if ("1.3.0-beta.1" -ne $gaVer.ToString()) {
|
||||
Write-Host "Error: Ga string did not correctly increment"
|
||||
}
|
||||
|
||||
$betaVerString = "1.2.3-beta.4"
|
||||
$betaVer = [AzureEngSemanticVersion]::ParseVersionString($betaVerString)
|
||||
if ($betaVer.Major -ne 1 -or $betaVer.Minor -ne 2 -or $betaVer.Patch -ne 3 -or $betaVer.PrereleaseLabel -ne "beta" -or $betaVer.PrereleaseNumber -ne 4) {
|
||||
Write-Host "Error: Didn't correctly parse beta version string $betaVerString"
|
||||
}
|
||||
if ($betaVerString -ne $betaVer.ToString()) {
|
||||
Write-Host "Error: beta string did not correctly round trip with ToString"
|
||||
}
|
||||
$betaVer.IncrementAndSetToPrerelease()
|
||||
if ("1.2.3-beta.5" -ne $betaVer.ToString()) {
|
||||
Write-Host "Error: Beta string did not correctly increment"
|
||||
}
|
||||
|
||||
$pythonBetaVerString = "1.2.3b4"
|
||||
$pbetaVer = [AzureEngSemanticVersion]::ParsePythonVersionString($pythonBetaVerString)
|
||||
if ($pbetaVer.Major -ne 1 -or $pbetaVer.Minor -ne 2 -or $pbetaVer.Patch -ne 3 -or $pbetaVer.PrereleaseLabel -ne "b" -or $pbetaVer.PrereleaseNumber -ne 4) {
|
||||
Write-Host "Error: Didn't correctly parse python beta string $pythonBetaVerString"
|
||||
}
|
||||
if ($pythonBetaVerString -ne $pbetaVer.ToString()) {
|
||||
Write-Host "Error: python beta string did not correctly round trip with ToString"
|
||||
}
|
||||
$pbetaVer.IncrementAndSetToPrerelease()
|
||||
if ("1.2.3b5" -ne $pbetaVer.ToString()) {
|
||||
Write-Host "Error: Python beta string did not correctly increment"
|
||||
}
|
||||
|
||||
Write-Host "QuickTests done"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user