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(core): Rewrite and separate path-related functions to system.ps1 #5836

Merged
merged 7 commits into from Mar 27, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -55,6 +55,7 @@
- **git:** Use Invoke-Git() with direct path to git.exe to prevent spawning shim subprocesses ([#5122](https://github.com/ScoopInstaller/Scoop/issues/5122), [#5375](https://github.com/ScoopInstaller/Scoop/issues/5375))
- **scoop-download:** Output more detailed manifest information ([#5277](https://github.com/ScoopInstaller/Scoop/issues/5277))
- **core:** Cleanup some old codes, e.g., msi section and config migration ([#5715](https://github.com/ScoopInstaller/Scoop/issues/5715), [#5824](https://github.com/ScoopInstaller/Scoop/issues/5824))
- **core:** Rewrite and separate path-related functions to `system.ps1` ([#5836](https://github.com/ScoopInstaller/Scoop/issues/5836))

### Builds

Expand Down
4 changes: 2 additions & 2 deletions bin/uninstall.ps1
Expand Up @@ -12,6 +12,7 @@ param(
)

. "$PSScriptRoot\..\lib\core.ps1"
. "$PSScriptRoot\..\lib\system.ps1"
. "$PSScriptRoot\..\lib\install.ps1"
. "$PSScriptRoot\..\lib\shortcuts.ps1"
. "$PSScriptRoot\..\lib\versions.ps1"
Expand Down Expand Up @@ -98,7 +99,6 @@ if ($purge) {
if ($global) { keep_onlypersist $globaldir }
}

remove_from_path (shimdir $false)
if ($global) { remove_from_path (shimdir $true) }
Remove-Path -Path (shimdir $global) -Global:$global

success 'Scoop has been uninstalled.'
126 changes: 11 additions & 115 deletions lib/core.ps1
Expand Up @@ -581,12 +581,18 @@ function fullpath($path) {
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($path)
}
function friendly_path($path) {
$h = (Get-PsProvider 'FileSystem').home; if(!$h.endswith('\')) { $h += '\' }
if($h -eq '\') { return $path }
return "$path" -replace ([regex]::escape($h)), "~\"
$h = (Get-PSProvider 'FileSystem').Home
if (!$h.EndsWith('\')) {
$h += '\'
}
if ($h -eq '\') {
return $path
} else {
return $path -replace ([Regex]::Escape($h)), '~\'
}
}
function is_local($path) {
($path -notmatch '^https?://') -and (test-path $path)
($path -notmatch '^https?://') -and (Test-Path $path)
}

# operations
Expand Down Expand Up @@ -714,57 +720,6 @@ function Invoke-ExternalCommand {
return $true
}

function Publish-Env {
if (-not ("Win32.NativeMethods" -as [Type])) {
Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}

$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero

[Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST,
$WM_SETTINGCHANGE,
[UIntPtr]::Zero,
"Environment",
2,
5000,
[ref] $result
) | Out-Null
}

function env($name, $global, $val = '__get') {
$RegisterKey = if ($global) {
Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
} else {
Get-Item -Path 'HKCU:'
}
$EnvRegisterKey = $RegisterKey.OpenSubKey('Environment', $val -ne '__get')

if ($val -eq '__get') {
$RegistryValueOption = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
$EnvRegisterKey.GetValue($name, $null, $RegistryValueOption)
} elseif ($val -eq $null) {
try { $EnvRegisterKey.DeleteValue($name) } catch { }
Publish-Env
} else {
$RegistryValueKind = if ($val.Contains('%')) {
[Microsoft.Win32.RegistryValueKind]::ExpandString
} elseif ($EnvRegisterKey.GetValue($name)) {
$EnvRegisterKey.GetValueKind($name)
} else {
[Microsoft.Win32.RegistryValueKind]::String
}
$EnvRegisterKey.SetValue($name, $val, $RegistryValueKind)
Publish-Env
}
}

function isFileLocked([string]$path) {
$file = New-Object System.IO.FileInfo $path

Expand Down Expand Up @@ -872,7 +827,7 @@ function warn_on_overwrite($shim, $path) {
function shim($path, $global, $name, $arg) {
if (!(Test-Path $path)) { abort "Can't shim '$(fname $path)': couldn't find '$path'." }
$abs_shimdir = ensure (shimdir $global)
ensure_in_path $abs_shimdir $global
Add-Path -Path $abs_shimdir -Global:$global
if (!$name) { $name = strip_ext (fname $path) }

$shim = "$abs_shimdir\$($name.tolower())"
Expand Down Expand Up @@ -1009,26 +964,6 @@ function get_shim_path() {
return $shim_path
}

function search_in_path($target) {
niheaven marked this conversation as resolved.
Show resolved Hide resolved
$path = (env 'PATH' $false) + ";" + (env 'PATH' $true)
foreach($dir in $path.split(';')) {
if(test-path "$dir\$target" -pathType leaf) {
return "$dir\$target"
}
}
}

function ensure_in_path($dir, $global) {
$path = env 'PATH' $global
$dir = fullpath $dir
if($path -notmatch [regex]::escape($dir)) {
write-output "Adding $(friendly_path $dir) to $(if($global){'global'}else{'your'}) path."

env 'PATH' $global "$dir;$path" # for future sessions...
$env:PATH = "$dir;$env:PATH" # for this session
}
}

function Get-DefaultArchitecture {
$arch = get_config DEFAULT_ARCHITECTURE
$system = if (${env:ProgramFiles(Arm)}) {
Expand Down Expand Up @@ -1103,45 +1038,6 @@ function Confirm-InstallationStatus {
return , $Installed
}

function strip_path($orig_path, $dir) {
if($null -eq $orig_path) { $orig_path = '' }
$stripped = [string]::join(';', @( $orig_path.split(';') | Where-Object { $_ -and $_ -ne $dir } ))
return ($stripped -ne $orig_path), $stripped
}

function add_first_in_path($dir, $global) {
$dir = fullpath $dir

# future sessions
$null, $currpath = strip_path (env 'path' $global) $dir
env 'path' $global "$dir;$currpath"

# this session
$null, $env:PATH = strip_path $env:PATH $dir
$env:PATH = "$dir;$env:PATH"
}

function remove_from_path($dir, $global) {
$dir = fullpath $dir

# future sessions
$was_in_path, $newpath = strip_path (env 'path' $global) $dir
if($was_in_path) {
Write-Output "Removing $(friendly_path $dir) from your path."
env 'path' $global $newpath
}

# current session
$was_in_path, $newpath = strip_path $env:PATH $dir
if($was_in_path) { $env:PATH = $newpath }
}

function ensure_robocopy_in_path {
if(!(Test-CommandAvailable robocopy)) {
shim "C:\Windows\System32\Robocopy.exe" $false
}
}

function wraptext($text, $width) {
if(!$width) { $width = $host.ui.rawui.buffersize.width };
$width -= 1 # be conservative: doesn't seem to print the last char
Expand Down
16 changes: 8 additions & 8 deletions lib/install.ps1
Expand Up @@ -783,7 +783,7 @@ function create_shims($manifest, $dir, $global, $arch) {
} elseif (Test-Path $target -PathType leaf) {
$bin = $target
} else {
$bin = search_in_path $target
$bin = (Get-Command $target).Source
}
if (!$bin) { abort "Can't shim '$target': File doesn't exist." }

Expand Down Expand Up @@ -876,16 +876,16 @@ function unlink_current($versiondir) {

# to undo after installers add to path so that scoop manifest can keep track of this instead
function ensure_install_dir_not_in_path($dir, $global) {
$path = (env 'path' $global)
$path = (Get-EnvVar -Name 'PATH' -Global:$global)

$fixed, $removed = find_dir_or_subdir $path "$dir"
if ($removed) {
$removed | ForEach-Object { "Installer added '$(friendly_path $_)' to path. Removing." }
env 'path' $global $fixed
Set-EnvVar -Name 'PATH' -Value $fixed -Global:$global
}

if (!$global) {
$fixed, $removed = find_dir_or_subdir (env 'path' $true) "$dir"
$fixed, $removed = find_dir_or_subdir (Get-EnvVar -Name 'PATH' -Global) "$dir"
if ($removed) {
$removed | ForEach-Object { warn "Installer added '$_' to system path. You might want to remove this manually (requires admin permission)." }
}
Expand Down Expand Up @@ -920,7 +920,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."
}
add_first_in_path $path_dir $global
Add-Path -Path $path_dir -Global:$global -Force
}
}
}
Expand All @@ -935,7 +935,7 @@ function env_rm_path($manifest, $dir, $global, $arch) {
} else {
$path_dir = Join-Path $dir $_
}
remove_from_path $path_dir $global
Remove-Path -Path $path_dir -Global:$global
}
}
}
Expand All @@ -946,7 +946,7 @@ function env_set($manifest, $dir, $global, $arch) {
$env_set | Get-Member -Member NoteProperty | ForEach-Object {
$name = $_.name
$val = format $env_set.$($_.name) @{ 'dir' = $dir }
env $name $global $val
Set-EnvVar -Name $name -Value $val -Global:$global
Set-Content env:\$name $val
}
}
Expand All @@ -956,7 +956,7 @@ function env_rm($manifest, $global, $arch) {
if ($env_set) {
$env_set | Get-Member -Member NoteProperty | ForEach-Object {
$name = $_.name
env $name $global $null
Set-EnvVar -Name $name -Value $null -Global:$global
if (Test-Path env:\$name) { Remove-Item env:\$name }
}
}
Expand Down
5 changes: 2 additions & 3 deletions lib/psmodules.ps1
Expand Up @@ -42,15 +42,14 @@ function uninstall_psmodule($manifest, $dir, $global) {
}

function ensure_in_psmodulepath($dir, $global) {
$path = env 'psmodulepath' $global
$path = Get-EnvVar -Name 'PSModulePath' -Global:$global
if (!$global -and $null -eq $path) {
$path = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules"
}
$dir = fullpath $dir
if ($path -notmatch [Regex]::Escape($dir)) {
Write-Output "Adding $(friendly_path $dir) to $(if($global){'global'}else{'your'}) PowerShell module path."

env 'psmodulepath' $global "$dir;$path" # for future sessions...
$env:psmodulepath = "$dir;$env:psmodulepath" # for this session
Set-EnvVar -Name 'PSModulePath' -Value "$dir;$path" -Global:$global
}
}