@@ -71,85 +71,86 @@ function Set-NuspecVersion([string] $file, [string] $version) {
7171function Get-BumpedProjectVersion ([string ] $projectPath , [string ] $bumpVersion ) {
7272 [xml ]$projectXml = Get-Content - Path $projectPath
7373
74- $old = Get-ProjectVersionAndSuffix $projectXml
74+ $oldSemVer = [string ]($projectXml.Project.PropertyGroup.Version )[0 ]
75+
76+ return Get-BumpedSemanticVersion $oldSemVer $bumpVersion
77+ }
78+
79+ function Get-BumpedSemanticVersion (
80+ [string ] $semanticVersion ,
81+ [string ] $bumpVersion ,
82+ [string ] $defaultPreReleaseIdentifiers = " alpha000" ) {
83+ $match = [regex ]::Match(
84+ $semanticVersion ,
85+ ' ^(?<major>0|[1-9][0-9]*)\.(?<minor>0|[1-9][0-9]*)\.(?<patch>0|[1-9][0-9]*)(?:-(?<prerelease>[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+(?<metadata>[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$' )
86+
87+ if (! $match.Success ) {
88+ throw " Unable to parse semantic version '$semanticVersion '."
89+ }
90+
91+ $preRelease = $match.Groups [" prerelease" ].Value
92+ foreach ($identifier in $preRelease.Split (" ." , [StringSplitOptions ]::RemoveEmptyEntries)) {
93+ if ($identifier -match ' ^[0-9]+$' -and $identifier.Length -gt 1 -and $identifier.StartsWith (" 0" )) {
94+ throw " Numeric prerelease identifier '$identifier ' in '$semanticVersion ' must not contain leading zeroes."
95+ }
96+ }
97+
98+ $major = [long ]$match.Groups [" major" ].Value
99+ $minor = [long ]$match.Groups [" minor" ].Value
100+ $patch = [long ]$match.Groups [" patch" ].Value
75101
76102 switch ($bumpVersion ) {
77103 " major" {
78- $newVersion = BumpMajor $old.Version
79- $newSuffix = " "
104+ return " $ ( $major + 1 ) .0.0"
80105 }
81106 " minor" {
82- $newVersion = BumpMinor $old.Version
83- $newSuffix = " "
107+ return " $major .$ ( $minor + 1 ) .0"
84108 }
85109 " patch" {
86- $newVersion = BumpPatch $old.Version
87- $newSuffix = " "
110+ return " $major .$minor .$ ( $patch + 1 ) "
88111 }
89112 " suffix" {
90- $newVersion = $old .Version
91- $newSuffix = BumpSuffix $old .Suffix
113+ $newSuffix = BumpSuffix $ ( if ( $preRelease ) { " - $preRelease " } else { " " }) $defaultPreReleaseIdentifiers
114+ return " $major . $minor . $patch$newSuffix "
92115 }
93116 default {
94117 throw " Unrecognized 'bumpVersion' argument: $bumpVersion "
95118 }
96119 }
97-
98- $newSemVer = $newVersion.ToString () + $newSuffix
99- return $newSemVer
100- }
101-
102- function BumpMajor ([Version ] $oldVersion ) {
103- return New-Object System.Version - ArgumentList ($oldVersion.Major + 1 ), 0 , 0
104- }
105-
106- function BumpMinor ([Version ] $oldVersion ) {
107- return New-Object System.Version - ArgumentList $oldVersion.Major , ($oldVersion.Minor + 1 ), 0
108- }
109-
110- function BumpPatch ([Version ] $oldVersion ) {
111- return New-Object System.Version - ArgumentList $oldVersion.Major , $oldVersion.Minor , ($oldVersion.Build + 1 );
112120}
113121
114- function BumpSuffix ([string ] $oldSuffix ) {
122+ function BumpSuffix (
123+ [string ] $oldSuffix ,
124+ [string ] $defaultPreReleaseIdentifiers = " alpha000" ) {
115125 $oldSuffix = $oldSuffix.Trim ()
116126
117- # A suffix is a dash '-', then a sequcence of word characters followed by an optional number
118- # Example:
119- # "" => "-alpha001"
120- # "-beta" => "-beta001"
121- # "-beta1"=> "-beta002"
122- $match = [regex ]::Match($oldSuffix , ' ^-([a-zA-Z]+)(\d+)?$' );
123- $oldSuffix = $match.Groups [1 ].Value
124- if (! $oldSuffix ) {
125- $oldSuffix = " alpha"
127+ $preRelease = $oldSuffix.TrimStart (" -" )
128+ if (! $preRelease ) {
129+ $preRelease = $defaultPreReleaseIdentifiers
126130 }
127131
128- $numberGroup = $match.Groups [2 ]
129-
130- $number = if ($numberGroup.Success ) { 1 + $match.Groups [2 ].Value } else { 1 }
131-
132- # Use 3 digits for the number "-alpha003", for 999 releases lexically sorted.
133- return [string ]::Format(" -{0}{1:D3}" , $oldSuffix , $number )
134- }
135-
136- # Returns object with properties: Version, Suffix
137- function Get-ProjectVersionAndSuffix ([xml ] $projectXml ) {
132+ $identifiers = [Collections.Generic.List [string ]]::new()
133+ $identifiers.AddRange ([string []]$preRelease.Split (" ." ))
134+ $lastIdentifierIndex = $identifiers.Count - 1
135+ $lastIdentifier = $identifiers [$lastIdentifierIndex ]
138136
139- # Split "1.2.3-alpha" into ["1.2.3", "alpha"]
140- # Split "1.2.3" into ["1.2.3"]
141- $oldSemVer = $ ($projectXml.Project.PropertyGroup.Version )[0 ]
142-
143- $oldSemVerParts = $oldSemVer.Split (' -' )
144- $oldVersion = $null
145- if (-not [Version ]::TryParse($oldSemVerParts [0 ], [ref ] $oldVersion )) { throw " Unable to parse old version." }
146-
147- $oldSuffix = if ($oldSemVerParts.Length -eq 2 ) { " -" + $oldSemVerParts [1 ]} else { " " }
148- return [PSCustomObject ]@ {
149- PSTypeName = " VersionAndSuffix"
150- Version = $oldVersion
151- Suffix = $oldSuffix
137+ if ($lastIdentifier -match ' ^[0-9]+$' ) {
138+ $identifiers [$lastIdentifierIndex ] = ([long ]$lastIdentifier + 1 ).ToString()
139+ }
140+ elseif ($lastIdentifier -match ' ^(?<prefix>.*?)(?<number>[0-9]+)$' ) {
141+ $numberWidth = $Matches [" number" ].Length
142+ $number = [long ]$Matches [" number" ] + 1
143+ $identifiers [$lastIdentifierIndex ] = $Matches [" prefix" ] + $number.ToString (" D$numberWidth " )
152144 }
145+ elseif ($identifiers.Count -eq 1 ) {
146+ # Preserve the repository's existing alpha001/beta001 suffix convention.
147+ $identifiers [0 ] += " 001"
148+ }
149+ else {
150+ $identifiers.Add (" 1" )
151+ }
152+
153+ return " -" + [string ]::Join(" ." , $identifiers )
153154}
154155
155156function Resolve-Error ($ErrorRecord = $Error [0 ])
@@ -169,6 +170,7 @@ function Resolve-Error ($ErrorRecord=$Error[0])
169170}
170171
171172export-modulemember - function Get-NewProjectVersion ,
173+ Get-BumpedSemanticVersion ,
172174 Invoke-CommitVersionBump ,
173175 Invoke-TagVersionBump ,
174176 Set-ProjectVersion ,
0 commit comments