From 9662b76d592025c1536a6d7e0cb9aa317c09cc4e Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Thu, 11 Jun 2026 12:49:58 +0530 Subject: [PATCH] fix(install/windows): merge PATH in Update-ProcessPathForPackages instead of overwriting Follow-up to the winget stale-registration fix. Update-ProcessPathForPackages rebuilt $env:Path wholesale from the persisted User+Machine hives (plus winget's Links dir), discarding any process-only PATH entries added earlier in the installer run. Since the helper now runs after every package manager, that wholesale replace is more likely to clobber a process-local entry than the original winget-branch-only version was. Merge instead: seed from the current process PATH, then append hive and winget-Links entries not already present, with a case-insensitive, order-preserving dedupe. Behaviour on a clean box is unchanged (the hive entries are simply appended); the difference is that pre-existing process-only entries now survive the refresh. --- scripts/install.ps1 | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/scripts/install.ps1 b/scripts/install.ps1 index 23a602ca9e8..b316a99e4f7 100644 --- a/scripts/install.ps1 +++ b/scripts/install.ps1 @@ -893,19 +893,39 @@ function Test-Node { } function Update-ProcessPathForPackages { - # Rebuild the current process PATH from the persisted User+Machine hives plus - # winget's alias-shim directory, so a freshly-installed shim (rg.exe, - # ffmpeg.exe) becomes visible to Get-Command in THIS process without - # spawning a new shell. Called after every package-manager attempt - # (winget/choco/scoop): previously PATH was only refreshed inside the winget - # branch, so a successful choco/scoop fallback -- or any install on a box - # without winget -- could be misreported as "not installed". - $envPath = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine") + # Make freshly-installed shims (rg.exe, ffmpeg.exe) visible to Get-Command in + # THIS process without spawning a new shell, by folding the persisted + # User+Machine hives plus winget's alias-shim directory into $env:Path. + # Called after every package-manager attempt (winget/choco/scoop): previously + # PATH was only refreshed inside the winget branch, so a successful + # choco/scoop fallback -- or any install on a box without winget -- could be + # misreported as "not installed". + # + # MERGE rather than overwrite: start from the existing process PATH so any + # process-only entries added earlier in this installer run survive, then + # APPEND hive/winget-Links entries not already present (case-insensitive, + # order-preserving dedupe). A wholesale replace would silently drop those + # process-only entries. + $candidates = @() + $candidates += $env:Path + $candidates += [Environment]::GetEnvironmentVariable("Path", "User") + $candidates += [Environment]::GetEnvironmentVariable("Path", "Machine") $wingetLinks = Join-Path $env:LOCALAPPDATA "Microsoft\WinGet\Links" if (Test-Path $wingetLinks) { - $envPath = "$envPath;$wingetLinks" + $candidates += $wingetLinks } - $env:Path = $envPath + $seen = New-Object System.Collections.Generic.HashSet[string] ([StringComparer]::OrdinalIgnoreCase) + $ordered = New-Object System.Collections.Generic.List[string] + foreach ($chunk in $candidates) { + if ([string]::IsNullOrEmpty($chunk)) { continue } + foreach ($entry in $chunk.Split(';')) { + $trimmed = $entry.Trim() + if ($trimmed -and $seen.Add($trimmed)) { + $ordered.Add($trimmed) + } + } + } + $env:Path = [string]::Join(';', $ordered) } function Install-SystemPackages {