diff --git a/AU/Private/AUVersion.ps1 b/AU/Private/AUVersion.ps1 index ba57070d..8e5587c2 100644 --- a/AU/Private/AUVersion.ps1 +++ b/AU/Private/AUVersion.ps1 @@ -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 = '(?\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 = '(?\d+(?:\.\d+){1,3})' if ($strict) { + $identifierPattern = "[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*" return "^$versionPattern(?:-(?$identifierPattern))?(?:\+(?$identifierPattern))?`$" } else { - return "$versionPattern(?:-?(?$identifierPattern))?(?:\+(?$identifierPattern))?" + $identifierPattern = "[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+| \d+)*" + return "$versionPattern(?:[- ]*(?$identifierPattern))?(?:[+ *](?$identifierPattern))?" } } diff --git a/AU/Public/Get-Version.ps1 b/AU/Public/Get-Version.ps1 index 2e727695..1171dd73 100644 --- a/AU/Public/Get-Version.ps1 +++ b/AU/Public/Get-Version.ps1 @@ -2,7 +2,7 @@ <# .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 @@ -10,15 +10,46 @@ 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) } diff --git a/tests/Get-Version.Tests.ps1 b/tests/Get-Version.Tests.ps1 index 39551622..c99f677b 100644 --- a/tests/Get-Version.Tests.ps1 +++ b/tests/Get-Version.Tests.ps1 @@ -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' { @@ -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) + } } }