-
Notifications
You must be signed in to change notification settings - Fork 3
/
version.ps1
142 lines (122 loc) · 5.03 KB
/
version.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
###
# SmVer version generator based on current commit.
#
# Requires to enable these Git features: unshallow fetch, fetch tags. Output difer from the Git environment:
#
# - If the tag is added on the current commit, output follows <version core>, or <version core> "+" <build>.
# - If the tag is added on an ancestor, this build is treaten as a pre-release, output follows <version core> "-" <pre-release>, or <version core> "-" <pre-release> "+" <build>. The pre-release is greater than the previous commit. Choice between patch, minor or major version increment is stored in the ".version" file.
#
# Parameters:
#
# -m Displays build metadata (<version core> "+" <build>, or <version core> "-" <pre-release> "+" <build>)
# -c Cache the date contained in the metadata. Data is stored in the ".version.cache" file. Alloys re-executing the command multiple times with a reproductible response, like in CI/CD environment.
# -w Compatibility for Windows MSX build, use a 0-65535 numbers for the pre-release tag.
#
# Usage:
#
# - Without metadata: "./cicd/version.ps1"
# - With metadata: "./cicd/version.ps1 -b"
#
# See: https://semver.org/#backusnaur-form-grammar-for-valid-semver-versions
###
param(
[string]
[Parameter(Mandatory = $true, HelpMessage = "Repository path")]
[Alias("g")]
$repo_path,
[switch]
[Parameter(Mandatory = $false, HelpMessage = "Displays build metadata (<version core> '+' <build>, or <version core> '-' <pre-release> '+' <build>)")]
[Alias("m")]
$metadata,
[switch]
[Parameter(Mandatory = $false, HelpMessage = "Cache the date contained in the metadata. Data is stored in the '.version.cache' file. Alloys re-executing the command multiple times with a reproductible response, like in CI/CD environment.")]
[Alias("c")]
$cache,
[switch]
[Parameter(Mandatory = $false, HelpMessage = "Compatibility for Windows MSX build, use a 0-65535 numbers for the pre-release tag.")]
[Alias("w")]
$windows
)
if ($null -eq $(git tag --merged HEAD 'v[0-9]*.[0-9]*.[0-9]*')) {
Write-Output "Error: no tag found, use 'git tag v0.0.0'"
exit 1
}
$version_file = "${repo_path}/.version.config"
if (Test-Path $version_file) {
$version_config = Get-Content $version_file
} else {
$version_config = "patch"
$version_config | Out-File $version_file
}
$cache_file = "${repo_path}/.version.cache"
$latest_tag_raw = $(git describe --all --abbrev=0 --match "v[0-9]*.[0-9]*.[0-9]*" --candidates=10000)
$latest_tag_matches = Select-String "^tags/v([0-9]+).([0-9]+).([0-9]+)" -inputobject $latest_tag_raw
$latest_tag_x = [int] $latest_tag_matches.Matches.Groups[1].Value
$latest_tag_y = [int] $latest_tag_matches.Matches.Groups[2].Value
$latest_tag_z = [int] $latest_tag_matches.Matches.Groups[3].Value
$count_from_tag = [int] $(git rev-list HEAD ^$latest_tag_raw --count --ancestry-path --no-merges)
if ($count_from_tag -eq 0) {
# <version core>
$base_smver = "$latest_tag_x.$latest_tag_y.$latest_tag_z"
} else {
# Remove all the zeros at the leading zeros, as this is not compliant with SmVer
$commit_id = git rev-parse --short HEAD | ForEach-Object { $_ -replace '^0*', '' }
$prerelease_smver = "$count_from_tag.$commit_id"
switch ($version_config) {
"major" {
$latest_tag_x++
$latest_tag_y = 0
$latest_tag_z = 0
break
}
"minor" {
$latest_tag_y++
$latest_tag_z = 0
break
}
"patch" {
$latest_tag_z++
break
}
default {
throw "Unknown version config: $version_config"
}
}
# Windows MSX binaries do not support characters in the pre-release tag, only 0-65535 numbers
if ($windows -eq $true) {
# Generate the MD5 hash of the string
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = New-Object -TypeName System.Text.UTF8Encoding
$hash = $md5.ComputeHash($utf8.GetBytes($prerelease_smver))
$hash_string = [System.BitConverter]::ToString($hash).Replace('-', '').ToUpper()
# Define a function for calculating the modulo
function BigInteger-Modulo {
param (
[Parameter(Mandatory=$true)] [string] $HexString,
[Parameter(Mandatory=$true)] [int] $Modulo
)
$result = 0
for ($i = 0; $i -lt $HexString.Length; $i++) {
$digit = [Convert]::ToInt32($HexString[$i], 16)
$result = ($result * 16 + $digit) % $Modulo
}
return $result
}
# Convert the hexadecimal hash to a decimal number, apply modulo 65536 operation and print the result
$prerelease_smver = BigInteger-Modulo -HexString $hash_string -Modulo 65536
}
# <version core> "-" <pre-release>
$base_smver = "$latest_tag_x.$latest_tag_y.$latest_tag_z-$prerelease_smver"
}
if ( $metadata -eq $true ) {
if ( $cache -eq $true -and (Test-Path $cache_file) ) {
$build_date = Get-Content $cache_file
} else {
$build_date = (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmmss")
Set-Content $cache_file $build_date
}
$metadata_smver = $build_date
Write-Output "$base_smver+$metadata_smver"
} else {
Write-Output "$base_smver"
}