Skip to content

Commit

Permalink
Improve Get-Version to handle more cases and to have a more comprehen…
Browse files Browse the repository at this point in the history
…sive documentation
  • Loading branch information
Thomas committed Feb 4, 2018
1 parent 67975fc commit dad6be9
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 15 deletions.
20 changes: 13 additions & 7 deletions AU/Private/AUVersion.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,26 @@ class AUVersion : System.IComparable {
if ($input -notmatch $pattern) { return $false }
$reference = [ref] $null
if (![version]::TryParse($Matches['version'], $reference)) { return $false }
$result.Value = [AUVersion]::new($reference.Value, $Matches['prerelease'], $Matches['buildMetadata'])
$pr = $Matches['prerelease']
$bm = $Matches['buildMetadata']
if ($pr -and !$strict) { $pr = $pr.Replace(' ', '.') }
if ($bm -and !$strict) { $bm = $bm.Replace(' ', '.') }
# for now, chocolatey does only support SemVer v1 (no dot separated identifiers in pre-release):
if ($pr) { $pr = $pr.Replace('.', '') }
if ($bm) { $bm = $bm.Replace('.', '') }
#
$result.Value = [AUVersion]::new($reference.Value, $pr, $bm)
return $true
}

hidden static [string] GetPattern([bool] $strict) {
$versionPattern = '(?<version>\d+(?:\.\d+){0,3})'
# for now, chocolatey does only support SemVer v1 (no dot separated identifiers in pre-release):
$identifierPattern = "[0-9A-Za-z-]+"
# here is the SemVer v2 equivalent:
#$identifierPattern = "[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*"
$versionPattern = '(?<version>\d+(?:\.\d+){1,3})'
if ($strict) {
$identifierPattern = "[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*"
return "^$versionPattern(?:-(?<prerelease>$identifierPattern))?(?:\+(?<buildMetadata>$identifierPattern))?`$"
} else {
return "$versionPattern(?:-?(?<prerelease>$identifierPattern))?(?:\+(?<buildMetadata>$identifierPattern))?"
$identifierPattern = "[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+| \d+)*"
return "$versionPattern(?:[- ]*(?<prerelease>$identifierPattern))?(?:[+ *](?<buildMetadata>$identifierPattern))?"
}
}

Expand Down
39 changes: 35 additions & 4 deletions AU/Public/Get-Version.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,54 @@

