fix(shell): restore always-on PATH after macOS path_helper
path_helper runs after ~/.zshenv in login shells and puts Homebrew ahead of fnm, pyenv, and ~/.local/bin. Re-source ~/.zshenv from ~/.zprofile and make prepends idempotent so login and zsh -c resolve the same binaries.
This commit is contained in:
1 parent
82c6a57c3a
commit
34d11b5aa4
8 files changed
+198
-73
No files matched your search
@@ -1,13 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install easyzsh shell stubs into a home directory.
|
||||
# Overwrites: ~/.zshenv ~/.zshrc
|
||||
# Installs: ~/.zprofile (re-applies ~/.zshenv after macOS path_helper)
|
||||
# Never overwrites: ~/.config/zsh/local.zsh ~/.config/zshrc/** ~/.local/bin/**
|
||||
# Does not manage ~/.zprofile (machine/login hooks belong in local.zsh).
|
||||
# Extra ~/.zprofile lines stay as login-only hooks unless --migrate-zprofile
|
||||
# folds them into local.zsh.
|
||||
#
|
||||
# Usage:
|
||||
# ./deploy.sh
|
||||
# ./deploy.sh --home /path/to/home
|
||||
# ./deploy.sh --migrate-zprofile # fold real ~/.zprofile into local.zsh, then remove stub
|
||||
# ./deploy.sh --migrate-zprofile # fold extra ~/.zprofile lines into local.zsh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -58,6 +60,9 @@ file_has_content() {
|
||||
[[ -f "$1" ]] && grep -q '[^[:space:]]' "$1"
|
||||
}
|
||||
|
||||
ZPROFILE_MARKER='# easyzsh: reapply always-on PATH after macOS path_helper'
|
||||
PYENV_LOGIN_HOOK='[[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/zsh/pyenv.zsh" ]] && . "${XDG_CONFIG_HOME:-$HOME/.config}/zsh/pyenv.zsh"'
|
||||
|
||||
is_easyzsh_zprofile_stub() {
|
||||
local f="$1"
|
||||
[[ -f "$f" ]] || return 1
|
||||
@@ -68,9 +73,25 @@ is_easyzsh_zprofile_stub() {
|
||||
grep -Eq 'easyzsh|PATH lives in|Leave this file empty|prefer.*local\.zsh' "$f"
|
||||
}
|
||||
|
||||
has_pyenv_login_hook() {
|
||||
local hook='[[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/zsh/pyenv.zsh" ]] && . "${XDG_CONFIG_HOME:-$HOME/.config}/zsh/pyenv.zsh"'
|
||||
[[ -f "$1" ]] && grep -Fqx "$hook" "$1"
|
||||
is_pyenv_only_zprofile() {
|
||||
local f="$1"
|
||||
local body
|
||||
[[ -f "$f" ]] || return 1
|
||||
body=$(grep -Ev '^[[:space:]]*(#|$)' "$f" || true)
|
||||
[[ "$body" == "$PYENV_LOGIN_HOOK" ]]
|
||||
}
|
||||
|
||||
# Lines that are not the managed path_helper block or the old pyenv login hook.
|
||||
zprofile_extras() {
|
||||
local f="$1"
|
||||
[[ -f "$f" ]] || return 0
|
||||
awk -v marker="$ZPROFILE_MARKER" -v hook="$PYENV_LOGIN_HOOK" '
|
||||
$0 == marker { in_block=1; next }
|
||||
in_block && $0 == "fi" { in_block=0; next }
|
||||
in_block { next }
|
||||
$0 == hook { next }
|
||||
{ print }
|
||||
' "$f"
|
||||
}
|
||||
|
||||
echo "Deploying easyzsh shell stubs into $TARGET_HOME"
|
||||
@@ -104,45 +125,49 @@ if [[ ! -f "$LOCAL_ZSH" ]]; then
|
||||
rm -f "$tmp"
|
||||
fi
|
||||
|
||||
# Optional: fold a real (non-stub) ~/.zprofile into local.zsh.
|
||||
if [[ "$MIGRATE_ZPROFILE" -eq 1 && -f "$ZPROFILE" ]]; then
|
||||
if has_pyenv_login_hook "$ZPROFILE"; then
|
||||
# ponytail: keep the whole profile; split migration only if per-line ownership is needed.
|
||||
echo "Keeping ~/.zprofile: contains the pyenv login hook"
|
||||
elif is_easyzsh_zprofile_stub "$ZPROFILE"; then
|
||||
echo "Removing easyzsh ~/.zprofile stub (hooks live in local.zsh / .zshenv)"
|
||||
rm -f "$ZPROFILE"
|
||||
elif [[ ! -f "$LOCAL_ZSH" ]]; then
|
||||
zprofile_extract=$(mktemp)
|
||||
awk '
|
||||
/Created by `pipx`/ { skip_pipx=1; next }
|
||||
skip_pipx && /local\/bin/ { skip_pipx=0; next }
|
||||
skip_pipx { next }
|
||||
{ print }
|
||||
' "$ZPROFILE" >"$zprofile_extract"
|
||||
if file_has_content "$zprofile_extract"; then
|
||||
cp "$zprofile_extract" "$LOCAL_ZSH"
|
||||
echo "Migrated ~/.zprofile body -> ~/.config/zsh/local.zsh"
|
||||
rm -f "$ZPROFILE"
|
||||
echo "Removed ~/.zprofile after migration"
|
||||
fi
|
||||
rm -f "$zprofile_extract"
|
||||
elif is_easyzsh_zprofile_stub "$ZPROFILE"; then
|
||||
rm -f "$ZPROFILE"
|
||||
fi
|
||||
# ~/.zprofile re-applies ~/.zshenv after macOS path_helper.
|
||||
# Replace comment-only stubs and the old pyenv-only hook. Keep other login
|
||||
# lines, or fold them into local.zsh when --migrate-zprofile is set.
|
||||
zprofile_extras_file=$(mktemp)
|
||||
: >"$zprofile_extras_file"
|
||||
if [[ -f "$ZPROFILE" ]] && ! is_easyzsh_zprofile_stub "$ZPROFILE" && ! is_pyenv_only_zprofile "$ZPROFILE"; then
|
||||
zprofile_extras "$ZPROFILE" | awk '
|
||||
/Created by `pipx`/ { skip_pipx=1; next }
|
||||
skip_pipx && /local\/bin/ { skip_pipx=0; next }
|
||||
skip_pipx { next }
|
||||
{ print }
|
||||
' >"$zprofile_extras_file"
|
||||
fi
|
||||
|
||||
# Always drop the comment-only easyzsh stub if present (even without --migrate).
|
||||
if is_easyzsh_zprofile_stub "$ZPROFILE"; then
|
||||
rm -f "$ZPROFILE"
|
||||
echo "Removed empty easyzsh ~/.zprofile stub"
|
||||
if [[ "$MIGRATE_ZPROFILE" -eq 1 ]] && file_has_content "$zprofile_extras_file"; then
|
||||
if [[ -f "$LOCAL_ZSH" ]]; then
|
||||
printf '\n' >>"$LOCAL_ZSH"
|
||||
cat "$zprofile_extras_file" >>"$LOCAL_ZSH"
|
||||
else
|
||||
cp "$zprofile_extras_file" "$LOCAL_ZSH"
|
||||
fi
|
||||
echo "Migrated extra ~/.zprofile lines -> ~/.config/zsh/local.zsh"
|
||||
: >"$zprofile_extras_file"
|
||||
fi
|
||||
|
||||
backup_file "${TARGET_HOME}/.zshenv"
|
||||
backup_file "${TARGET_HOME}/.zshrc"
|
||||
backup_file "$ZPROFILE"
|
||||
|
||||
install -m 644 "${ROOT}/.zshenv" "${TARGET_HOME}/.zshenv"
|
||||
install -m 644 "${ROOT}/.zshrc" "${TARGET_HOME}/.zshrc"
|
||||
if file_has_content "$zprofile_extras_file"; then
|
||||
{
|
||||
cat "${ROOT}/.zprofile"
|
||||
printf '\n'
|
||||
cat "$zprofile_extras_file"
|
||||
} >"$ZPROFILE"
|
||||
echo "Installed ~/.zprofile (kept extra login lines)"
|
||||
else
|
||||
install -m 644 "${ROOT}/.zprofile" "$ZPROFILE"
|
||||
echo "Installed ~/.zprofile"
|
||||
fi
|
||||
rm -f "$zprofile_extras_file"
|
||||
|
||||
# Remove obsolete managed-tree layout and examples from earlier deploys.
|
||||
/bin/rm -rf \
|
||||
|
||||
Reference in new issue
Block a user