Skip to content

Instantly share code, notes, and snippets.

@LindnerBrewery
Last active November 17, 2022 09:10
Show Gist options
  • Save LindnerBrewery/ecd3773f7c174baed4e6e8c61d1e27aa to your computer and use it in GitHub Desktop.
Save LindnerBrewery/ecd3773f7c174baed4e6e8c61d1e27aa to your computer and use it in GitHub Desktop.
Get-NormalizedVersion
function Get-NormalizedVersion {
<#
.SYNOPSIS
Normalizes a Version according to semantic versioning v2
.DESCRIPTION
Normalizes a Version according to semantic versioning v2. The function accepts a version as a string and will try to normalize it.
It will return a string representing at least major.minor.patch. If revision is 0 it will be dropped, unless is has a prerelease or buildmetadata.
1 -> 1.0.0
1.1 -> 1.1.0
1.1.1.0 -> 1.1.1
1.1.1.1 -> 1.1.1.1
1-Alpha -> 1.0.0-Alpha
1.1.0.0-RC -> 1.1.0.0-RC
.EXAMPLE
PS C:\> Get-NormalizedVersion -Version 1.0
1.0.0
#>
[CmdletBinding()]
param (
[String]$Version
)
begin {}
process {
$normVersion = $null
$regexPattern = '^(?<major>0|[0-9]\d*)?(?:\.(?<minor>0|[0-9]\d*))?(?:\.(?<patch>0|[0-9]\d*))?(?:\.(?<build>0|[0-9]\d*))?(?:-(?<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
$result = [Regex]::Match($Version, $regexPattern)
# throw error if version not valid
if (! $result.Success) {
Throw "$Version is not a valid semantic version"
}
# if version is a prerelease or has build metadata then return original version
if ($result.Groups[5].Success -or $result.Groups[6].Success) {
# Check if minor, patch exists. If not set them to 0
if ($result.Groups[2].Success) {
$minor = $result.Groups[2].Value
}
else {
$minor = 0
}
if ($result.Groups[3].Success) {
$patch = $result.Groups[3].Value
}
else {
$patch = 0
}
if ($result.Groups[4].Success) {
$revision = $result.Groups[4].Value
}
$normVersion = [version]::new($result.groups[1].Value, $minor, $patch)
if ($result.Groups[4].Success) {
$normVersion = [System.Version]::Parse("$($normVersion).$($result.groups[4].Value)")
}
#convert normalized version to String
$versionString = $normVersion.ToString()
if ($result.groups[5].Value) {
Write-Verbose "Version has prerelease tag"
$versionString += "-" + $result.groups[5].Value
}
if ($result.groups[6].Value) {
Write-Verbose "Version has buildmetadata tag"
$versionString += "-" + $result.groups[6].Value
}
return $versionString
}
else {
# normalize the major minor and patch
Write-Verbose "Normalizing version"
$normVersion = [version]::new($result.groups[1].Value, $result.groups[2].Value, $result.groups[3].Value)
$rev = $result.groups[4].Value
if ($rev -gt 0) {
Write-Verbose "Revision ($rev) is not 0 and will be preserved"
$normVersion = [System.Version]::Parse("$($normVersion).$($result.groups[4].Value)")
}
elseif ($rev -eq 0) {
Write-Verbose "Revision is 0 and will be removed from the normalized version"
}
return $normVersion.ToString()
}
}
end {}
}
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Scope='Function')]
Param()
BeforeAll {
. $PSCommandPath.Replace('.Tests.ps1','.ps1')
}
Describe Get-NormalizedVersion -Tag Unit{
Context 'Basic tests' {
It "1 -> 1.0.0" {
Get-NormalizedVersion 1 | Should -Be '1.0.0'
}
It "1.1 -> 1.1.0" {
Get-NormalizedVersion 1.1 | Should -Be '1.1.0'
}
It "1.1.1.0 -> 1.1.1" {
Get-NormalizedVersion 1.1.1.0 | Should -Be '1.1.1'
}
It "1.1.1.1 -> 1.1.1.1" {
Get-NormalizedVersion 1.1.1.1 | Should -Be '1.1.1.1'
}
It "1-Alpha -> 1.0.0-Alpha" {
Get-NormalizedVersion 1-Alpha | Should -Be '1.0.0-Alpha'
}
It "1.1.0.0-RC -> 1.1.0.0-RC" {
Get-NormalizedVersion 1.1.0.0-RC | Should -Be '1.1.0.0-RC'
}
It "01.01.0.0-RC -> 1.1.0.0-RC" {
Get-NormalizedVersion 01.01.0.0-RC | Should -Be '1.1.0.0-RC'
}
It "022.01.05.06 -> 22.1.5.6" {
Get-NormalizedVersion 022.01.05.06 | Should -Be '22.1.5.6'
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment