fix(installer): symlink bundled node/npm into command bin dir for FHS root installs

Root installs on Linux (FHS layout, #15608) put the `hermes` command in
`/usr/local/bin` (on PATH) but symlinked the bundled node/npm/npx into
`~/.local/bin`, which isn't on PATH for a stock root shell. `node`/`npm`
were 'command not found' and `hermes dashboard` failed with 'npm is not
available' because its build-on-demand fallback couldn't find npm.

Fix: `install_node()` now symlinks into `get_command_link_dir()` — the same
helper the `hermes` command link already uses — so node/npm/npx land
wherever the command does (`/usr/local/bin` on FHS root, `~/.local/bin`
otherwise, `$PREFIX/bin` on Termux). Non-root and Termux installs are
unchanged.

Also fixes:
- `scripts/lib/node-bootstrap.sh`: adds `_nb_get_link_dir()` mirroring
  the same root/Termux/user logic for the standalone bootstrap path
  (used by `hermes update`, TUI node bootstrap, etc.)
- `hermes_cli/uninstall.py`: `remove_node_symlinks()` now checks all
  candidate directories (`~/.local/bin`, `/usr/local/bin`, `$PREFIX/bin`)
  so root FHS uninstalls don't leave orphan symlinks

Regression from #15608, which created the FHS path for the command but
left `install_node` pointed at the legacy user-local dir.
This commit is contained in:
alt-glitch
2026-06-04 13:34:42 +05:30
committed by Teknium
parent b1b0f4b668
commit aeec88c77f
4 changed files with 105 additions and 36 deletions

View File

@ -836,16 +836,20 @@ install_node() {
return 0
fi
# Place into ~/.hermes/node/ and symlink binaries to ~/.local/bin/
# Place into ~/.hermes/node/ and symlink binaries into the same bin dir
# the hermes command uses (get_command_link_dir): /usr/local/bin for root
# FHS installs, $PREFIX/bin on Termux, ~/.local/bin otherwise.
rm -rf "$HERMES_HOME/node"
mkdir -p "$HERMES_HOME"
mv "$extracted_dir" "$HERMES_HOME/node"
rm -rf "$tmp_dir"
mkdir -p "$HOME/.local/bin"
ln -sf "$HERMES_HOME/node/bin/node" "$HOME/.local/bin/node"
ln -sf "$HERMES_HOME/node/bin/npm" "$HOME/.local/bin/npm"
ln -sf "$HERMES_HOME/node/bin/npx" "$HOME/.local/bin/npx"
local node_link_dir
node_link_dir="$(get_command_link_dir)"
mkdir -p "$node_link_dir"
ln -sf "$HERMES_HOME/node/bin/node" "$node_link_dir/node"
ln -sf "$HERMES_HOME/node/bin/npm" "$node_link_dir/npm"
ln -sf "$HERMES_HOME/node/bin/npx" "$node_link_dir/npx"
export PATH="$HERMES_HOME/node/bin:$PATH"

View File

@ -44,6 +44,19 @@ _nb_is_termux() {
[ -n "${TERMUX_VERSION:-}" ] || [[ "${PREFIX:-}" == *"com.termux/files/usr"* ]]
}
# Where to symlink node/npm/npx so they land on PATH.
# Mirrors get_command_link_dir() from install.sh: root FHS → /usr/local/bin,
# Termux → $PREFIX/bin, otherwise ~/.local/bin.
_nb_get_link_dir() {
if _nb_is_termux && [ -n "${PREFIX:-}" ]; then
echo "$PREFIX/bin"
elif [ "$(id -u)" = 0 ] && [ "$(uname -s)" = "Linux" ]; then
echo "/usr/local/bin"
else
echo "$HOME/.local/bin"
fi
}
_nb_node_major() {
local v
v=$(node --version 2>/dev/null | sed 's/^v//' | cut -d. -f1)
@ -187,10 +200,12 @@ _nb_install_bundled_node() {
mv "$extracted" "$HERMES_HOME/node"
rm -rf "$tmp"
mkdir -p "$HOME/.local/bin"
ln -sf "$HERMES_HOME/node/bin/node" "$HOME/.local/bin/node"
ln -sf "$HERMES_HOME/node/bin/npm" "$HOME/.local/bin/npm"
ln -sf "$HERMES_HOME/node/bin/npx" "$HOME/.local/bin/npx"
local _link_dir
_link_dir="$(_nb_get_link_dir)"
mkdir -p "$_link_dir"
ln -sf "$HERMES_HOME/node/bin/node" "$_link_dir/node"
ln -sf "$HERMES_HOME/node/bin/npm" "$_link_dir/npm"
ln -sf "$HERMES_HOME/node/bin/npx" "$_link_dir/npx"
export PATH="$HERMES_HOME/node/bin:$PATH"
_nb_have_modern_node || return 1