Skip to content

fix(install): preserve pip entry point when re-running on symlinked install#25734

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-8f75015c
May 14, 2026
Merged

fix(install): preserve pip entry point when re-running on symlinked install#25734
teknium1 merged 1 commit into
mainfrom
hermes/hermes-8f75015c

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Re-running scripts/install.sh on a system installed with an older layout overwrites the pip-generated venv/bin/hermes console script with a self-execing bash wrapper, so hermes hangs silently with no output.

Root cause

setup_path() writes the user-facing launcher with cat > "$command_link_dir/hermes" <<EOF. Older installs created $command_link_dir/hermes as a symlink to $HERMES_BIN (venv/bin/hermes). The redirect follows the symlink and overwrites the pip entry point with the wrapper body. $HERMES_BIN then resolves to the same wrapper — exec calls itself, infinite loop.

This is the trigger behind the recursive-wrapper hang reported across #21802, #21454, #21513, and #24834.

Fix

One-line: rm -f "$command_link_dir/hermes" before the cat > heredoc, so the redirect always creates a fresh regular file and never follows a symlink back into the venv.

Salvage attribution

Cherry-picked from @Tranquil-Flow's #21513. Three contributors independently converged on this exact one-line fix — credit also to @wesleysimplicio (#22472) and @luyao618 (#24850).

Validation

Before fix After fix
venv/bin/hermes survives re-install overwritten with wrapper preserved as pip script
~/.local/bin/hermes after install symlink (will stomp again) regular file
hermes invocation hangs (recursive exec) runs

Confirmed live by reproducing the symlink-stomp end-to-end against the actual shim block in install.sh: pre-fix overwrites the pip entry point, post-fix leaves it intact.

Pinned by @Tranquil-Flow's regression test tests/test_install_sh_symlink_stomp.py (2/2 passing) — both a static guard that rm -f precedes the heredoc, and a behavioural reproducer that drives the real shim-write block.

Closes

Supersedes #22472, #24850 (same fix, later submissions).

…nstall

setup_path() writes the user-facing hermes shim with `cat >`, which
follows existing symlinks. Older installs created
`$command_link_dir/hermes` as a symlink to `$HERMES_BIN`
(`venv/bin/hermes`), so re-running install.sh stomped the pip entry
point with a bash shim that exec'd itself in an infinite loop.

`rm -f` the link target before writing so the shim lands at
`$command_link_dir/hermes` and the venv entry point is left intact.

Adds a regression test that reproduces the symlink-stomp end-to-end
(creates the symlink, drives the real shim-write block from setup_path,
asserts the venv pip script body survives and the shim is now a regular
file). Both new assertions fail on origin/main and pass with the fix.

Closes #21454.
@teknium1 teknium1 merged commit c75e1a0 into main May 14, 2026
14 of 15 checks passed
@teknium1 teknium1 deleted the hermes/hermes-8f75015c branch May 14, 2026 14:08
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-8f75015c vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8322 on HEAD, 8321 on base (🆕 +1)

🆕 New issues (1):

Rule Count
unresolved-import 1
First entries
tests/test_install_sh_symlink_stomp.py:23: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`

✅ Fixed issues: none

Unchanged: 4382 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

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

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

3 participants