119 lines
4.5 KiB
Bash
Executable File
119 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# 30-shell-zsh — zsh + oh-my-zsh + plugins, set as default shell, drop our config.
|
|
|
|
step_name="shell-zsh"
|
|
step_desc="zsh + oh-my-zsh + plugins, set default shell, ship config"
|
|
step_run="run_zsh"
|
|
|
|
# All paths resolve against the config TARGET (set by 05-create-user).
|
|
# NOTE: we deliberately do NOT honor an inherited $ZSH env var — oh-my-zsh exports
|
|
# ZSH when it loads, so a setup.sh run from an omz-equipped shell would otherwise
|
|
# pin these to the *old* home (e.g. /root) while the chown step retargets to the
|
|
# *new* user, mis-owning the wrong tree (the 'insecure completion dirs' bug).
|
|
ZSH="$TARGET_HOME/.oh-my-zsh"
|
|
ZSH_CUSTOM="$ZSH/custom"
|
|
ZDOTDIR_TARGET="$TARGET_HOME/.config/zsh"
|
|
|
|
run_zsh() {
|
|
log "installing zsh + oh-my-zsh"
|
|
_install_zsh
|
|
_install_omz
|
|
_install_plugins
|
|
_chown_target_tree
|
|
_ship_config
|
|
_set_default_shell
|
|
if [[ "$TARGET_USER" != "$USER" ]]; then
|
|
log "zsh ready. Start it as $TARGET_USER: sudo -iu $TARGET_USER"
|
|
else
|
|
ok "zsh ready — start it with: exec zsh"
|
|
fi
|
|
}
|
|
|
|
_chown_target_tree() {
|
|
# when running as root for a created user, make omz + plugins + config owned by them
|
|
if [[ "$TARGET_USER" == "$USER" ]]; then return; fi
|
|
local grp; grp="$(id -gn "$TARGET_USER" 2>/dev/null || echo "$TARGET_USER")"
|
|
chown -R "$TARGET_USER:$grp" "$ZSH" "$ZDOTDIR_TARGET" "$TARGET_HOME/.zshrc" 2>/dev/null || true
|
|
}
|
|
|
|
_install_zsh() {
|
|
if command -v zsh >/dev/null 2>&1; then ok "zsh already installed"; return; fi
|
|
case "$DISTRO" in
|
|
arch) sudo_ pacman -Sy --noconfirm --needed zsh ;;
|
|
debian) sudo_ apt-get install -y zsh ;;
|
|
esac
|
|
}
|
|
|
|
_install_omz() {
|
|
if [[ -d "$ZSH/.git" ]]; then ok "oh-my-zsh already present"; return; fi
|
|
# clone directly (skip the upstream installer so we keep .zshrc under our control)
|
|
rm -rf "$ZSH"
|
|
git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$ZSH"
|
|
ok "oh-my-zsh cloned to $ZSH"
|
|
}
|
|
|
|
_install_plugins() {
|
|
mkdir -p "$ZSH_CUSTOM/plugins"
|
|
_clone_plugin zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
|
|
_clone_plugin zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
|
|
_clone_plugin zsh-users/zsh-completions "$ZSH_CUSTOM/plugins/zsh-completions"
|
|
_clone_plugin zsh-users/zsh-history-substring-search "$ZSH_CUSTOM/plugins/history-substring-search"
|
|
_clone_plugin Aloxaf/fzf-tab "$ZSH_CUSTOM/plugins/fzf-tab"
|
|
}
|
|
|
|
_clone_plugin() { # repo dest
|
|
local repo="$1" dest="$2"
|
|
if [[ -d "$dest/.git" ]]; then return; fi
|
|
git clone --depth=1 "https://github.com/$repo.git" "$dest" \
|
|
|| warn "failed to clone $repo"
|
|
}
|
|
|
|
_ship_config() {
|
|
log "shipping zsh config to $ZDOTDIR_TARGET"
|
|
mkdir -p "$ZDOTDIR_TARGET"
|
|
local f
|
|
for f in zshrc aliases.zsh functions.zsh path.zsh plugins.zsh; do
|
|
local src="$BOOT_DIR/config/zsh/$f"
|
|
[[ -f "$src" ]] || continue
|
|
local dst="$ZDOTDIR_TARGET/$f"
|
|
[[ -f "$dst" ]] && cp "$dst" "${dst}.bak.$(date +%Y%m%d-%H%M%S)"
|
|
cp "$src" "$dst"
|
|
done
|
|
# aliases-extras.zsh is user-owned: only seed it if absent
|
|
if [[ ! -f "$ZDOTDIR_TARGET/aliases-extras.zsh" ]]; then
|
|
cp "$BOOT_DIR/config/zsh/aliases-extras.zsh" "$ZDOTDIR_TARGET/aliases-extras.zsh"
|
|
fi
|
|
# ~/.zshrc shim that loads our real config via ZDOTDIR
|
|
local shim="$TARGET_HOME/.zshrc"
|
|
if ! grep -q 'BOOTSTRAP ZDOTDIR' "$shim" 2>/dev/null; then
|
|
cat >> "$shim" <<'EOF'
|
|
|
|
# BOOTSTRAP ZDOTDIR — real config lives in ~/.config/zsh
|
|
export ZDOTDIR="${ZDOTDIR:-$HOME/.config/zsh}"
|
|
[[ -f "$ZDOTDIR/zshrc" ]] && source "$ZDOTDIR/zshrc"
|
|
EOF
|
|
fi
|
|
# ensure the whole shipped tree is owned by the target user
|
|
if [[ "$TARGET_USER" != "$USER" ]]; then
|
|
chown -R "$TARGET_USER:$(id -gn "$TARGET_USER" 2>/dev/null || echo "$TARGET_USER")" "$ZDOTDIR_TARGET" "$shim"
|
|
fi
|
|
ok "zsh config installed ($ZDOTDIR_TARGET) + $shim shim"
|
|
}
|
|
|
|
_set_default_shell() {
|
|
local zsh_bin; zsh_bin="$(command -v zsh || true)"
|
|
[[ -z "$zsh_bin" ]] && { warn "zsh not on PATH — skipping chsh"; return; }
|
|
# ensure listed in /etc/shells
|
|
if ! grep -qx "$zsh_bin" /etc/shells 2>/dev/null; then
|
|
echo "$zsh_bin" | sudo_ tee -a /etc/shells >/dev/null
|
|
fi
|
|
if [[ "$(getent passwd "$TARGET_USER" | cut -d: -f7)" != "$zsh_bin" ]]; then
|
|
if yn "Set zsh as default login shell for $TARGET_USER?" y; then
|
|
sudo_ chsh -s "$zsh_bin" "$TARGET_USER" && ok "default shell set to zsh for $TARGET_USER"
|
|
else
|
|
warn "zsh not set as default — run 'chsh -s $zsh_bin' for $TARGET_USER' later"
|
|
fi
|
|
else
|
|
ok "zsh already the default shell for $TARGET_USER"
|
|
fi
|
|
} |