feat: separate updates and manage shell config blocks

This commit is contained in:
叶林立
2026-08-19 00:13:39 +08:00
parent 68490db454
commit 04ad87b54d
6 changed files with 497 additions and 87 deletions
Executable
+264
View File
@@ -0,0 +1,264 @@
#!/bin/sh
set -u
SCRIPT_DIR=$(CDPATH=; cd "$(dirname "$0")" && pwd) || exit 1
MANAGED_CONFIG_HELPERS=$SCRIPT_DIR/scripts/managed-config.sh
if [ ! -f "$MANAGED_CONFIG_HELPERS" ]; then
printf '错误: 找不到受管配置辅助脚本:%s\n' "$MANAGED_CONFIG_HELPERS" >&2
exit 1
fi
# shellcheck source=scripts/managed-config.sh
. "$MANAGED_CONFIG_HELPERS"
PACKAGE_SOURCE=${PI_PACKAGE_SOURCE:-git:git@bitbucket.org:siakitem/my-pi.git}
POWERLEVEL10K_PRESET_FILE=$SCRIPT_DIR/config/p10k.zsh
CODEGRAPH_INSTALL_URL=https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh
KITTY_INSTALL_URL=https://sw.kovidgoyal.net/kitty/installer.sh
update_failed=0
say() {
printf '%s\n' "$*"
}
warn() {
printf '警告: %s\n' "$*" >&2
}
record_update_failure() {
warn "$1 升级或配置同步失败;其余已安装组件仍会继续处理。"
update_failed=1
}
select_updated_bundle_config() {
updated_bundle_dir=
case $PACKAGE_SOURCE in
/*)
updated_bundle_dir=$PACKAGE_SOURCE
;;
./*|../*)
updated_bundle_dir=$(CDPATH=; cd "$PACKAGE_SOURCE" 2>/dev/null && pwd) || updated_bundle_dir=
;;
git:git@bitbucket.org:siakitem/my-pi.git)
updated_bundle_dir=${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}/git/bitbucket.org/siakitem/my-pi
;;
esac
if [ -n "$updated_bundle_dir" ] && [ -f "$updated_bundle_dir/config/p10k.zsh" ]; then
POWERLEVEL10K_PRESET_FILE=$updated_bundle_dir/config/p10k.zsh
elif [ ! -f "$POWERLEVEL10K_PRESET_FILE" ]; then
warn "无法定位升级后的组合包配置,找不到 $POWERLEVEL10K_PRESET_FILE"
return 1
else
warn "无法从当前 PI_PACKAGE_SOURCE 推导升级后的包目录,将使用脚本目录中的配置。"
fi
}
resolve_zsh_paths() {
oh_my_zsh_dir=${ZSH:-$HOME/.oh-my-zsh}
zsh_custom_dir=${ZSH_CUSTOM:-$oh_my_zsh_dir/custom}
zshrc_file=${ZDOTDIR:-$HOME}/.zshrc
my_pi_config_dir=${XDG_CONFIG_HOME:-$HOME/.config}/my-pi
p10k_managed_config_file=$my_pi_config_dir/p10k.zsh
}
replace_zsh_managed_block() {
managed_id=$1
managed_placement=$2
managed_anchor=$3
shift 3
managed_content=$(mktemp "${TMPDIR:-/tmp}/my-pi-zsh-block.XXXXXX") || return 1
printf '%s\n' "$@" > "$managed_content"
my_pi_replace_managed_block "$zshrc_file" "$managed_id" "$managed_content" \
"$managed_placement" "$managed_anchor"
managed_status=$?
rm -f "$managed_content"
return "$managed_status"
}
update_git_checkout() {
component=$1
checkout=$2
if [ ! -d "$checkout/.git" ]; then
warn "$component 已安装,但不是脚本可安全升级的 Git checkout,已跳过版本升级。"
return 0
fi
if ! command -v git >/dev/null 2>&1; then
warn "升级 $component 需要 git。"
return 1
fi
git -C "$checkout" pull --ff-only
}
update_brew_formula_if_installed() {
formula=$1
description=$2
command_name=$3
if command -v brew >/dev/null 2>&1 && brew list --formula "$formula" >/dev/null 2>&1; then
say "正在升级 $description"
brew upgrade "$formula" || record_update_failure "$description"
elif command -v "$command_name" >/dev/null 2>&1; then
say "- $description 已安装,但不由 Homebrew 管理,已保留现有安装。"
else
say "- $description 未安装,升级流程跳过。"
fi
}
detect_kitty() {
kitty_bin=
if command -v kitty >/dev/null 2>&1; then
kitty_bin=$(command -v kitty)
return 0
fi
case $(uname -s) in
Darwin) kitty_candidates="/Applications/kitty.app/Contents/MacOS/kitty" ;;
*) kitty_candidates="$HOME/.local/kitty.app/bin/kitty" ;;
esac
for candidate in $kitty_candidates; do
if [ -x "$candidate" ]; then
kitty_bin=$candidate
return 0
fi
done
return 1
}
resolve_kitty_config_dir() {
kitty_config_dir=${KITTY_CONFIG_DIRECTORY:-${XDG_CONFIG_HOME:-$HOME/.config}/kitty}
}
kitty_uses_solarized_dark() {
resolve_kitty_config_dir
[ -f "$kitty_config_dir/current-theme.conf" ] &&
grep -F "Solarized Dark" "$kitty_config_dir/current-theme.conf" >/dev/null 2>&1
}
update_kitty() {
if ! detect_kitty; then
say "- Kitty 未安装,升级流程跳过。"
return 0
fi
if command -v brew >/dev/null 2>&1 && brew list --cask kitty >/dev/null 2>&1; then
brew upgrade --cask kitty || record_update_failure "Kitty"
elif [ "$kitty_bin" = "$HOME/.local/kitty.app/bin/kitty" ] || \
[ "$kitty_bin" = "/Applications/kitty.app/Contents/MacOS/kitty" ]; then
if ! command -v curl >/dev/null 2>&1; then
record_update_failure "Kitty(官方安装需要 curl"
else
installer_file=$(mktemp "${TMPDIR:-/tmp}/my-pi-kitty.XXXXXX") || return 1
if ! curl -fsSL "$KITTY_INSTALL_URL" -o "$installer_file" || \
! sh "$installer_file" launch=n; then
record_update_failure "Kitty"
fi
rm -f "$installer_file"
fi
else
say "- Kitty 已安装,但不由 Homebrew 或官方 ~/.local 安装管理,已保留现有安装。"
fi
if kitty_uses_solarized_dark; then
"$kitty_bin" +kitten themes --reload-in=none "Solarized Dark" || \
record_update_failure "Kitty Solarized Dark 主题"
fi
}
update_codegraph() {
if ! command -v codegraph >/dev/null 2>&1; then
say "- CodeGraph 未安装,升级流程跳过。"
return 0
fi
if ! command -v curl >/dev/null 2>&1; then
warn "升级 CodeGraph 需要 curl。"
return 1
fi
installer_file=$(mktemp "${TMPDIR:-/tmp}/my-pi-codegraph.XXXXXX") || return 1
if ! curl -fsSL "$CODEGRAPH_INSTALL_URL" -o "$installer_file" || ! sh "$installer_file"; then
rm -f "$installer_file"
return 1
fi
rm -f "$installer_file"
}
update_zsh_environment() {
resolve_zsh_paths
if [ ! -f "$oh_my_zsh_dir/oh-my-zsh.sh" ]; then
say "- Oh My Zsh 未安装,Powerlevel10k 和 Zsh 插件升级均跳过。"
return 0
fi
if [ -f "$oh_my_zsh_dir/tools/upgrade.sh" ] && command -v zsh >/dev/null 2>&1; then
ZSH="$oh_my_zsh_dir" zsh "$oh_my_zsh_dir/tools/upgrade.sh" || record_update_failure "Oh My Zsh"
else
update_git_checkout "Oh My Zsh" "$oh_my_zsh_dir" || record_update_failure "Oh My Zsh"
fi
powerlevel10k_dir=$zsh_custom_dir/themes/powerlevel10k
if [ -f "$powerlevel10k_dir/powerlevel10k.zsh-theme" ]; then
update_git_checkout "Powerlevel10k" "$powerlevel10k_dir" || record_update_failure "Powerlevel10k"
else
say "- Powerlevel10k 未安装,升级流程跳过。"
fi
for plugin in zsh-autosuggestions zsh-syntax-highlighting; do
plugin_dir=$zsh_custom_dir/plugins/$plugin
if [ -d "$plugin_dir" ]; then
update_git_checkout "$plugin" "$plugin_dir" || record_update_failure "$plugin"
else
say "- $plugin 未安装,升级流程跳过。"
fi
done
[ -f "$zshrc_file" ] || return 0
if my_pi_managed_block_exists "$zshrc_file" "oh-my-zsh-loader"; then
replace_zsh_managed_block "oh-my-zsh-loader" "append" "" \
"export ZSH=\"$oh_my_zsh_dir\"" \
"source \"\$ZSH/oh-my-zsh.sh\"" || record_update_failure ".zshrc Oh My Zsh 受管块"
fi
if my_pi_managed_block_exists "$zshrc_file" "powerlevel10k-theme"; then
replace_zsh_managed_block "powerlevel10k-theme" "before" \
'^(# >>> my-pi:oh-my-zsh-loader >>>|[[:space:]]*(source|\.)[[:space:]].*oh-my-zsh\.sh)' \
'ZSH_THEME="powerlevel10k/powerlevel10k"' || record_update_failure ".zshrc Powerlevel10k 主题受管块"
fi
for plugin in git zsh-autosuggestions zsh-syntax-highlighting; do
if my_pi_managed_block_exists "$zshrc_file" "zsh-plugin-$plugin"; then
replace_zsh_managed_block "zsh-plugin-$plugin" "before" \
'^(# >>> my-pi:oh-my-zsh-loader >>>|[[:space:]]*(source|\.)[[:space:]].*oh-my-zsh\.sh)' \
"plugins+=($plugin)" || record_update_failure ".zshrc $plugin 受管块"
fi
done
if [ -f "$p10k_managed_config_file" ] || \
my_pi_managed_block_exists "$zshrc_file" "powerlevel10k-config"; then
if my_pi_sync_managed_file "$POWERLEVEL10K_PRESET_FILE" "$p10k_managed_config_file"; then
replace_zsh_managed_block "powerlevel10k-config" "append" "" \
"[[ ! -f \"$p10k_managed_config_file\" ]] || source \"$p10k_managed_config_file\"" || \
record_update_failure ".zshrc Powerlevel10k 配置受管块"
else
record_update_failure "Powerlevel10k 受管配置"
fi
fi
}
if ! command -v pi >/dev/null 2>&1; then
warn "找不到 pi,无法升级组合包。请确保 pi 位于 PATH。"
exit 127
fi
say "正在升级 Pi 组合包:$PACKAGE_SOURCE"
if ! pi update "$PACKAGE_SOURCE"; then
warn "pi update 执行失败,已停止后续升级。"
exit 1
fi
select_updated_bundle_config || exit 1
say "组合包升级完成,开始升级已安装的终端环境和机器级 CLI;未安装项将直接跳过。"
update_kitty || record_update_failure "Kitty"
update_zsh_environment || record_update_failure "Zsh 环境"
update_codegraph || record_update_failure "CodeGraph"
update_brew_formula_if_installed "kotlin-lsp" "kotlin-lsp" "kotlin-lsp"
update_brew_formula_if_installed "openjdk@21" "Java 21" "java"
update_brew_formula_if_installed "jdtls" "jdtls" "jdtls"
say "已安装组件的升级与受管配置同步完成。"
exit "$update_failed"