Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(versions): Refactor 'versions.ps1' #3721

Merged
merged 23 commits into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/checkver.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ while ($in_progress -gt 0) {

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

if ($json.autoupdate -and $update_available) {
Write-Host ' autoupdate available' -ForegroundColor Cyan
Expand Down
2 changes: 1 addition & 1 deletion bin/uninstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ $errors = $false

# Uninstall given app
function do_uninstall($app, $global) {
$version = current_version $app $global
$version = Select-CurrentVersion -AppName $app -Global:$global
$dir = versiondir $app $version $global
$manifest = installed_manifest $app $version $global
$install = install_info $app $version $global
Expand Down
4 changes: 2 additions & 2 deletions lib/core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ function Test-Aria2Enabled {
function app_status($app, $global) {
$status = @{}
$status.installed = (installed $app $global)
$status.version = current_version $app $global
$status.version = Select-CurrentVersion -AppName $app -Global:$global
$status.latest_version = $status.version

$install_info = install_info $app $status.version $global
Expand All @@ -305,7 +305,7 @@ function app_status($app, $global) {

$status.outdated = $false
if($status.version -and $status.latest_version) {
$status.outdated = ((compare_versions $status.latest_version $status.version) -gt 0)
$status.outdated = ((Compare-Version -ReferenceVersion $status.version -DifferenceVersion $status.latest_version) -ne 0)
}

$status.missing_deps = @()
Expand Down
2 changes: 1 addition & 1 deletion lib/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ function prune_installed($apps, $global) {

# check whether the app failed to install
function failed($app, $global) {
$ver = current_version $app $global
$ver = Select-CurrentVersion -AppName $app -Global:$global
if(!$ver) { return $false }
$info = install_info $app $ver $global
if(!$info) { return $true }
Expand Down
261 changes: 233 additions & 28 deletions lib/versions.ps1
Original file line number Diff line number Diff line change
@@ -1,53 +1,258 @@
# versions
function latest_version($app, $bucket, $url) {
(manifest $app $bucket $url).version
}
function current_version($app, $global) {
@(versions $app $global)[-1]
function Get-LatestVersion {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
<#
.SYNOPSIS
Get latest version of app from manifest
.PARAMETER AppName
App's name
.PARAMETER Bucket
Bucket which the app belongs to
.PARAMETER Uri
Remote app manifest's URI
#>
[OutputType([String])]
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[Alias('App')]
[String]
$AppName,
[Parameter(Position = 1)]
[String]
$Bucket,
[Parameter(Position = 2)]
[String]
$Uri
)
return (manifest $AppName $Bucket $Uri).version
}
function versions($app, $global) {
$appdir = appdir $app $global
if(!(test-path $appdir)) { return @() }

sort_versions (Get-ChildItem $appdir -dir -attr !reparsePoint | Where-Object { $null -ne $(Get-ChildItem $_.fullname) } | ForEach-Object { $_.name })
function Select-CurrentVersion {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
<#
.SYNOPSIS
Select current version of installed app, from 'current\manifest.json' or modified time of version directory
.PARAMETER AppName
App's name
.PARAMETER Global
Globally installed application
#>
[OutputType([String])]
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[Alias('App')]
[String]
$AppName,
[Parameter(Position = 1)]
[Switch]
$Global
)

$appPath = appdir $AppName $Global
if (Test-Path "$appPath\current") {
$currentVersion = (installed_manifest $AppName 'current' $Global).version
} else {
$installedVersion = Get-InstalledVersion -AppName $AppName -Global:$Global
if ($installedVersion) {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
$currentVersion = $installedVersion[-1]
} else {
$currentVersion = $null
}
}
return $currentVersion
}

function version($ver) {
$ver -split '[\.-]' | ForEach-Object {
$num = $_ -as [int]
if($num) { $num } else { $_ }
function Get-InstalledVersion {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
<#
.SYNOPSIS
Get all installed version of app, by checking version directories' 'install.json'
niheaven marked this conversation as resolved.
Show resolved Hide resolved
.PARAMETER AppName
App's name
.PARAMETER Global
Globally installed application
.NOTES
Versions are sorted from oldest to newest, i.e., latest installed version is the last one in the output array.
If no installed version found, empty array will be returned.
#>
[OutputType([Object[]])]
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[Alias('App')]
[String]
$AppName,
[Parameter(Position = 1)]
[Switch]
$Global
)

$appPath = appdir $AppName $Global
if (Test-Path $appPath) {
return @((Get-ChildItem "$appPath\*\install.json" | Sort-Object -Property LastWriteTimeUtc).Directory.Name) -ne 'current'
} else {
return @()
}

# Deprecated
# sort_versions (Get-ChildItem $appPath -dir -attr !reparsePoint | Where-Object { $null -ne $(Get-ChildItem $_.FullName) } | ForEach-Object { $_.Name })
}
function compare_versions($a, $b) {
$ver_a = @(version $a)
$ver_b = @(version $b)

for($i=0;$i -lt $ver_a.length;$i++) {
if($i -gt $ver_b.length) { return 1; }
function Compare-Version {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
<#
.SYNOPSIS
Compare versions, mainly according to SemVer's rules
niheaven marked this conversation as resolved.
Show resolved Hide resolved
.PARAMETER ReferenceVersion
Specifies a version used as a reference for comparison
.PARAMETER DifferenceVersion
Specifies the version that are compared to the reference version
.PARAMETER Delimiter
Specifies the delimiter of versions
.OUTPUTS
System.Int32
'0' if DifferenceVersion is equal to ReferenceVersion,
'1' if DifferenceVersion is greater then ReferenceVersion,
'-1' if DifferenceVersion is less then ReferenceVersion
#>
[OutputType([Int])]
[CmdletBinding()]
param (
[Parameter(Position = 0)]
[String]
$ReferenceVersion,
[Parameter(Position = 1, ValueFromPipeline = $true)]
[String]
$DifferenceVersion,
[String]
$Delimiter = '-'
)

# don't try to compare int to string
if($ver_b[$i] -is [string] -and $ver_a[$i] -isnot [string]) {
$ver_a[$i] = "$($ver_a[$i])"
# Use '+' sign as post-release, see https://github.com/lukesampson/scoop/pull/3721#issuecomment-553718093
$ReferenceVersion, $DifferenceVersion = @($ReferenceVersion, $DifferenceVersion) -replace '\+', '-'

# Return 0 if versions are equal
if ($DifferenceVersion -eq $ReferenceVersion) {
return 0
}

# Preprocess versions (split, convert and separate)
$splitReferenceVersion = @(SplitVersion -Version $ReferenceVersion -Delimiter $Delimiter)
$splitDifferenceVersion = @(SplitVersion -Version $DifferenceVersion -Delimiter $Delimiter)

# Nightly versions are always equal
if ($splitReferenceVersion[0] -eq 'nightly' -and $splitDifferenceVersion[0] -eq 'nightly') {
return 0
}

for ($i = 0; $i -lt [Math]::Max($splitReferenceVersion.Length, $splitDifferenceVersion.Length); $i++) {
# '1.1-alpha' is less then '1.1'
if ($i -ge $splitReferenceVersion.Length) {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
if ($splitDifferenceVersion[$i] -match 'alpha|beta|rc|pre') {
return -1
} else {
return 1
}
}
# '1.1' is greater then '1.1-beta'
if ($i -ge $splitDifferenceVersion.Length) {
if ($splitReferenceVersion[$i] -match 'alpha|beta|rc|pre') {
return 1
} else {
return -1
}
}

if($ver_a[$i] -gt $ver_b[$i]) { return 1; }
if($ver_a[$i] -lt $ver_b[$i]) { return -1; }
# If some parts of versions have '.', compare them with delimiter '.'
if (($splitReferenceVersion[$i] -match '\.') -or ($splitDifferenceVersion[$i] -match '\.')) {
$Result = Compare-Version -ReferenceVersion $splitReferenceVersion[$i] -DifferenceVersion $splitDifferenceVersion[$i] -Delimiter '.'
# If the parts are equal, continue to next part, otherwise return
if ($Result -ne 0) {
return $Result
} else {
continue
}
}

# Don't try to compare [Long] to [String]
if ($null -ne $splitReferenceVersion[$i] -and $null -ne $splitDifferenceVersion[$i]) {
if ($splitReferenceVersion[$i] -is [String] -and $splitDifferenceVersion[$i] -isnot [String]) {
$splitDifferenceVersion[$i] = "$($splitDifferenceVersion[$i])"
}
if ($splitDifferenceVersion[$i] -is [String] -and $splitReferenceVersion[$i] -isnot [String]) {
$splitReferenceVersion[$i] = "$($splitReferenceVersion[$i])"
}
}

# Compare [String] or [Long]
if ($splitDifferenceVersion[$i] -gt $splitReferenceVersion[$i]) {
return 1
}
if ($splitDifferenceVersion[$i] -lt $splitReferenceVersion[$i]) {
return -1
}
}
if($ver_b.length -gt $ver_a.length) { return -1 }
return 0
}

# Helper function
function SplitVersion {
<#
.SYNOPSIS
Split version by Delimiter, convert number string to number, and separate letters from numbers
.PARAMETER Version
Specifies a version
.PARAMETER Delimiter
Specifies the delimiter of version (Literal)
#>
param (
[String]
$Version,
[String]
$Delimiter = '-'
)
$Version = $Version -replace '[a-zA-Z]+', "$Delimiter$&$Delimiter"
niheaven marked this conversation as resolved.
Show resolved Hide resolved
return ($Version -split [Regex]::Escape($Delimiter) -ne '' | ForEach-Object { if ($_ -match '^\d+$') { [Long]$_ } else { $_ } })
}

# Deprecated
# Not used anymore in scoop core
function qsort($ary, $fn) {
warn '"qsort" is deprecated. Please avoid using it anymore.'
if($null -eq $ary) { return @() }
if(!($ary -is [array])) { return @($ary) }

$pivot = $ary[0]
$rem = $ary[1..($ary.length-1)]

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

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

return @() + $lesser + @($pivot) + $greater
}
function sort_versions($versions) { qsort $versions compare_versions }

# Deprecated
niheaven marked this conversation as resolved.
Show resolved Hide resolved
# Not used anymore in scoop core
function sort_versions($versions) {
warn '"sort_versions" is deprecated. Please avoid using it anymore.'
qsort $versions Compare-Version
}
niheaven marked this conversation as resolved.
Show resolved Hide resolved

function compare_versions($a, $b) {
Show-DeprecatedWarning $MyInvocation 'Compare-Version'
# Please note the parameters' sequence
return Compare-Version -ReferenceVersion $b -DifferenceVersion $a
}

function latest_version($app, $bucket, $url) {
Show-DeprecatedWarning $MyInvocation 'Get-LatestVersion'
return Get-LatestVersion -AppName $app -Bucket $bucket -Uri $url
}

function current_version($app, $global) {
Show-DeprecatedWarning $MyInvocation 'Select-CurrentVersion'
return Select-CurrentVersion -AppName $app -Global:$global
}

function versions($app, $global) {
Show-DeprecatedWarning $MyInvocation 'Get-InstalledVersion'
return Get-InstalledVersion -AppName $app -Global:$global
}
4 changes: 2 additions & 2 deletions libexec/scoop-cleanup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ if ($global -and !(is_admin)) {
}

function cleanup($app, $global, $verbose, $cache) {
$current_version = current_version $app $global
$current_version = Select-CurrentVersion -AppName $app -Global:$global
if ($cache) {
Remove-Item "$cachedir\$app#*" -Exclude "$app#$current_version#*"
}
$versions = versions $app $global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
$versions = Get-InstalledVersion -AppName $app -Global:$global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
if (!$versions) {
if ($verbose) { success "$app is already clean" }
return
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-export.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ if($apps) {
$apps | Sort-Object { $_.name } | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
$app = $_.name
$global = $_.global
$ver = current_version $app $global
$ver = Select-CurrentVersion -AppName $app -Global:$global
$global_display = $null; if($global) { $global_display = ' *global*'}

$install_info = install_info $app $ver $global
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-info.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Write-Output "Manifest:`n $manifest_file"
if($status.installed) {
# Show installed versions
Write-Output "Installed:"
$versions = versions $app $global
$versions = Get-InstalledVersion -AppName $app -Global:$global
$versions | ForEach-Object {
$dir = versiondir $app $_ $global
if($global) { $dir += " *global*" }
Expand Down
4 changes: 2 additions & 2 deletions libexec/scoop-install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function is_installed($app, $global) {
if (installed $app $global) {
function gf($g) { if ($g) { ' --global' } }

$version = @(versions $app $global)[-1]
$version = Select-CurrentVersion -AppName $app -Global:$global
if (!(install_info $app $version $global)) {
error "It looks like a previous installation of $app failed.`nRun 'scoop uninstall $app$(gf $global)' before retrying the install."
}
Expand Down Expand Up @@ -114,7 +114,7 @@ $apps, $skip = prune_installed $apps $global

$skip | Where-Object { $explicit_apps -contains $_ } | ForEach-Object {
$app, $null, $null = parse_app $_
$version = @(versions $app $global)[-1]
$version = Select-CurrentVersion -AppName $app -Global:$global
warn "'$app' ($version) is already installed. Skipping."
}

Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-list.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if($apps) {
$apps | Sort-Object { $_.name } | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
$app = $_.name
$global = $_.global
$ver = current_version $app $global
$ver = Select-CurrentVersion -AppName $app -Global:$global

$install_info = install_info $app $ver $global
write-host " $app " -NoNewline
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-reset.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ $apps | ForEach-Object {
}

if ($null -eq $version) {
$version = current_version $app $global
$version = Select-CurrentVersion -AppName $app -Global:$global
}

$manifest = installed_manifest $app $version $global
Expand Down
Loading