Always-on and machine hooks already live in .zshenv / local.zsh. Drop the empty stub, remove it on deploy, and leave real .zprofile files to optional migration into local.zsh only.
157 lines
4.3 KiB
Bash
Executable File
157 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Install easyzsh shell stubs into a home directory.
|
|
# Overwrites: ~/.zshenv ~/.zshrc
|
|
# Never overwrites: ~/.config/zsh/local.zsh ~/.config/zshrc/** ~/.local/bin/**
|
|
# Does not manage ~/.zprofile (machine/login hooks belong in local.zsh).
|
|
#
|
|
# Usage:
|
|
# ./deploy.sh
|
|
# ./deploy.sh --home /path/to/home
|
|
# ./deploy.sh --migrate-zprofile # fold real ~/.zprofile into local.zsh, then remove stub
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
TARGET_HOME="${HOME}"
|
|
MIGRATE_ZPROFILE=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--home)
|
|
TARGET_HOME="$2"
|
|
shift 2
|
|
;;
|
|
--migrate-zprofile)
|
|
MIGRATE_ZPROFILE=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
sed -n '2,12p' "$0"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ ! -d "$TARGET_HOME" ]]; then
|
|
echo "Home does not exist: $TARGET_HOME" >&2
|
|
exit 1
|
|
fi
|
|
|
|
ZSH_CFG="${TARGET_HOME}/.config/zsh"
|
|
LOCAL_ZSH="${ZSH_CFG}/local.zsh"
|
|
ZPROFILE="${TARGET_HOME}/.zprofile"
|
|
ts=$(date +%Y%m%d-%H%M%S)
|
|
|
|
backup_file() {
|
|
local f="$1"
|
|
if [[ -e "$f" || -L "$f" ]]; then
|
|
cp -Pp "$f" "${f}.backup.${ts}"
|
|
echo "Backed up $f -> ${f}.backup.${ts}"
|
|
fi
|
|
}
|
|
|
|
file_has_content() {
|
|
[[ -f "$1" ]] && grep -q '[^[:space:]]' "$1"
|
|
}
|
|
|
|
is_easyzsh_zprofile_stub() {
|
|
local f="$1"
|
|
[[ -f "$f" ]] || return 1
|
|
# Comment-only placeholder from earlier easyzsh deploys.
|
|
if grep -Eqv '^[[:space:]]*(#|$)' "$f"; then
|
|
return 1
|
|
fi
|
|
grep -Eq 'easyzsh|PATH lives in|Leave this file empty|prefer.*local\.zsh' "$f"
|
|
}
|
|
|
|
echo "Deploying easyzsh shell stubs into $TARGET_HOME"
|
|
|
|
mkdir -p \
|
|
"${ZSH_CFG}" \
|
|
"${TARGET_HOME}/.config/zshrc" \
|
|
"${TARGET_HOME}/.cache/zsh" \
|
|
"${TARGET_HOME}/.local/bin"
|
|
|
|
# Migrate legacy fragments into local.zsh once.
|
|
if [[ ! -f "$LOCAL_ZSH" ]]; then
|
|
tmp=$(mktemp)
|
|
: >"$tmp"
|
|
if file_has_content "${TARGET_HOME}/.config/zshenv.local"; then
|
|
cat "${TARGET_HOME}/.config/zshenv.local" >>"$tmp"
|
|
printf '\n' >>"$tmp"
|
|
fi
|
|
if [[ -d "${ZSH_CFG}/local" ]]; then
|
|
for part in env.local.zsh login.local.zsh interactive.local.zsh; do
|
|
if file_has_content "${ZSH_CFG}/local/${part}"; then
|
|
cat "${ZSH_CFG}/local/${part}" >>"$tmp"
|
|
printf '\n' >>"$tmp"
|
|
fi
|
|
done
|
|
fi
|
|
if file_has_content "$tmp"; then
|
|
cp "$tmp" "$LOCAL_ZSH"
|
|
echo "Migrated machine-local fragments -> ~/.config/zsh/local.zsh"
|
|
fi
|
|
rm -f "$tmp"
|
|
fi
|
|
|
|
# Optional: fold a real (non-stub) ~/.zprofile into local.zsh.
|
|
if [[ "$MIGRATE_ZPROFILE" -eq 1 && -f "$ZPROFILE" ]]; then
|
|
if 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
|
|
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"
|
|
fi
|
|
|
|
backup_file "${TARGET_HOME}/.zshenv"
|
|
backup_file "${TARGET_HOME}/.zshrc"
|
|
|
|
install -m 644 "${ROOT}/.zshenv" "${TARGET_HOME}/.zshenv"
|
|
install -m 644 "${ROOT}/.zshrc" "${TARGET_HOME}/.zshrc"
|
|
|
|
# Remove obsolete managed-tree layout and examples from earlier deploys.
|
|
/bin/rm -rf \
|
|
"${ZSH_CFG}/env" \
|
|
"${ZSH_CFG}/interactive" \
|
|
"${ZSH_CFG}/login" \
|
|
"${ZSH_CFG}/local"
|
|
/bin/rm -f \
|
|
"${ZSH_CFG}/local.zsh.example" \
|
|
"${TARGET_HOME}/.config/zshenv.local"
|
|
|
|
# Ensure intentional grok shim when the binary tree exists.
|
|
if [[ -e "${TARGET_HOME}/.grok/bin/grok" ]]; then
|
|
ln -sfn "${TARGET_HOME}/.grok/bin/grok" "${TARGET_HOME}/.local/bin/grok"
|
|
echo "Ensured ~/.local/bin/grok -> ~/.grok/bin/grok"
|
|
fi
|
|
|
|
echo "Deploy complete."
|
|
echo "Verify: env -i HOME=\"$TARGET_HOME\" PATH=/usr/bin:/bin zsh -c '. ~/.zshenv; command -v grok'"
|