From: Max Vilimpoc Date: Mon, 28 Sep 2026 11:04:14 +0000 (+0200) Subject: dotfiles: stop the per-user ssh.exe check killing the ssh.exe it tests X-Git-Url: https://vilimpoc.org/repos/dotfiles/commitdiff_plain/d254a9bebd5448269d34a5c6dfcd36b646659b31 dotfiles: stop the per-user ssh.exe check killing the ssh.exe it tests The GitConfig step picks the ssh.exe git gets by running each candidate's -V, and it still used the spelling 4658d6d removed from the elevated half: try { $version = (& $cand -V 2>&1 | Select-Object -First 1) } catch { } Select-Object stops the pipeline as soon as ssh.exe has written its banner, before it has exited; PowerShell kills it and the exit code comes back -1. Measured under Windows PowerShell 5.1 against a healthy C:\Tools\rsync\ssh.exe: 19 of 20 runs reported -1 that way, 0 of 20 once the output was collected first. So the check usually judged the fast client broken and pointed core.sshCommand at the in-box one - the ~17MB/s client the rsync step exists to avoid. The last run here happened to land on the lucky twentieth. Collect the output, then take its first line, as the elevated half does. Found by chasing "System error." warnings (event 4100) in the PowerShell operational log. Those are otherwise harmless: Windows PowerShell 5.1 logs one whenever Select-Object -First stops a nested pipeline early - the exception it stops it with carries no message, and .NET's default text is "System error." This check was the one place that early stop killed a process whose exit code mattered. Co-Authored-By: Claude Opus 5.5 --- diff --git a/setup-windows-no-uac.ps1 b/setup-windows-no-uac.ps1 index 2a104fb..50cdd89 100644 --- a/setup-windows-no-uac.ps1 +++ b/setup-windows-no-uac.ps1 @@ -373,7 +373,17 @@ function Set-GlobalGitConfig { # run would otherwise read as success. $global: because a bare assignment # would make a local copy that the native call then does not update. $global:LASTEXITCODE = $null - try { $version = (& $cand -V 2>&1 | Select-Object -First 1) } catch { } + # Collect ALL the output, THEN take its first line. Piped straight into + # `Select-Object -First 1`, which is how this used to read, PowerShell + # stops the pipeline the moment ssh.exe prints its banner - before it + # has exited - kills it, and the exit code comes back -1 instead of 0. + # Measured under Windows PowerShell 5.1 against a healthy + # C:\Tools\rsync\ssh.exe: 19 of 20 runs reported -1 that way, 0 of 20 + # once collected first. So this check usually judged the fast client + # broken and handed git the in-box one it exists to avoid. + # setup-windows-with-uac.ps1 fixed the same trap in its own ssh.exe + # check (see DRAIN THE OUTPUT there); this copy was missed. + try { $sshOut = @(& $cand -V 2>&1); $version = $sshOut[0] } catch { } finally { $ErrorActionPreference = $prevEap } if ($LASTEXITCODE -eq 0) { $winSsh = $cand; break } $why = if ($null -eq $LASTEXITCODE) { 'it would not start' } else { "exit $LASTEXITCODE" }