Skip to content

Fix install.ps1 crash when piped through iex and render in PowerShell 5.1 - #2

Open
devin-ai-integration[bot] wants to merge 2 commits into
devfrom
devin/1778501892-install-ps1-source-fallback-fix
Open

Fix install.ps1 crash when piped through iex and render in PowerShell 5.1#2
devin-ai-integration[bot] wants to merge 2 commits into
devfrom
devin/1778501892-install-ps1-source-fallback-fix

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented May 11, 2026

Copy link
Copy Markdown

Summary

Fixes three bugs surfaced when running the one-liner installer in stock Windows PowerShell 5.1:

[1/5] Detected: Windows x64 -> hackcode-windows-x64
[2/5] Getting HackCode...
  No release artifact available (The remote server returned an error: (404) Not Found.).
  Building from source...
iex : Cannot bind argument to parameter 'Path' because it is an empty string.
  1. Empty $PSScriptRoot when piped through iexJoin-Path $PSScriptRoot 'rust\Cargo.toml' threw Cannot bind argument to parameter 'Path' because it is an empty string. right after "Building from source...". Replaced with a Get-LocalCheckoutDir helper that falls back to $PSCommandPath and $MyInvocation.MyCommand.Path, finally returning $null. The source-build branch treats $null as "no local checkout" and skips straight to the user-scope git clone. Also added a Test-Command 'git' guard with a winget install Git.Git hint and a $LASTEXITCODE check on the clone.

  2. `e is not an ESC literal in Windows PowerShell 5.1 — only PowerShell 6+ interprets it. The user's transcript showing literal e[38;2;0;255;65m confirms this. Replaced with $ESC = [char]27 so ANSI sequences render correctly on 5.1 (Win10/11 ConsoleHost supports VT sequences when raw ANSI is emitted).

  3. Box-drawing glyphs rendered as ? because the default OEM console code page can't represent them. Set [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 early (wrapped in try/catch in case the host forbids it).

Review & Testing Checklist for Human

  • Re-run the one-liner on Windows 10/11 in a fresh non-elevated PowerShell: iwr https://raw.githubusercontent.com/johnesecat/hackcode-main/dev/install.ps1 | iex — confirm it gets past "Building from source..." instead of throwing the iex : Cannot bind argument to parameter 'Path' error.
  • Confirm the banner renders in green with proper box-drawing glyphs (not e[38;2;0;255;65m literal text and not ? boxes).
  • Confirm hackcode.exe lands at %LOCALAPPDATA%\Programs\HackCode\hackcode.exe and hackcode --version works in a new PowerShell session.

Notes

  • Verified the parser accepts the script (Parser.ParseFile returned no errors) and end-to-end dry-ran both the iex-piped path and the local-checkout path under pwsh on Linux with stubbed network/exec calls. Both branches reach "Installation complete!" without the bug.
  • iwr | iex will use the default branch of the repo, so the user needs the PR merged (or the curl URL pointing at this branch) before re-running.

Link to Devin session: https://app.devin.ai/sessions/f5985bf35b3c4979b88e83e6ccf371e3
Requested by: @johnesecat


Open in Devin Review

Three bugs surfaced by running the one-liner installer in stock Windows
PowerShell 5.1:

1. $PSScriptRoot is empty when the script is piped through Invoke-Expression
   (iwr ... | iex), so `Join-Path $PSScriptRoot 'rust\Cargo.toml'` threw
   'Cannot bind argument to parameter Path because it is an empty string'
   right after 'Building from source...'. Introduce a Get-LocalCheckoutDir
   helper that falls back to $PSCommandPath and $MyInvocation.MyCommand.Path
   and finally returns $null. The source-build branch now treats $null as
   'no local checkout' and skips straight to the user-scope git clone.

2. The backtick-e escape (`e) is only an ESC literal in PowerShell 6+.
   In Windows PowerShell 5.1 it's just the character 'e', which is why the
   user saw literal 'e[38;2;0;255;65m' in the output instead of green text.
   Replace with $ESC = [char]27 so ANSI sequences render on 5.1 too.

3. Box-drawing glyphs printed as '?' on the user's terminal because the
   default OEM code page can't represent them. Set [Console]::OutputEncoding
   to UTF-8 early in the script (wrapped in try/catch in case the host
   forbids it).

Co-Authored-By: jacob levesque <jaemlev@icloud.com>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment thread install.ps1
Comment on lines +226 to +227
git -C $SrcDir fetch --quiet origin 2>$null | Out-Null
git -C $SrcDir reset --quiet --hard origin/HEAD 2>$null | Out-Null

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Missing error check after git fetch / git reset allows silent build from stale source

The new git fetch + git reset --hard origin/HEAD path (lines 226-227) suppresses all output and stderr (2>$null | Out-Null) but never checks $LASTEXITCODE. If git fetch fails (e.g., network error), git reset --hard origin/HEAD will silently succeed by resetting to whatever was last fetched — potentially very outdated code. The script then proceeds to build and install that stale version without any warning. This is inconsistent with the git clone path at install.ps1:232-234, where $LASTEXITCODE is properly checked and an error is thrown on failure.

