PATH helper polish: venv precedence, quoted entries, raw/expanded dedup

Three small follow-ups surfaced by a 10-reviewer pass against the rebased
PR head. None fix a regression vs main; each strictly improves the new
helpers.

Refresh-SessionPath / Refresh-Environment:
- Move $env:Path to the front of the merge so an activated venv keeps
  precedence over machine/user PATH after a refresh. Pre-PR dropped
  process-only entries entirely; post-PR kept them but at the back.
- Dedup on both raw and expanded forms so %USERPROFILE%\foo and the
  already-expanded C:\Users\me\foo do not both survive.

Add-ToUserPath:
- Trim whitespace and surrounding double-quotes from each compared entry
  so quoted PATH entries like "C:\Program Files\CMake\bin" deduplicate
  against an unquoted directory of the same path.
This commit is contained in:
Daniel Han 2026-04-16 07:11:39 +00:00
commit 8e0f170495
2 changed files with 26 additions and 14 deletions

View file

@ -100,16 +100,21 @@ function Install-UnslothStudio {
Write-Host ""
# ── Helper: refresh PATH from registry (deduplicating entries) ──
# Process entries first so an activated venv keeps precedence, then
# machine/user. Dedup by both raw and expanded form so %VAR% and
# already-expanded copies of the same dir don't both survive.
function Refresh-SessionPath {
$machine = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
$user = [System.Environment]::GetEnvironmentVariable("Path", "User")
$merged = "$machine;$user;$env:Path"
$merged = "$env:Path;$machine;$user"
$seen = @{}
$unique = New-Object System.Collections.Generic.List[string]
foreach ($p in $merged -split ";") {
$key = $p.TrimEnd("\").ToLowerInvariant()
if ($key -and -not $seen.ContainsKey($key)) {
$seen[$key] = $true
$rawKey = $p.Trim().Trim('"').TrimEnd("\").ToLowerInvariant()
$expKey = [Environment]::ExpandEnvironmentVariables($p).Trim().Trim('"').TrimEnd("\").ToLowerInvariant()
if ($rawKey -and -not $seen.ContainsKey($rawKey) -and -not $seen.ContainsKey($expKey)) {
$seen[$rawKey] = $true
if ($expKey -and $expKey -ne $rawKey) { $seen[$expKey] = $true }
$unique.Add($p)
}
}
@ -128,10 +133,11 @@ function Install-UnslothStudio {
try {
$rawPath = $regKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
$entries = if ($rawPath) { $rawPath -split ';' } else { @() }
$normalDir = $Directory.TrimEnd('\').ToLowerInvariant()
$normalDir = $Directory.Trim().Trim('"').TrimEnd('\').ToLowerInvariant()
foreach ($entry in $entries) {
$rawNorm = $entry.TrimEnd('\').ToLowerInvariant()
$expNorm = [Environment]::ExpandEnvironmentVariables($entry).TrimEnd('\').ToLowerInvariant()
$stripped = $entry.Trim().Trim('"')
$rawNorm = $stripped.TrimEnd('\').ToLowerInvariant()
$expNorm = [Environment]::ExpandEnvironmentVariables($stripped).TrimEnd('\').ToLowerInvariant()
if ($rawNorm -eq $normalDir -or $expNorm -eq $normalDir) {
return $false # already present
}

View file

@ -73,13 +73,18 @@ function Refresh-Environment {
}
$machinePath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
$userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
$merged = "$machinePath;$userPath;$env:Path"
# Process entries first so an activated venv keeps precedence, then
# machine/user. Dedup by both raw and expanded form so %VAR% and
# already-expanded copies of the same dir don't both survive.
$merged = "$env:Path;$machinePath;$userPath"
$seen = @{}
$unique = New-Object System.Collections.Generic.List[string]
foreach ($p in $merged -split ";") {
$key = $p.TrimEnd("\").ToLowerInvariant()
if ($key -and -not $seen.ContainsKey($key)) {
$seen[$key] = $true
$rawKey = $p.Trim().Trim('"').TrimEnd("\").ToLowerInvariant()
$expKey = [Environment]::ExpandEnvironmentVariables($p).Trim().Trim('"').TrimEnd("\").ToLowerInvariant()
if ($rawKey -and -not $seen.ContainsKey($rawKey) -and -not $seen.ContainsKey($expKey)) {
$seen[$rawKey] = $true
if ($expKey -and $expKey -ne $rawKey) { $seen[$expKey] = $true }
$unique.Add($p)
}
}
@ -98,10 +103,11 @@ function Add-ToUserPath {
try {
$rawPath = $regKey.GetValue('Path', '', [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
$entries = if ($rawPath) { $rawPath -split ';' } else { @() }
$normalDir = $Directory.TrimEnd('\').ToLowerInvariant()
$normalDir = $Directory.Trim().Trim('"').TrimEnd('\').ToLowerInvariant()
foreach ($entry in $entries) {
$rawNorm = $entry.TrimEnd('\').ToLowerInvariant()
$expNorm = [Environment]::ExpandEnvironmentVariables($entry).TrimEnd('\').ToLowerInvariant()
$stripped = $entry.Trim().Trim('"')
$rawNorm = $stripped.TrimEnd('\').ToLowerInvariant()
$expNorm = [Environment]::ExpandEnvironmentVariables($stripped).TrimEnd('\').ToLowerInvariant()
if ($rawNorm -eq $normalDir -or $expNorm -eq $normalDir) {
return $false # already present
}