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(install): Replace 'run_(un)installer()' with 'Invoke-Installer()' #5968

Merged
merged 3 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
### Code Refactoring

- **install:** Separate archive extraction from downloader ([#5951](https://github.com/ScoopInstaller/Scoop/issues/5951))
- **install:** Replace 'run_(un)installer()' with 'Invoke-Installer()' ([#5968](https://github.com/ScoopInstaller/Scoop/issues/5968))

## [v0.4.1](https://github.com/ScoopInstaller/Scoop/compare/v0.4.0...v0.4.1) - 2024-04-25

Expand Down
2 changes: 1 addition & 1 deletion bin/uninstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function do_uninstall($app, $global) {
$architecture = $install.architecture

Write-Output "Uninstalling '$app'"
run_uninstaller $manifest $architecture $dir
Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -Uninstall
rm_shims $app $manifest $global $architecture

# If a junction was used during install, that will have been used
Expand Down
4 changes: 0 additions & 4 deletions lib/core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,6 @@ function Invoke-GitLog {
# helper functions
function coalesce($a, $b) { if($a) { return $a } $b }

function format($str, $hash) {
$hash.keys | ForEach-Object { set-variable $_ $hash[$_] }
$executionContext.invokeCommand.expandString($str)
}
function is_admin {
$admin = [security.principal.windowsbuiltinrole]::administrator
$id = [security.principal.windowsidentity]::getcurrent()
Expand Down
154 changes: 73 additions & 81 deletions lib/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru

$fname = Invoke-ScoopDownload $app $version $manifest $bucket $architecture $dir $use_cache $check_hash
Invoke-Extraction -Path $dir -Name $fname -Manifest $manifest -ProcessorArchitecture $architecture
Invoke-HookScript -HookType 'pre_install' -Manifest $manifest -Arch $architecture
Invoke-HookScript -HookType 'pre_install' -Manifest $manifest -ProcessorArchitecture $architecture

run_installer @($fname)[-1] $manifest $architecture $dir $global
Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -AppName $app -Global:$global
ensure_install_dir_not_in_path $dir $global
$dir = link_current $dir
create_shims $manifest $dir $global $architecture
Expand All @@ -66,7 +66,7 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru
persist_data $manifest $original_dir $persist_dir
persist_permission $manifest $global

Invoke-HookScript -HookType 'post_install' -Manifest $manifest -Arch $architecture
Invoke-HookScript -HookType 'post_install' -Manifest $manifest -ProcessorArchitecture $architecture

# save info for uninstall
save_installed_manifest $app $bucket $dir $url
Expand Down Expand Up @@ -540,7 +540,7 @@ function Invoke-ScoopDownload ($app, $version, $manifest, $bucket, $architecture
# we only want to show this warning once
if (!$use_cache) { warn 'Cache is being ignored.' }

# can be multiple urls: if there are, then installer should go last to make 'installer.args' section work
# can be multiple urls: if there are, then installer should go first to make 'installer.args' section work
$urls = @(script:url $manifest $architecture)

# can be multiple cookies: they will be used for all HTTP requests.
Expand Down Expand Up @@ -651,70 +651,84 @@ function check_hash($file, $hash, $app_name) {
return $true, $null
}

# for dealing with installers
function args($config, $dir, $global) {
if ($config) { return $config | ForEach-Object { (format $_ @{'dir' = $dir; 'global' = $global }) } }
@()
}

function run_installer($fname, $manifest, $architecture, $dir, $global) {
$installer = installer $manifest $architecture
if ($installer.script) {
Write-Output 'Running installer script...'
Invoke-Command ([scriptblock]::Create($installer.script -join "`r`n"))
return
}
if ($installer) {
$prog = "$dir\$(coalesce $installer.file $fname)"
if (!(is_in_dir $dir $prog)) {
abort "Error in manifest: Installer $prog is outside the app directory."
function Invoke-Installer {
[CmdletBinding()]
param (
[string]
$Path,
[psobject]
$Manifest,
[Alias('Arch', 'Architecture')]
[ValidateSet('32bit', '64bit', 'arm64')]
[string]
$ProcessorArchitecture,
[string]
$AppName,
[switch]
$Global,
[switch]
$Uninstall
)
$type = if ($Uninstall) { 'uninstaller' } else { 'installer' }
$installer = arch_specific $type $Manifest $ProcessorArchitecture
if ($installer.file -or $installer.args) {
# Installer filename is either explicit defined ('installer.file') or file name in the first URL
$progName = "$Path\$(coalesce $installer.file (url_filename @(url $manifest $architecture)[0]))"
if (!(is_in_dir $Path $progName)) {
abort "Error in manifest: $((Get-Culture).TextInfo.ToTitleCase($type)) $progName is outside the app directory."
} elseif (!(Test-Path $progName)) {
abort "$((Get-Culture).TextInfo.ToTitleCase($type)) $progName is missing."
}
$arg = @(args $installer.args $dir $global)
if ($prog.endswith('.ps1')) {
& $prog @arg
$substitutions = @{
'$dir' = $Path
'$global' = $Global
'$version' = $Manifest.version
}
$fnArgs = substitute $installer.args $substitutions
if ($progName.EndsWith('.ps1')) {
& $progName @fnArgs
} else {
$installed = Invoke-ExternalCommand $prog $arg -Activity 'Running installer...'
if (!$installed) {
abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again."
$status = Invoke-ExternalCommand $progName -ArgumentList $fnArgs -Activity "Running $type ..."
if (!$status) {
if ($Uninstall) {
abort 'Uninstallation aborted.'
} else {
abort "Installation aborted. You might need to run 'scoop uninstall $AppName' before trying again."
}
}
# Don't remove installer if "keep" flag is set to true
if (!($installer.keep -eq 'true')) {
Remove-Item $prog
if (!$installer.keep) {
Remove-Item $progName
}
}
}
Invoke-HookScript -HookType $type -Manifest $Manifest -ProcessorArchitecture $ProcessorArchitecture
}

function run_uninstaller($manifest, $architecture, $dir) {
$uninstaller = uninstaller $manifest $architecture
$version = $manifest.version
if ($uninstaller.script) {
Write-Output 'Running uninstaller script...'
Invoke-Command ([scriptblock]::Create($uninstaller.script -join "`r`n"))
return
}

if ($uninstaller.file) {
$prog = "$dir\$($uninstaller.file)"
$arg = args $uninstaller.args
if (!(is_in_dir $dir $prog)) {
warn "Error in manifest: Installer $prog is outside the app directory, skipping."
$prog = $null
} elseif (!(Test-Path $prog)) {
warn "Uninstaller $prog is missing, skipping."
$prog = $null
}
function Invoke-HookScript {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateSet('installer', 'pre_install', 'post_install', 'uninstaller', 'pre_uninstall', 'post_uninstall')]
[String] $HookType,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[PSCustomObject] $Manifest,
[Parameter(Mandatory = $true)]
[Alias('Arch', 'Architecture')]
[ValidateSet('32bit', '64bit', 'arm64')]
[string]
$ProcessorArchitecture
)

if ($prog) {
if ($prog.endswith('.ps1')) {
& $prog @arg
} else {
$uninstalled = Invoke-ExternalCommand $prog $arg -Activity 'Running uninstaller...'
if (!$uninstalled) {
abort 'Uninstallation aborted.'
}
}
}
$script = arch_specific $HookType $Manifest $ProcessorArchitecture
if ($HookType -in @('installer', 'uninstaller')) {
$script = $script.script
}
if ($script) {
Write-Host "Running $HookType script..." -NoNewline
Invoke-Command ([scriptblock]::Create($script -join "`r`n"))
Write-Host 'done.' -ForegroundColor Green
}
}

Expand Down Expand Up @@ -884,7 +898,7 @@ function env_set($manifest, $dir, $global, $arch) {
if ($env_set) {
$env_set | Get-Member -Member NoteProperty | ForEach-Object {
$name = $_.name
$val = format $env_set.$($_.name) @{ 'dir' = $dir }
$val = substitute $env_set.$($_.name) @{ '$dir' = $dir }
Set-EnvVar -Name $name -Value $val -Global:$global
Set-Content env:\$name $val
}
Expand All @@ -901,28 +915,6 @@ function env_rm($manifest, $global, $arch) {
}
}

function Invoke-HookScript {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateSet('pre_install', 'post_install',
'pre_uninstall', 'post_uninstall')]
[String] $HookType,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[PSCustomObject] $Manifest,
[Parameter(Mandatory = $true)]
[ValidateSet('32bit', '64bit', 'arm64')]
[String] $Arch
)

$script = arch_specific $HookType $Manifest $Arch
if ($script) {
Write-Output "Running $HookType script..."
Invoke-Command ([scriptblock]::Create($script -join "`r`n"))
}
}

function show_notes($manifest, $dir, $original_dir, $persist_dir) {
if ($manifest.notes) {
Write-Output 'Notes'
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-info.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ $env_set = arch_specific 'env_set' $manifest $install.architecture
if ($env_set) {
$env_vars = @()
$env_set | Get-Member -member noteproperty | ForEach-Object {
$env_vars += "$($_.name) = $(format $env_set.$($_.name) @{ "dir" = $dir })"
$env_vars += "$($_.name) = $(substitute $env_set.$($_.name) @{ '$dir' = $dir })"
}
$item.Environment = $env_vars -join "`n"
}
Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-uninstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ if (!$apps) { exit 0 }
continue
}

run_uninstaller $manifest $architecture $dir
Invoke-Installer -Path $dir -Manifest $manifest -ProcessorArchitecture $architecture -Uninstall
rm_shims $app $manifest $global $architecture
rm_startmenu_shortcuts $manifest $global $architecture

Expand Down
2 changes: 1 addition & 1 deletion libexec/scoop-update.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
Invoke-HookScript -HookType 'pre_uninstall' -Manifest $old_manifest -Arch $architecture

Write-Host "Uninstalling '$app' ($old_version)"
run_uninstaller $old_manifest $architecture $dir
Invoke-Installer -Path $dir -Manifest $old_manifest -ProcessorArchitecture $architecture -Uninstall
rm_shims $app $old_manifest $global $architecture

# If a junction was used during install, that will have been used
Expand Down