<#
.SYNOPSIS
Get a semver-like object from a given version string.
Parses a semver-like object from a string in a flexible manner.
.DESCRIPTION
This function parses a string containing a semver-like version
and returns an object that represents both the version (with up to 4 parts)
and optionally a pre-release and a build metadata.
The parsing is quite flexible:
- the string can starts with a 'v'
- the version can be in the middle of a url or sentence
- first version found is returned
- there can be no hyphen between the version and the pre-release
- extra spaces (between any parts of the semver-like version) are ignored
- extra spaces are ignored
- optional delimiters can be provided to help parsing the string
.EXAMPLE
Get-Version 'Last version: 1.2.3 beta 3.'
Returns 1.2.3-beta3
.EXAMPLE
Get-Version 'https://github.com/atom/atom/releases/download/v1.24.0-beta2/AtomSetup.exe'
Return 1.24.0-beta2
.EXAMPLE
Get-Version 'http://mirrors.kodi.tv/releases/windows/win32/kodi-17.6-Krypton-x86.exe' -Delimiter '-'
Return 17.6
#>
function Get-Version {
[CmdletBinding()]
param(
# Version string to parse.
[string] $Version
[Parameter(Mandatory=$true)]
[string] $Version,
# Optional delimiter(s) to help locate the version in the string: the version must start and end with one of these chars.
[char[]] $Delimiter
)
if ($Delimiter) {
$delimiters = $Delimiter -join ''
@('\', ']', '^', '-') | % { $delimiters = $delimiters.Replace($_, "\$_") }
$regex = $Version | Select-String -Pattern "[$delimiters](\d+\.\d+[^$delimiters]*)[$delimiters]" -AllMatches
foreach ($match in $regex.Matches) {
$reference = [ref] $null
if ([AUVersion]::TryParse($match.Groups[1], $reference, $false)) {
return $reference.Value
}
}
}
return [AUVersion]::Parse($Version, $false)
}
42 changes: 38 additions & 4 deletions tests/Get-Version.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ Describe 'Get-Version' -Tag getversion {

It 'should not convert a non-strict version' {
{ ConvertTo-AUVersion '1.2.3.4a' } | Should Throw
# for now, chocolatey does only support SemVer v1 (no dot separated identifiers in pre-release):
{ ConvertTo-AUVersion 'v1.2.3.4-beta1+xyz001' } | Should Throw
# here is the SemVer v2 equivalent:
#{ ConvertTo-AUVersion 'v1.2.3.4-beta.1+xyz.001' } | Should Throw
{ ConvertTo-AUVersion 'v1.2.3.4-beta.1+xyz.001' } | Should Throw
}

It 'should parse a non strict version' {
Expand Down Expand Up @@ -107,5 +104,42 @@ Describe 'Get-Version' -Tag getversion {
$version = [AUVersion] $Value
$version | Should Not BeNullOrEmpty
}

$testCases = @(
@{Value = '1.2-beta.3' ; ExpectedResult = '1.2-beta3'}
@{Value = '1.2+xyz.4' ; ExpectedResult = '1.2+xyz4'}
@{Value = '1.2-beta.3+xyz.4' ; ExpectedResult = '1.2-beta3+xyz4'}
)

It 'converts semver v2 to semver v1' -TestCases $testCases { param($Value, $ExpectedResult)
$version = [AUVersion] $Value
$version | Should Be ([AUVersion] $ExpectedResult)
}

$testCases = @(
@{ExpectedResult = '5.4.9' ; Delimiter = '-' ; Value = 'http://dl.airserver.com/pc32/AirServer-5.4.9-x86.msi'}
@{ExpectedResult = '1.24.0-beta2' ; Value = 'https://github.com/atom/atom/releases/download/v1.24.0-beta2/AtomSetup.exe'}
@{ExpectedResult = '2.4.0.24-beta' ; Value = 'https://github.com/gurnec/HashCheck/releases/download/v2.4.0.24-beta/HashCheckSetup-v2.4.0.24-beta.exe'}
@{ExpectedResult = '2.0.9' ; Value = 'http://www.ltr-data.se/files/imdiskinst_2.0.9.exe'}
@{ExpectedResult = '17.6' ; Delimiter = '-' ; Value = 'http://mirrors.kodi.tv/releases/windows/win32/kodi-17.6-Krypton-x86.exe'}
@{ExpectedResult = '0.70.2' ; Value = 'https://github.com/Nevcairiel/LAVFilters/releases/download/0.70.2/LAVFilters-0.70.2-Installer.exe'}
@{ExpectedResult = '2.2.0-1' ; Value = 'https://files.kde.org/marble/downloads/windows/Marble-setup_2.2.0-1_x64.exe'}
@{ExpectedResult = '2.3.2' ; Value = 'https://github.com/sabnzbd/sabnzbd/releases/download/2.3.2/SABnzbd-2.3.2-win-setup.exe'}
@{ExpectedResult = '1.9' ; Delimiter = '-' ; Value = 'http://download.serviio.org/releases/serviio-1.9-win-setup.exe'}
@{ExpectedResult = '0.17.0' ; Value = 'https://github.com/Stellarium/stellarium/releases/download/v0.17.0/stellarium-0.17.0-win32.exe'}
@{ExpectedResult = '5.24.3.1' ; Value = 'http://strawberryperl.com/download/5.24.3.1/strawberry-perl-5.24.3.1-32bit.msi'}
@{ExpectedResult = '3.5.4' ; Value = 'https://github.com/SubtitleEdit/subtitleedit/releases/download/3.5.4/SubtitleEdit-3.5.4-Setup.zip'}
# for now, chocolatey does only support SemVer v1 (no dot separated identifiers in pre-release):
@{ExpectedResult = '1.2.3-beta4' ; Value = 'v 1.2.3 beta 4'}
@{ExpectedResult = '1.2.3-beta3' ; Value = 'Last version: 1.2.3 beta 3.'}
# here is the SemVer v2 equivalent:
#@{ExpectedResult = '1.2.3-beta.4' ; Value = 'v 1.2.3 beta 4'}
#@{ExpectedResult = '1.2.3-beta.3' ; Value = 'Last version: 1.2.3 beta 3.'}
)

It 'should parse any non strict version' -TestCases $testCases { param($Value, $Delimiter, $ExpectedResult)
$version = Get-Version $Value -Delimiter $Delimiter
$version | Should Be ([AUVersion] $ExpectedResult)
}
}
}

0 comments on commit dad6be9

Please sign in to comment.