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

feat(path): Isolate Scoop apps' PATH #5840

Merged
merged 20 commits into from Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,7 @@
- **bucket:** Make official buckets higher priority ([#5398](https://github.com/ScoopInstaller/Scoop/issues/5398))
- **core:** Add `-Quiet` switch for `Invoke-ExternalCommand` ([#5346](https://github.com/ScoopInstaller/Scoop/issues/5346))
- **core:** Allow global install of PowerShell modules ([#5611](https://github.com/ScoopInstaller/Scoop/issues/5611))
- **path:** Isolate Scoop apps' PATH ([#5840](https://github.com/ScoopInstaller/Scoop/issues/5840))

### Bug Fixes

Expand Down
3 changes: 3 additions & 0 deletions bin/uninstall.ps1
Expand Up @@ -100,5 +100,8 @@ if ($purge) {
}

Remove-Path -Path (shimdir $global) -Global:$global
if (get_config USE_ISOLATED_PATH) {
Remove-Path -Path '%SCOOP_PATH%' -Global:$global
}

success 'Scoop has been uninstalled.'
18 changes: 16 additions & 2 deletions lib/install.ps1
Expand Up @@ -909,6 +909,12 @@ function env_add_path($manifest, $dir, $global, $arch) {
$env_add_path = arch_specific 'env_add_path' $manifest $arch
$dir = $dir.TrimEnd('\')
if ($env_add_path) {
if (get_config USE_ISOLATED_PATH) {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
Add-Path -Path '%SCOOP_PATH%' -Global:$global
$target_path = 'SCOOP_PATH'
} else {
$target_path = 'PATH'
}
# GH-3785: Add path in ascending order.
[Array]::Reverse($env_add_path)
$env_add_path | Where-Object { $_ } | ForEach-Object {
Expand All @@ -920,7 +926,7 @@ function env_add_path($manifest, $dir, $global, $arch) {
if (!(is_in_dir $dir $path_dir)) {
abort "Error in manifest: env_add_path '$_' is outside the app directory."
niheaven marked this conversation as resolved.
Show resolved Hide resolved
}
Add-Path -Path $path_dir -Global:$global -Force
Add-Path -Path $path_dir -Scope $target_path -Global:$global -Force
}
}
}
Expand All @@ -929,13 +935,21 @@ function env_rm_path($manifest, $dir, $global, $arch) {
$env_add_path = arch_specific 'env_add_path' $manifest $arch
$dir = $dir.TrimEnd('\')
if ($env_add_path) {
if (get_config USE_ISOLATED_PATH) {
$target_path = 'SCOOP_PATH'
} else {
$target_path = 'PATH'
}
niheaven marked this conversation as resolved.
Show resolved Hide resolved
$env_add_path | Where-Object { $_ } | ForEach-Object {
if ($_ -eq '.') {
$path_dir = $dir
} else {
$path_dir = Join-Path $dir $_
}
Remove-Path -Path $path_dir -Global:$global
Remove-Path -Path $path_dir -Scope $target_path -Global:$global
if ($target_path -eq 'SCOOP_PATH') {
Remove-Path -Path $path_dir -Global:$global
}
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions lib/system.ps1
Expand Up @@ -88,6 +88,7 @@ function Test-PathLikeEnvVar {
function Add-Path {
param(
[string]$Path,
[string]$Scope = 'PATH',
niheaven marked this conversation as resolved.
Show resolved Hide resolved
[switch]$Global,
[switch]$Force
)
Expand All @@ -96,10 +97,10 @@ function Add-Path {
$Path = fullpath $Path
}
# future sessions
$inPath, $strippedPath = Test-PathLikeEnvVar $Path (Get-EnvVar -Name 'PATH' -Global:$Global)
$inPath, $strippedPath = Test-PathLikeEnvVar $Path (Get-EnvVar -Name $Scope -Global:$Global)
if (!$inPath -or $Force) {
Write-Output "Adding $(friendly_path $Path) to $(if ($Global) {'global'} else {'your'}) path."
Set-EnvVar -Name 'PATH' -Value (@($Path, $strippedPath) -join ';') -Global:$Global
Set-EnvVar -Name $Scope -Value (@($Path, $strippedPath) -join ';') -Global:$Global
}
# current session
$inPath, $strippedPath = Test-PathLikeEnvVar $Path $env:PATH
Expand All @@ -111,17 +112,18 @@ function Add-Path {
function Remove-Path {
param(
[string]$Path,
[string]$Scope = 'PATH',
[switch]$Global
)

if (!$Path.Contains('%')) {
$Path = fullpath $Path
}
# future sessions
$inPath, $strippedPath = Test-PathLikeEnvVar $Path (Get-EnvVar -Name 'PATH' -Global:$Global)
$inPath, $strippedPath = Test-PathLikeEnvVar $Path (Get-EnvVar -Name $Scope -Global:$Global)
if ($inPath) {
Write-Output "Removing $(friendly_path $Path) from $(if ($Global) {'global'} else {'your'}) path."
Set-EnvVar -Name 'PATH' -Value $strippedPath -Global:$Global
Set-EnvVar -Name $Scope -Value $strippedPath -Global:$Global
}
# current session
$inPath, $strippedPath = Test-PathLikeEnvVar $Path $env:PATH
Expand Down
4 changes: 4 additions & 0 deletions libexec/scoop-config.ps1
Expand Up @@ -115,6 +115,10 @@
# Nightly version is formatted as 'nightly-yyyyMMdd' and will be updated after one day if this is set to $true.
# Otherwise, nightly version will not be updated unless `--force` is used.
#
# use_isolated_path: $true|$false
# When set to $true, Scoop will use `SCOOP_PATH` environment variable to store apps' `PATH`s.
# This is useful when you want to isolate Scoop from the system `PATH`.
#
# ARIA2 configuration
# -------------------
#
Expand Down
3 changes: 3 additions & 0 deletions libexec/scoop-reset.ps1
Expand Up @@ -80,6 +80,9 @@ $apps | ForEach-Object {
$dir = link_current $dir
create_shims $manifest $dir $global $architecture
create_startmenu_shortcuts $manifest $dir $global $architecture
# unset all potential old env before re-adding
env_rm_path $manifest $dir $global $architecture
env_rm $manifest $global $architecture
env_add_path $manifest $dir $global $architecture
env_set $manifest $dir $global $architecture
# unlink all potential old link before re-persisting
Expand Down