Suggested change
git -C $SrcDir fetch --quiet origin 2>$null | Out-Null
git -C $SrcDir reset --quiet --hard origin/HEAD 2>$null | Out-Null
git -C $SrcDir fetch --quiet origin 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
Info "git fetch failed (exit code $LASTEXITCODE); building from existing checkout"
}
git -C $SrcDir reset --quiet --hard origin/HEAD 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "git reset failed with exit code $LASTEXITCODE"
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Addresses Devin Review feedback on PR #2: the previous diff suppressed
all output from `git fetch` and `git reset --hard origin/HEAD` without
checking $LASTEXITCODE. If `git fetch` failed (e.g. transient network
error) the subsequent `reset` would silently succeed against whatever
was last fetched and the script would build a potentially stale tree.

Now we surface fetch failures as an Info notice (the existing checkout
is still usable, so we don't abort) and throw if the reset itself fails.

Co-Authored-By: jacob levesque <jaemlev@icloud.com>
johnesecat added a commit that referenced this pull request May 11, 2026
…offline

* Fix install.ps1 crash when piped through iex and render in PS 5.1

Three bugs surfaced by running the one-liner installer in stock Windows
PowerShell 5.1:

1. $PSScriptRoot is empty when the script is piped through Invoke-Expression
   (iwr ... | iex), so `Join-Path $PSScriptRoot 'rust\Cargo.toml'` threw
   'Cannot bind argument to parameter Path because it is an empty string'
   right after 'Building from source...'. Introduce a Get-LocalCheckoutDir
   helper that falls back to $PSCommandPath and $MyInvocation.MyCommand.Path
   and finally returns $null. The source-build branch now treats $null as
   'no local checkout' and skips straight to the user-scope git clone.

2. The backtick-e escape (`e) is only an ESC literal in PowerShell 6+.
   In Windows PowerShell 5.1 it's just the character 'e', which is why the
   user saw literal 'e[38;2;0;255;65m' in the output instead of green text.
   Replace with $ESC = [char]27 so ANSI sequences render on 5.1 too.

3. Box-drawing glyphs printed as '?' on the user's terminal because the
   default OEM code page can't represent them. Set [Console]::OutputEncoding
   to UTF-8 early in the script (wrapped in try/catch in case the host
   forbids it).

Co-Authored-By: jacob levesque <jaemlev@icloud.com>

* Check git fetch/reset exit codes in source-build fallback (cherry-picked from PR #2)

Co-Authored-By: jacob levesque <jaemlev@icloud.com>

* Windows audit, offline/proxy install support, clippy/fmt cleanup

Windows correctness fixes:
- platform::extra_path now adds \$USERPROFILE\.cargo\bin so freshly-installed Rust user binaries are discoverable.
- bash tool degrades to 'cmd /C' on Windows (no /bin/sh).
  Existing POSIX-only printf tests now gated to #[cfg(unix)].
- plugins/runtime hooks::shell_command: fix Windows mut warning, gate
  unused std::path::Path import.
- file_ops symlink test scoped under #[cfg(unix)] (Windows had unused let).

install.ps1 network-restricted / offline support:
- New flags: -OfflineSource, -OfflineZip, -Proxy,
  -ProxyUseDefaultCredentials, -Repo.
- Auto-detect HTTP_PROXY/HTTPS_PROXY env vars.
- Get-WebRequestSplat applies proxy + NTLM credentials uniformly to all
  Invoke-WebRequest calls (release zip, rustup-init, git fallback).
- Friendly error when Zscaler/raw.githubusercontent.com filtering hits,
  pointing user at -OfflineSource or -OfflineZip workflow.

Docs:
- New INSTALL.md: Linux/macOS quickstart, Windows quickstart, three
  network-restricted workflows (proxy, offline source, offline zip),
  troubleshooting, install locations.
- README points at INSTALL.md for restricted networks.
- .gitignore picks up .hackcode/, .hackcode-agents/, .hackcode-src/
  runtime artefacts so they don't get committed.

Rust workspace cleanup so cargo clippy --workspace --all-targets -- -D
warnings now passes clean on both Linux and x86_64-pc-windows-gnu:
- Workspace [lints.clippy] allows the pedantic / style lints that newer
  clippy releases (1.95+) added but that the existing codebase has many
  of (doc_markdown, match_same_arms, too_many_lines, uninlined_format_args,
  cast_possible_truncation, type_complexity, manual_split_once, etc.).
  Substantive lints (correctness, suspicious, perf) stay enforced.
- A handful of substantive fixes were applied directly rather than
  allow-listed: redundant pattern matching, identical match arms,
  doc-comment backticks, is_ok_and on a Result.
- cargo clippy --fix + scripts/fmt.sh swept the remaining cascade of
  formatting nits across crates touched by the lint changes.

Co-Authored-By: jacob levesque <jaemlev@icloud.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: jacob levesque <jaemlev@icloud.com>
@devin-ai-integration

Copy link
Copy Markdown
Author

Closing — the install.ps1 crash + PS 5.1 render fixes from this PR were cherry-picked into #3 (commit 3e2cc9f) and are now on dev as of the #3 merge. No further action needed on this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant