fix(install): put ludic on PATH in every shell, not just $SHELL's
The installer edited one profile — whichever ~/.zshrc or ~/.bashrc $SHELL pointed at — and skipped any profile that did not already exist. So a fresh account got nothing written at all, a bash user's ~/.bashrc is not read by the login shell macOS Terminal starts, and ~/.zshrc is only read by interactive zsh. The toolchain installed correctly and `ludic` was still not a command. The PATH edit now lives in one file, <install>/env (plus env.fish), and each profile gets a single line that sources it: ~/.profile for sh and for login bash with no .bash_profile, ~/.zshenv because zsh never reads ~/.profile and reads this one for every invocation, ~/.bashrc and ~/.bash_profile when they already exist, and fish's config when fish is installed. Missing .profile/.zshenv are created; .bash_profile deliberately is not, since creating it would stop bash from reading ~/.profile at all. Sourcing a shared file rather than appending an export keeps a re-install from accumulating a second entry, and leaves one place to delete when uninstalling. Verified with a staged HOME: zsh -i, zsh -c, bash -l, bash -i and sh -l all resolve ludic; a second run reports "already on your PATH" and writes nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
29fcef3b9c
commit
44e752b606
3 changed files with 90 additions and 41 deletions
|
|
@ -42,8 +42,10 @@ formatter and the language server — with one command:
|
||||||
curl -fsSL https://workshopsoft.pages.workshopsoft.io/ludic/install.sh | sh
|
curl -fsSL https://workshopsoft.pages.workshopsoft.io/ludic/install.sh | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
It installs into `~/.ludic` and puts `~/.ludic/bin` on your `PATH`; nothing else
|
It installs into `~/.ludic` and puts `~/.ludic/bin` on your `PATH` in every
|
||||||
on the machine is touched, and uninstalling is `rm -rf ~/.ludic`. Where a
|
shell — the PATH line lives in `~/.ludic/env`, sourced from `~/.profile`,
|
||||||
|
`~/.zshenv` and your bash or fish config. Nothing else on the machine is touched;
|
||||||
|
uninstalling is `rm -rf ~/.ludic` and deleting those two-line blocks. Where a
|
||||||
prebuilt toolchain exists for your platform it is downloaded and verified against
|
prebuilt toolchain exists for your platform it is downloaded and verified against
|
||||||
a published checksum; where it does not, the installer bootstraps from the
|
a published checksum; where it does not, the installer bootstraps from the
|
||||||
compiler's own IR seed with clang. Either way you need clang (or Xcode's Command
|
compiler's own IR seed with clang. Either way you need clang (or Xcode's Command
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,11 @@ type: fix
|
||||||
`bin/ludicc` and `VERSION` beside the *current* directory, so it answered
|
`bin/ludicc` and `VERSION` beside the *current* directory, so it answered
|
||||||
"(version unknown)" from a project — which is the only place a user ever runs it.
|
"(version unknown)" from a project — which is the only place a user ever runs it.
|
||||||
It now resolves the compiler through the install root, like every other command.
|
It now resolves the compiler through the install root, like every other command.
|
||||||
|
|
||||||
|
`install.sh` also now puts `ludic` on `PATH` for every shell, not just the one
|
||||||
|
`$SHELL` names. The PATH edit lives in one file (`~/.ludic/env`) that each
|
||||||
|
profile sources, and the profiles are chosen to cover what people actually open:
|
||||||
|
`~/.profile` for sh and login bash, `~/.zshenv` because zsh never reads
|
||||||
|
`~/.profile`, `~/.bashrc`/`~/.bash_profile` when they already exist, and fish's
|
||||||
|
config when fish is installed. Re-running the installer does not add a second
|
||||||
|
copy, and `--no-modify-path` still touches nothing.
|
||||||
|
|
|
||||||
103
install.sh
103
install.sh
|
|
@ -219,35 +219,75 @@ install_from_source() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---- PATH -------------------------------------------------------------------
|
# ---- PATH -------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# "Installed but `ludic` is not a command" is the most common way an installer
|
||||||
|
# fails, so this is deliberate about it.
|
||||||
|
#
|
||||||
|
# The PATH edit itself lives in one file, <install>/env, and each shell profile
|
||||||
|
# gets a single line that sources it. That keeps the change easy to find, easy to
|
||||||
|
# undo (delete the line, delete ~/.ludic), and means a later install does not
|
||||||
|
# accumulate a second export.
|
||||||
|
#
|
||||||
|
# Which profiles: enough to cover every shell the user actually opens, not just
|
||||||
|
# the one $SHELL happens to name.
|
||||||
|
#
|
||||||
|
# ~/.profile sh, dash, and bash login shells that have no .bash_profile.
|
||||||
|
# Created when missing — it is the portable catch-all.
|
||||||
|
# ~/.bash_profile bash login shells (what macOS Terminal starts). Only touched
|
||||||
|
# ~/.bashrc when they already exist: creating .bash_profile would stop
|
||||||
|
# bash from reading ~/.profile and silently break other tools.
|
||||||
|
# ~/.zshenv zsh reads this for *every* invocation, interactive or not,
|
||||||
|
# and never reads ~/.profile. Created when missing.
|
||||||
|
# fish config only when fish is installed.
|
||||||
|
|
||||||
# The shell profiles worth touching: the login shell's, plus ~/.profile as the
|
# write <install>/env and <install>/env.fish — the one place the PATH is set
|
||||||
# catch-all. Appending a guarded line is the least surprising thing an installer
|
write_env_files() {
|
||||||
# can do to someone's dotfiles, and it is easy to find and delete.
|
cat > "${INSTALL_DIR}/env" <<EOF
|
||||||
profiles() {
|
# Adds the Ludic toolchain to PATH. Sourced from your shell profile; safe to
|
||||||
case "${SHELL:-}" in
|
# source more than once. Written by install.sh — edit ~/.ludic instead.
|
||||||
*/zsh) printf '%s\n' "${ZDOTDIR:-$HOME}/.zshrc" ;;
|
case ":\${PATH}:" in
|
||||||
*/bash) printf '%s\n' "$HOME/.bashrc" ;;
|
*":${INSTALL_DIR}/bin:"*) ;;
|
||||||
*/fish) printf '%s\n' "$HOME/.config/fish/config.fish" ;;
|
*) PATH="${INSTALL_DIR}/bin:\${PATH}"; export PATH ;;
|
||||||
esac
|
esac
|
||||||
[ -f "$HOME/.profile" ] && printf '%s\n' "$HOME/.profile"
|
EOF
|
||||||
|
cat > "${INSTALL_DIR}/env.fish" <<EOF
|
||||||
|
# Adds the Ludic toolchain to PATH (fish). Written by install.sh.
|
||||||
|
if not contains "${INSTALL_DIR}/bin" \$PATH
|
||||||
|
set -gx PATH "${INSTALL_DIR}/bin" \$PATH
|
||||||
|
end
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# append the source line to one profile, unless it is already there
|
||||||
|
add_line() {
|
||||||
|
_file="$1"
|
||||||
|
_line="$2"
|
||||||
|
if [ -f "$_file" ] && grep -qF "$_line" "$_file" 2>/dev/null; then
|
||||||
|
ALREADY="${ALREADY} ${_file}"
|
||||||
return 0
|
return 0
|
||||||
|
fi
|
||||||
|
mkdir -p "$(dirname "$_file")" 2>/dev/null || true
|
||||||
|
printf '\n# ludic\n%s\n' "$_line" >> "$_file" || {
|
||||||
|
warn "could not write ${_file}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
TOUCHED="${TOUCHED} ${_file}"
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_path() {
|
add_to_path() {
|
||||||
_bin="${INSTALL_DIR}/bin"
|
|
||||||
case ":${PATH}:" in *":${_bin}:"*) return 0 ;; esac
|
|
||||||
[ "$MODIFY_PATH" -eq 1 ] || return 0
|
[ "$MODIFY_PATH" -eq 1 ] || return 0
|
||||||
_added=''
|
write_env_files
|
||||||
for _p in $(profiles); do
|
_posix=". \"${INSTALL_DIR}/env\""
|
||||||
[ -e "$_p" ] || continue
|
|
||||||
if grep -q 'ludic/bin\|LUDIC_INSTALL' "$_p" 2>/dev/null; then _added="$_p"; continue; fi
|
add_line "${HOME}/.profile" "$_posix"
|
||||||
case "$_p" in
|
add_line "${ZDOTDIR:-$HOME}/.zshenv" "$_posix"
|
||||||
*/config.fish) printf '\n# Ludic\nset -gx PATH %s $PATH\n' "$_bin" >> "$_p" ;;
|
# bash: only files that already exist, so we never shadow ~/.profile
|
||||||
*) printf '\n# Ludic\nexport PATH="%s:$PATH"\n' "$_bin" >> "$_p" ;;
|
[ -f "${HOME}/.bash_profile" ] && add_line "${HOME}/.bash_profile" "$_posix"
|
||||||
esac
|
[ -f "${HOME}/.bashrc" ] && add_line "${HOME}/.bashrc" "$_posix"
|
||||||
_added="$_p"
|
if have fish || [ -f "${HOME}/.config/fish/config.fish" ]; then
|
||||||
done
|
add_line "${HOME}/.config/fish/config.fish" "source \"${INSTALL_DIR}/env.fish\""
|
||||||
PATH_NOTE="$_added"
|
fi
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---- go ---------------------------------------------------------------------
|
# ---- go ---------------------------------------------------------------------
|
||||||
|
|
@ -293,7 +333,8 @@ else
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PATH_NOTE=''
|
TOUCHED=''
|
||||||
|
ALREADY=''
|
||||||
add_to_path
|
add_to_path
|
||||||
|
|
||||||
# ---- report -----------------------------------------------------------------
|
# ---- report -----------------------------------------------------------------
|
||||||
|
|
@ -314,21 +355,19 @@ if [ "$OS" != darwin ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
say ""
|
say ""
|
||||||
if [ -n "$PATH_NOTE" ]; then
|
if [ "$MODIFY_PATH" -eq 1 ]; then
|
||||||
say " ${DIM}added ${INSTALL_DIR}/bin to your PATH in ${PATH_NOTE} — open a new shell, or:${R}"
|
[ -n "${TOUCHED# }" ] && say " ${DIM}added ${INSTALL_DIR}/bin to your PATH in:${R}${TOUCHED# }"
|
||||||
say " export PATH=\"${INSTALL_DIR}/bin:\$PATH\""
|
[ -n "${ALREADY# }" ] && say " ${DIM}already on your PATH in:${R}${ALREADY# }"
|
||||||
say ""
|
fi
|
||||||
else
|
|
||||||
case ":${PATH}:" in
|
case ":${PATH}:" in
|
||||||
*":${INSTALL_DIR}/bin:"*) ;;
|
*":${INSTALL_DIR}/bin:"*) ;;
|
||||||
*)
|
*)
|
||||||
say " ${DIM}add this to your shell profile:${R}"
|
say " ${DIM}this shell was started before that, so for right now:${R}"
|
||||||
say " export PATH=\"${INSTALL_DIR}/bin:\$PATH\""
|
say " export PATH=\"${INSTALL_DIR}/bin:\$PATH\""
|
||||||
say ""
|
say " ${DIM}(new terminals pick it up on their own)${R}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
say ""
|
||||||
|
|
||||||
say "next:"
|
say "next:"
|
||||||
say " ${B}ludic new mygame${R} create a project"
|
say " ${B}ludic new mygame${R} create a project"
|
||||||
say " ${B}cd mygame && ludic run${R} build it and play"
|
say " ${B}cd mygame && ludic run${R} build it and play"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue