Skip to content

Commit

Permalink
feat(install): Add PIXI_NO_PATH_UPDATE for PATH update suppression (#…
Browse files Browse the repository at this point in the history
…692)

Close #686 

The PR mainly adds the option of using a `PIXI_NO_PATH_UPDATE`
environment variable to suppress PATH update, when installing pixi from
install script.

Besides the option added, since the PR is about environment variable,
the way of updating PATH in the PowerShell install script has also been
modified from using `[Environment]::SetEnvironmentVariable` to set
environment variable to get and update environment variable from Windows
registry.

This change doesn't affect pixi installation directly and is primarily
to address a potential issue that `SetEnvironmentVariable` expands all
environment variables and this behavior may not be welcomed in some
cases.

```pwsh
$Env:PATH
#> %USERPROFILE%\bin;

# when using `SetEnvironmentVariable` to update PATH, `%USERPROFILE%` will be expanded
#> C:\Users\userA\bin;C:\pixi\bin

# when using registry to update PATH, `%USERPROFILE%` will be kept unexpanded
#> %USERPROFILE%\bin;C:\pixi\bin
```

Related code are copied from
[ScoopInstaller/Install](https://github.com/ScoopInstaller/Install/blob/master/install.ps1#L362)
I'm maintaining.

Signed-off-by: Chawye Hsu <[email protected]>
  • Loading branch information
chawyehsu authored Jan 20, 2024
1 parent 52d5d6d commit ce255da
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 11 deletions.
107 changes: 96 additions & 11 deletions install/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,91 @@
Specifies Pixi's home directory.
The default value is '$Env:USERPROFILE\.pixi'. You can also specify it by
setting the environment variable 'PIXI_HOME'.
.PARAMETER NoPathUpdate
If specified, the script will not update the PATH environment variable.
.LINK
https://pixi.sh
.LINK
https://github.com/prefix-dev/pixi
#>
param (
[string] $PixiVersion = 'latest',
[string] $PixiHome = "$Env:USERPROFILE\.pixi"
[string] $PixiHome = "$Env:USERPROFILE\.pixi",
[switch] $NoPathUpdate
)

Set-StrictMode -Version Latest

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 Write-Env {
param(
[String] $name,
[String] $val,
[Switch] $global
)

$RegisterKey = if ($global) {
Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
} else {
Get-Item -Path 'HKCU:'
}

$EnvRegisterKey = $RegisterKey.OpenSubKey('Environment', $true)
if ($null -eq $val) {
$EnvRegisterKey.DeleteValue($name)
} 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 Get-Env {
param(
[String] $name,
[Switch] $global
)

$RegisterKey = if ($global) {
Get-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
} else {
Get-Item -Path 'HKCU:'
}

$EnvRegisterKey = $RegisterKey.OpenSubKey('Environment')
$RegistryValueOption = [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
$EnvRegisterKey.GetValue($name, $null, $RegistryValueOption)
}

if ($Env:PIXI_VERSION) {
$PixiVersion = $Env:PIXI_VERSION
}
Expand All @@ -31,6 +104,10 @@ if ($Env:PIXI_HOME) {
$PixiHome = $Env:PIXI_HOME
}

if ($Env:PIXI_NO_PATH_UPDATE) {
$NoPathUpdate = $true
}

# Repository name
$REPO = 'prefix-dev/pixi'
$ARCH = 'x86_64'
Expand All @@ -57,26 +134,34 @@ try {

# Create the install dir if it doesn't exist
if (!(Test-Path -Path $BinDir)) {
New-Item -ItemType directory -Path $BinDir
New-Item -ItemType Directory -Path $BinDir | Out-Null
}

$ZIP_FILE = $TEMP_FILE + ".zip"
Rename-Item -Path $TEMP_FILE -NewName $ZIP_FILE

# Extract pixi from the downloaded zip file
Expand-Archive -Path $ZIP_FILE -DestinationPath $BinDir -Force

# Add pixi to PATH if the folder is not already in the PATH variable
$PATH = [Environment]::GetEnvironmentVariable("Path", "User")
if ($PATH -notlike "*$BinDir*") {
Write-Output "Adding $BinDir to PATH`n"
[Environment]::SetEnvironmentVariable("Path", "$BinDir;" + [Environment]::GetEnvironmentVariable("Path", "User"), "User")
} else {
Write-Output "$BinDir is already in PATH`n"
}
} catch {
Write-Host "Error: '$DOWNLOAD_URL' is not available or failed to download"
exit 1
} finally {
Remove-Item -Path $ZIP_FILE
}

# Add pixi to PATH if the folder is not already in the PATH variable
if (!$NoPathUpdate) {
$PATH = Get-Env 'PATH'
if ($PATH -notlike "*$BinDir*") {
Write-Output "Adding $BinDir to PATH"
# For future sessions
Write-Env -name 'PATH' -val "$BinDir;$PATH"
# For current session
$Env:PATH = "$BinDir;$PATH"
Write-Output "You may need to restart your shell"
} else {
Write-Output "$BinDir is already in PATH"
}
} else {
Write-Output "You may need to update your PATH manually to use pixi"
}
3 changes: 3 additions & 0 deletions install/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ update_shell() {
FILE=$1
LINE=$2

# shell update can be suppressed by `PIXI_NO_PATH_UPDATE` env var
[[ ! -z "$PIXI_NO_PATH_UPDATE" ]] && return

# Create the file if it doesn't exist
if [ -f "$FILE" ]; then
touch "$FILE"
Expand Down

0 comments on commit ce255da

Please sign in to comment.