From 1b797648580d0e9ccb2b6116a6f25e119ff845bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E6=9C=8D=E5=8A=A1=E9=83=A8-=E5=8F=B6=E6=9E=97?= =?UTF-8?q?=E7=AB=8B?= <1361666059@qq.com> Date: Wed, 19 Aug 2026 09:17:07 +0800 Subject: [PATCH] feat: skip unchanged dependency updates --- AGENTS.md | 4 +- README.md | 9 ++++- update.sh | 110 +++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 106 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d7fa5e8..55cfd16 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ - `@ogulcancelik/pi-codex-compaction@0.1.3`:为 `openai-codex` 提供原生远程 compaction,默认阈值为 90%。 - 根包还固定安装 `pi-context-view`、`@firstpick/pi-extension-codex-fast-mode` 和 `@gotgenes/pi-permission-system`。 - `install.sh`:先安装根组合包,再交互检查 Kitty/Solarized Dark、Oh My Zsh/Powerlevel10k/Zsh 插件、CodeGraph、Kotlin LSP、Java 21+ 和 JDT LS;缺失项目只在用户明确选择 `Y` 后安装或配置。Powerlevel10k 默认配置来自仓库内置的 `config/p10k.zsh`(当前 Rainbow/ASCII 单行紧凑主题)。 -- `update.sh`:先通过 `pi update` 升级根组合包,再只升级当前已安装的终端环境和机器级依赖;未安装项直接跳过。Powerlevel10k 配置优先从 `pi update` 后的已安装组合包读取,并与 `.zshrc` 受管块一起按内容比较后增量同步。 +- `update.sh`:先通过 `pi update` 升级根组合包,再只升级当前已安装的终端环境和机器级依赖;未安装项直接跳过。升级前先查询并比较本地与远端版本,只有版本不同时才下载或替换;Powerlevel10k 配置优先从 `pi update` 后的已安装组合包读取,并与 `.zshrc` 受管块一起按内容比较后增量同步。 - `uninstall.sh`:只移除根组合包,不卸载或还原可能被其他项目共享的终端环境、CodeGraph、Kotlin LSP、JDT LS 或 Java。 ## 当前职责与默认行为 @@ -49,7 +49,7 @@ - 终端环境配置只属于便捷脚本:Kitty 可选安装后可通过官方 kitten 启用 Solarized Dark;Oh My Zsh 使用不切换 shell 的 unattended 安装;Powerlevel10k 将仓库内置的 `config/p10k.zsh`(Rainbow/ASCII 单行紧凑主题)部署到 `~/.config/my-pi/p10k.zsh`(遵循 `XDG_CONFIG_HOME`),不得覆盖用户自己的 `~/.p10k.zsh`。`.zshrc` 中脚本拥有的内容必须使用 `# >>> my-pi: >>>` / `# <<< my-pi: <<<` 受管块,更新时只替换块内内容;标记不完整或重复时拒绝修改。实际修改前必须创建带时间戳的备份。`git`、`zsh-autosuggestions`、`zsh-syntax-highlighting` 在安装流程中逐项询问后才安装或启用。 - Codex 远程压缩只对 `openai-codex` 生效,默认在 turn boundary 达到 90% 时触发;Hermes Memory 默认使用 policy-only 模式。 - `install.sh` 默认从 `git:git@bitbucket.org:siakitem/my-pi.git` 安装,并允许用 `PI_PACKAGE_SOURCE` 覆盖来源;组合包安装失败时立即停止,机器级依赖安装失败时继续检查其余依赖并最终返回非零状态。 -- CodeGraph 的可选安装使用官方远程安装脚本;macOS Kitty 使用 Homebrew cask,其他系统使用 Kitty 官方安装器;Kotlin LSP、Java 21 和 JDT LS 使用 Homebrew;Oh My Zsh 使用官方安装器,Powerlevel10k 与两个第三方 Zsh 插件从各自官方 Git 仓库克隆。缺少 Homebrew、curl 或 git 时保留已经完成的组合包安装并报告失败。 +- CodeGraph 的可选安装使用官方远程安装脚本;macOS Kitty 使用 Homebrew cask,其他系统使用 Kitty 官方安装器;Kotlin LSP、Java 21 和 JDT LS 使用 Homebrew;Oh My Zsh 使用官方安装器,Powerlevel10k 与两个第三方 Zsh 插件从各自官方 Git 仓库克隆。升级时 Git checkout、Homebrew 包、Kitty 官方安装和 CodeGraph 都必须先比较本地与远端版本,版本一致时不得重新下载安装;无法可靠比较时保留现状并报告。缺少 Homebrew、curl 或 git 时保留已经完成的组合包安装并报告失败。 - `install.sh` 不检查默认不需要的 `rtk` CLI;`update.sh` 和 `uninstall.sh` 使用同一个 `PI_PACKAGE_SOURCE` 规则分别调用 `pi update` 和 `pi remove`。运行 `update.sh` 视为明确授权升级已安装组件及同步已有受管配置,但不得安装缺失组件或改写受管块之外的用户配置;卸载仍不改动共享机器级工具。 ## 修改边界 diff --git a/README.md b/README.md index efb99a3..f2b7a41 100644 --- a/README.md +++ b/README.md @@ -69,8 +69,13 @@ pi update git:git@bitbucket.org:siakitem/my-pi.git 随后只处理已经安装的项目,未安装项直接跳过且不会询问安装:Kitty 及已启用的 Solarized Dark、Oh My Zsh、Powerlevel10k、两个第三方 Zsh 插件、CodeGraph,以及由 -Homebrew 管理的 Kotlin LSP、Java 21 和 JDT LS。Git checkout 使用 `pull --ff-only`, -Homebrew 包使用 `brew upgrade`;无法确认安装来源时保留现状并报告。 +Homebrew 管理的 Kotlin LSP、Java 21 和 JDT LS。升级前会先刷新或查询对应的远端版本: +Git checkout 在 `fetch` 后比较本地与上游提交,Homebrew 包在刷新元数据后通过 `brew outdated` +判断,Kitty 官方安装和 CodeGraph 则比较本地版本与官方最新发布版本。只有检测到版本不同时才 +下载并替换;无法确认安装来源或无法可靠比较版本时保留现状并报告。 + +日志中的“Zsh 插件未安装,升级流程跳过”不是升级失败:升级脚本不会新增用户此前未选择的 +插件。需要补装时重新运行 `./install.sh`,并在对应的逐项询问中明确选择 `Y`。 升级时会优先从 `pi update` 后的已安装组合包目录读取最新 `config/p10k.zsh`,再与受管副本比较, 只在内容不同时备份并原子同步;`.zshrc` 也只更新已有的 my-pi 受管块,不触碰块外配置。因此安装流程负责补齐缺失项,升级流程只升级 diff --git a/update.sh b/update.sh index 05fd2cb..d5ae7e9 100755 --- a/update.sh +++ b/update.sh @@ -14,8 +14,11 @@ fi 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 +CODEGRAPH_LATEST_RELEASE_URL=https://github.com/colbymchenry/codegraph/releases/latest KITTY_INSTALL_URL=https://sw.kovidgoyal.net/kitty/installer.sh +KITTY_VERSION_URL=https://sw.kovidgoyal.net/kitty/current-version.txt update_failed=0 +brew_metadata_refreshed=0 say() { printf '%s\n' "$*" @@ -47,7 +50,7 @@ select_updated_bundle_config() { 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。" + warn "无法定位升级后的组合包配置,找不到 ${POWERLEVEL10K_PRESET_FILE}。" return 1 else warn "无法从当前 PI_PACKAGE_SOURCE 推导升级后的包目录,将使用脚本目录中的配置。" @@ -87,7 +90,28 @@ update_git_checkout() { warn "升级 $component 需要 git。" return 1 fi - git -C "$checkout" pull --ff-only + upstream=$(git -C "$checkout" rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' 2>/dev/null) || { + warn "$component 的 Git checkout 没有可识别的上游分支,已跳过版本升级。" + return 1 + } + git -C "$checkout" fetch --quiet || return 1 + local_revision=$(git -C "$checkout" rev-parse HEAD) || return 1 + remote_revision=$(git -C "$checkout" rev-parse "$upstream") || return 1 + if [ "$local_revision" = "$remote_revision" ]; then + say "✓ $component 已是最新版本。" + return 0 + fi + say "发现 $component 有新版本,正在快进升级。" + git -C "$checkout" merge --ff-only "$upstream" +} + +refresh_brew_metadata() { + if [ "$brew_metadata_refreshed" -eq 1 ]; then + return 0 + fi + say "正在刷新 Homebrew 版本信息。" + brew update || return 1 + brew_metadata_refreshed=1 } update_brew_formula_if_installed() { @@ -95,8 +119,20 @@ update_brew_formula_if_installed() { 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" + refresh_brew_metadata || { + record_update_failure "$description" + return 0 + } + outdated_formula=$(brew outdated --formula --quiet "$formula") || { + record_update_failure "$description" + return 0 + } + if [ -z "$outdated_formula" ]; then + say "✓ $description 已是最新版本。" + else + say "发现 $description 有新版本,正在升级。" + brew upgrade "$formula" || record_update_failure "$description" + fi elif command -v "$command_name" >/dev/null 2>&1; then say "- $description 已安装,但不由 Homebrew 管理,已保留现有安装。" else @@ -140,18 +176,47 @@ update_kitty() { 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" + if refresh_brew_metadata; then + if outdated_kitty=$(brew outdated --cask --quiet kitty); then + if [ -z "$outdated_kitty" ]; then + say "✓ Kitty 已是最新版本。" + else + say "发现 Kitty 有新版本,正在升级。" + brew upgrade --cask kitty || record_update_failure "Kitty" + fi + else + record_update_failure "Kitty" + fi + else + record_update_failure "Kitty" + fi 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)" + 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" + kitty_version_output=$("$kitty_bin" --version 2>/dev/null) || kitty_version_output= + case $kitty_version_output in + kitty\ *) + installed_kitty_version=${kitty_version_output#kitty } + installed_kitty_version=${installed_kitty_version%% *} + ;; + *) installed_kitty_version= ;; + esac + latest_kitty_version=$(curl -fsSL "$KITTY_VERSION_URL") || latest_kitty_version= + if [ -z "$installed_kitty_version" ] || [ -z "$latest_kitty_version" ]; then + record_update_failure "Kitty 版本检查" + elif [ "$installed_kitty_version" = "$latest_kitty_version" ]; then + say "✓ Kitty $installed_kitty_version 已是最新版本。" + else + say "发现 Kitty ${latest_kitty_version}(当前 ${installed_kitty_version}),正在升级。" + 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 "installer=version-$latest_kitty_version"; then + record_update_failure "Kitty" + fi + rm -f "$installer_file" fi - rm -f "$installer_file" fi else say "- Kitty 已安装,但不由 Homebrew 或官方 ~/.local 安装管理,已保留现有安装。" @@ -169,11 +234,30 @@ update_codegraph() { return 0 fi if ! command -v curl >/dev/null 2>&1; then - warn "升级 CodeGraph 需要 curl。" + warn "检查 CodeGraph 版本需要 curl。" return 1 fi + installed_codegraph_version=$(codegraph --version 2>/dev/null) || installed_codegraph_version= + latest_release_url=$(curl -fsSLI -o /dev/null -w '%{url_effective}' \ + "$CODEGRAPH_LATEST_RELEASE_URL") || latest_release_url= + case $latest_release_url in + */releases/tag/*) latest_codegraph_tag=${latest_release_url##*/} ;; + *) latest_codegraph_tag= ;; + esac + latest_codegraph_version=${latest_codegraph_tag#v} + installed_codegraph_version=${installed_codegraph_version#v} + if [ -z "$installed_codegraph_version" ] || [ -z "$latest_codegraph_version" ]; then + warn "无法比较 CodeGraph 的本地版本与最新发布版本,已跳过替换。" + return 1 + fi + if [ "$installed_codegraph_version" = "$latest_codegraph_version" ]; then + say "✓ CodeGraph $installed_codegraph_version 已是最新版本。" + return 0 + fi + say "发现 CodeGraph ${latest_codegraph_version}(当前 ${installed_codegraph_version}),正在升级。" installer_file=$(mktemp "${TMPDIR:-/tmp}/my-pi-codegraph.XXXXXX") || return 1 - if ! curl -fsSL "$CODEGRAPH_INSTALL_URL" -o "$installer_file" || ! sh "$installer_file"; then + if ! curl -fsSL "$CODEGRAPH_INSTALL_URL" -o "$installer_file" || \ + ! CODEGRAPH_VERSION="$latest_codegraph_tag" sh "$installer_file"; then rm -f "$installer_file" return 1 fi