Skip to content

Commit 77d00d1

Browse files
niheavenAsh258ddavness
authored
refactor(versions): Refactor 'versions.ps1' (#3721)
Co-authored-by: Jakub Čábera <cabera.jakub@gmail.com> Co-authored-by: David Duque <david.f.s.duque@tecnico.ulisboa.pt>
1 parent ef3bf14 commit 77d00d1

14 files changed

+360
-76
lines changed

bin/checkver.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ while ($in_progress -gt 0) {
292292

293293
Write-Host $ver -ForegroundColor DarkRed -NoNewline
294294
Write-Host " (scoop version is $expected_ver)" -NoNewline
295-
$update_available = (compare_versions $expected_ver $ver) -eq -1
295+
$update_available = (Compare-Version -ReferenceVersion $ver -DifferenceVersion $expected_ver) -ne 0
296296

297297
if ($json.autoupdate -and $update_available) {
298298
Write-Host ' autoupdate available' -ForegroundColor Cyan

bin/uninstall.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ $errors = $false
3434

3535
# Uninstall given app
3636
function do_uninstall($app, $global) {
37-
$version = current_version $app $global
37+
$version = Select-CurrentVersion -AppName $app -Global:$global
3838
$dir = versiondir $app $version $global
3939
$manifest = installed_manifest $app $version $global
4040
$install = install_info $app $version $global

lib/core.ps1

+10-6
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ function Test-Aria2Enabled {
290290
function app_status($app, $global) {
291291
$status = @{}
292292
$status.installed = (installed $app $global)
293-
$status.version = current_version $app $global
293+
$status.version = Select-CurrentVersion -AppName $app -Global:$global
294294
$status.latest_version = $status.version
295295

296296
$install_info = install_info $app $status.version $global
@@ -300,22 +300,26 @@ function app_status($app, $global) {
300300

301301
$manifest = manifest $app $install_info.bucket $install_info.url
302302
$status.removed = (!$manifest)
303-
if($manifest.version) {
303+
if ($manifest.version) {
304304
$status.latest_version = $manifest.version
305305
}
306306

307307
$status.outdated = $false
308-
if($status.version -and $status.latest_version) {
309-
$status.outdated = ((compare_versions $status.latest_version $status.version) -gt 0)
308+
if ($status.version -and $status.latest_version) {
309+
if (get_config 'force-update' $false) {
310+
$status.outdated = ((Compare-Version -ReferenceVersion $status.version -DifferenceVersion $status.latest_version) -ne 0)
311+
} else {
312+
$status.outdated = ((Compare-Version -ReferenceVersion $status.version -DifferenceVersion $status.latest_version) -gt 0)
313+
}
310314
}
311315

312316
$status.missing_deps = @()
313317
$deps = @(runtime_deps $manifest) | Where-Object {
314318
$app, $bucket, $null = parse_app $_
315319
return !(installed $app)
316320
}
317-
if($deps) {
318-
$status.missing_deps += ,$deps
321+
if ($deps) {
322+
$status.missing_deps += , $deps
319323
}
320324

321325
return $status

lib/versions.ps1

+252-31
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,274 @@
11
# versions
2-
function latest_version($app, $bucket, $url) {
3-
(manifest $app $bucket $url).version
4-
}
5-
function current_version($app, $global) {
6-
@(versions $app $global)[-1]
2+
function Get-LatestVersion {
3+
<#
4+
.SYNOPSIS
5+
Get latest version of app from manifest
6+
.PARAMETER AppName
7+
App's name
8+
.PARAMETER Bucket
9+
Bucket which the app belongs to
10+
.PARAMETER Uri
11+
Remote app manifest's URI
12+
#>
13+
[OutputType([String])]
14+
[CmdletBinding()]
15+
param (
16+
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
17+
[Alias('App')]
18+
[String]
19+
$AppName,
20+
[Parameter(Position = 1)]
21+
[String]
22+
$Bucket,
23+
[Parameter(Position = 2)]
24+
[String]
25+
$Uri
26+
)
27+
process {
28+
return (manifest $AppName $Bucket $Uri).version
29+
}
730
}
8-
function versions($app, $global) {
9-
$appdir = appdir $app $global
10-
if(!(test-path $appdir)) { return @() }
1131

12-
sort_versions (Get-ChildItem $appdir -dir -attr !reparsePoint | Where-Object { $null -ne $(Get-ChildItem $_.fullname) } | ForEach-Object { $_.name })
32+
function Select-CurrentVersion {
33+
<#
34+
.SYNOPSIS
35+
Select current version of installed app, from 'current\manifest.json' or modified time of version directory
36+
.PARAMETER AppName
37+
App's name
38+
.PARAMETER Global
39+
Globally installed application
40+
#>
41+
[OutputType([String])]
42+
[CmdletBinding()]
43+
param (
44+
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
45+
[Alias('App')]
46+
[String]
47+
$AppName,
48+
[Parameter(Position = 1)]
49+
[Switch]
50+
$Global
51+
)
52+
process {
53+
$appPath = appdir $AppName $Global
54+
if (Test-Path "$appPath\current" -PathType Container) {
55+
$currentVersion = (installed_manifest $AppName 'current' $Global).version
56+
if ($currentVersion -eq 'nightly') {
57+
$currentVersion = (Get-Item "$appPath\current").Target | Split-Path -Leaf
58+
}
59+
} else {
60+
$installedVersion = Get-InstalledVersion -AppName $AppName -Global:$Global
61+
if ($installedVersion) {
62+
$currentVersion = $installedVersion[-1]
63+
} else {
64+
$currentVersion = $null
65+
}
66+
}
67+
return $currentVersion
68+
}
1369
}
1470

15-
function version($ver) {
16-
$ver -split '[\.-]' | ForEach-Object {
17-
$num = $_ -as [int]
18-
if($num) { $num } else { $_ }
71+
function Get-InstalledVersion {
72+
<#
73+
.SYNOPSIS
74+
Get all installed version of app, by checking version directories' 'install.json'
75+
.PARAMETER AppName
76+
App's name
77+
.PARAMETER Global
78+
Globally installed application
79+
.NOTES
80+
Versions are sorted from oldest to newest, i.e., latest installed version is the last one in the output array.
81+
If no installed version found, empty array will be returned.
82+
#>
83+
[OutputType([Object[]])]
84+
[CmdletBinding()]
85+
param (
86+
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
87+
[Alias('App')]
88+
[String]
89+
$AppName,
90+
[Parameter(Position = 1)]
91+
[Switch]
92+
$Global
93+
)
94+
process {
95+
$appPath = appdir $AppName $Global
96+
if (Test-Path $appPath) {
97+
$versions = @((Get-ChildItem "$appPath\*\install.json" | Sort-Object -Property LastWriteTimeUtc).Directory.Name)
98+
return $versions | Where-Object { ($_ -ne 'current') -and ($_ -notlike '_*.old*') }
99+
} else {
100+
return @()
101+
}
19102
}
103+
# Deprecated
104+
# sort_versions (Get-ChildItem $appPath -dir -attr !reparsePoint | Where-Object { $null -ne $(Get-ChildItem $_.FullName) } | ForEach-Object { $_.Name })
20105
}
21-
function compare_versions($a, $b) {
22-
$ver_a = @(version $a)
23-
$ver_b = @(version $b)
24106

25-
for($i=0;$i -lt $ver_a.length;$i++) {
26-
if($i -gt $ver_b.length) { return 1; }
107+
function Compare-Version {
108+
<#
109+
.SYNOPSIS
110+
Compare versions, mainly according to SemVer's rules
111+
.PARAMETER ReferenceVersion
112+
Specifies a version used as a reference for comparison
113+
.PARAMETER DifferenceVersion
114+
Specifies the version that are compared to the reference version
115+
.PARAMETER Delimiter
116+
Specifies the delimiter of versions
117+
.OUTPUTS
118+
System.Int32
119+
'0' if DifferenceVersion is equal to ReferenceVersion,
120+
'1' if DifferenceVersion is greater then ReferenceVersion,
121+
'-1' if DifferenceVersion is less then ReferenceVersion
122+
#>
123+
[OutputType([Int32])]
124+
[CmdletBinding()]
125+
param (
126+
[Parameter(Mandatory = $true, Position = 0)]
127+
[AllowEmptyString()]
128+
[String]
129+
$ReferenceVersion,
130+
[Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)]
131+
[AllowEmptyString()]
132+
[String]
133+
$DifferenceVersion,
134+
[String]
135+
$Delimiter = '-'
136+
)
137+
process {
138+
# Use '+' sign as post-release, see https://github.com/lukesampson/scoop/pull/3721#issuecomment-553718093
139+
$ReferenceVersion, $DifferenceVersion = @($ReferenceVersion, $DifferenceVersion) -replace '\+', '-'
27140

28-
# don't try to compare int to string
29-
if($ver_b[$i] -is [string] -and $ver_a[$i] -isnot [string]) {
30-
$ver_a[$i] = "$($ver_a[$i])"
141+
# Return 0 if versions are equal
142+
if ($DifferenceVersion -eq $ReferenceVersion) {
143+
return 0
31144
}
32145

33-
if($ver_a[$i] -gt $ver_b[$i]) { return 1; }
34-
if($ver_a[$i] -lt $ver_b[$i]) { return -1; }
146+
# Preprocess versions (split, convert and separate)
147+
$splitReferenceVersion = @(SplitVersion -Version $ReferenceVersion -Delimiter $Delimiter)
148+
$splitDifferenceVersion = @(SplitVersion -Version $DifferenceVersion -Delimiter $Delimiter)
149+
150+
# Nightly versions are always equal
151+
if ($splitReferenceVersion[0] -eq 'nightly' -and $splitDifferenceVersion[0] -eq 'nightly') {
152+
return 0
153+
}
154+
155+
for ($i = 0; $i -lt [Math]::Max($splitReferenceVersion.Length, $splitDifferenceVersion.Length); $i++) {
156+
# '1.1-alpha' is less then '1.1'
157+
if ($i -ge $splitReferenceVersion.Length) {
158+
if ($splitDifferenceVersion[$i] -match 'alpha|beta|rc|pre') {
159+
return -1
160+
} else {
161+
return 1
162+
}
163+
}
164+
# '1.1' is greater then '1.1-beta'
165+
if ($i -ge $splitDifferenceVersion.Length) {
166+
if ($splitReferenceVersion[$i] -match 'alpha|beta|rc|pre') {
167+
return 1
168+
} else {
169+
return -1
170+
}
171+
}
172+
173+
# If some parts of versions have '.', compare them with delimiter '.'
174+
if (($splitReferenceVersion[$i] -match '\.') -or ($splitDifferenceVersion[$i] -match '\.')) {
175+
$Result = Compare-Version -ReferenceVersion $splitReferenceVersion[$i] -DifferenceVersion $splitDifferenceVersion[$i] -Delimiter '.'
176+
# If the parts are equal, continue to next part, otherwise return
177+
if ($Result -ne 0) {
178+
return $Result
179+
} else {
180+
continue
181+
}
182+
}
183+
184+
# Don't try to compare [Long] to [String]
185+
if ($null -ne $splitReferenceVersion[$i] -and $null -ne $splitDifferenceVersion[$i]) {
186+
if ($splitReferenceVersion[$i] -is [String] -and $splitDifferenceVersion[$i] -isnot [String]) {
187+
$splitDifferenceVersion[$i] = "$($splitDifferenceVersion[$i])"
188+
}
189+
if ($splitDifferenceVersion[$i] -is [String] -and $splitReferenceVersion[$i] -isnot [String]) {
190+
$splitReferenceVersion[$i] = "$($splitReferenceVersion[$i])"
191+
}
192+
}
193+
194+
# Compare [String] or [Long]
195+
if ($splitDifferenceVersion[$i] -gt $splitReferenceVersion[$i]) {
196+
return 1
197+
}
198+
if ($splitDifferenceVersion[$i] -lt $splitReferenceVersion[$i]) {
199+
return -1
200+
}
201+
}
35202
}
36-
if($ver_b.length -gt $ver_a.length) { return -1 }
37-
return 0
38203
}
39204

205+
# Helper function
206+
function SplitVersion {
207+
<#
208+
.SYNOPSIS
209+
Split version by Delimiter, convert number string to number, and separate letters from numbers
210+
.PARAMETER Version
211+
Specifies a version
212+
.PARAMETER Delimiter
213+
Specifies the delimiter of version (Literal)
214+
#>
215+
[OutputType([Object[]])]
216+
[CmdletBinding()]
217+
param (
218+
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
219+
[AllowEmptyString()]
220+
[String]
221+
$Version,
222+
[String]
223+
$Delimiter = '-'
224+
)
225+
process {
226+
$Version = $Version -replace '[a-zA-Z]+', "$Delimiter$&$Delimiter"
227+
return ($Version -split [Regex]::Escape($Delimiter) -ne '' | ForEach-Object { if ($_ -match '^\d+$') { [Long]$_ } else { $_ } })
228+
}
229+
}
230+
231+
# Deprecated
232+
# Not used anymore in scoop core
40233
function qsort($ary, $fn) {
41-
if($null -eq $ary) { return @() }
42-
if(!($ary -is [array])) { return @($ary) }
234+
warn '"qsort" is deprecated. Please avoid using it anymore.'
235+
if ($null -eq $ary) { return @() }
236+
if (!($ary -is [array])) { return @($ary) }
43237

44238
$pivot = $ary[0]
45-
$rem = $ary[1..($ary.length-1)]
239+
$rem = $ary[1..($ary.length - 1)]
46240

47-
$lesser = qsort ($rem | Where-Object { (& $fn $_ $pivot) -lt 0 }) $fn
241+
$lesser = qsort ($rem | Where-Object { (& $fn $pivot $_) -lt 0 }) $fn
48242

49-
$greater = qsort ($rem | Where-Object { (& $fn $_ $pivot) -ge 0 }) $fn
243+
$greater = qsort ($rem | Where-Object { (& $fn $pivot $_) -ge 0 }) $fn
50244

51245
return @() + $lesser + @($pivot) + $greater
52246
}
53-
function sort_versions($versions) { qsort $versions compare_versions }
247+
248+
# Deprecated
249+
# Not used anymore in scoop core
250+
function sort_versions($versions) {
251+
warn '"sort_versions" is deprecated. Please avoid using it anymore.'
252+
qsort $versions Compare-Version
253+
}
254+
255+
function compare_versions($a, $b) {
256+
Show-DeprecatedWarning $MyInvocation 'Compare-Version'
257+
# Please note the parameters' sequence
258+
return Compare-Version -ReferenceVersion $b -DifferenceVersion $a
259+
}
260+
261+
function latest_version($app, $bucket, $url) {
262+
Show-DeprecatedWarning $MyInvocation 'Get-LatestVersion'
263+
return Get-LatestVersion -AppName $app -Bucket $bucket -Uri $url
264+
}
265+
266+
function current_version($app, $global) {
267+
Show-DeprecatedWarning $MyInvocation 'Select-CurrentVersion'
268+
return Select-CurrentVersion -AppName $app -Global:$global
269+
}
270+
271+
function versions($app, $global) {
272+
Show-DeprecatedWarning $MyInvocation 'Get-InstalledVersion'
273+
return Get-InstalledVersion -AppName $app -Global:$global
274+
}

libexec/scoop-cleanup.ps1

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ if ($global -and !(is_admin)) {
3131
}
3232

3333
function cleanup($app, $global, $verbose, $cache) {
34-
$current_version = current_version $app $global
34+
$current_version = Select-CurrentVersion -AppName $app -Global:$global
3535
if ($cache) {
3636
Remove-Item "$cachedir\$app#*" -Exclude "$app#$current_version#*"
3737
}
38-
$versions = versions $app $global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
38+
$versions = Get-InstalledVersion -AppName $app -Global:$global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
3939
if (!$versions) {
4040
if ($verbose) { success "$app is already clean" }
4141
return

libexec/scoop-export.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ if($apps) {
2323
$apps | Sort-Object { $_.name } | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
2424
$app = $_.name
2525
$global = $_.global
26-
$ver = current_version $app $global
26+
$ver = Select-CurrentVersion -AppName $app -Global:$global
2727
$global_display = $null; if($global) { $global_display = ' *global*'}
2828

2929
$install_info = install_info $app $ver $global

libexec/scoop-info.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Write-Output "Manifest:`n $manifest_file"
8585
if($status.installed) {
8686
# Show installed versions
8787
Write-Output "Installed:"
88-
$versions = versions $app $global
88+
$versions = Get-InstalledVersion -AppName $app -Global:$global
8989
$versions | ForEach-Object {
9090
$dir = versiondir $app $_ $global
9191
if($global) { $dir += " *global*" }

0 commit comments

Comments
 (0)