fix(homebrew): 优化终端输出处理逻辑

- 交互式终端中保留 Homebrew 原生配色和实时进度显示
- 非交互式输出时继续使用语义着色处理
- 在 macOS 上使用 script 命令为 brew 分配伪终端以保留完整输出
- 添加对管道状态的更精确错误处理
- 更新文档说明终端输出行为的变化
```
This commit is contained in:
2026-07-21 08:52:30 +08:00
parent 79efba3caa
commit 3c677eddcf
2 changed files with 28 additions and 11 deletions
+1
View File
@@ -325,6 +325,7 @@ brew upgrade --cask --greedy visual-studio-code
## 注意事项 ## 注意事项
- 脚本启用了 `set -euo pipefail`,但 Formula/Cask 升级阶段会捕获错误、继续隔离其他失败项,并在最后统一返回状态。 - 脚本启用了 `set -euo pipefail`,但 Formula/Cask 升级阶段会捕获错误、继续隔离其他失败项,并在最后统一返回状态。
- 交互式终端中直接保留 Homebrew 的 TTY 输出,因此 Formula/Cask 下载会显示原生实时进度;输出被重定向或用于 CI 时会自动回退到按行输出。
- `brew upgrade --cask --greedy` 可能退出正在运行的 GUI 应用,建议先保存重要工作。 - `brew upgrade --cask --greedy` 可能退出正在运行的 GUI 应用,建议先保存重要工作。
- 不建议日常启用 `HB_CASK_FORCE=1`;它会允许 Homebrew 覆盖已有 Cask 文件。 - 不建议日常启用 `HB_CASK_FORCE=1`;它会允许 Homebrew 覆盖已有 Cask 文件。
- 远程启动器属于“下载后执行”模式,只应从可信仓库使用。 - 远程启动器属于“下载后执行”模式,只应从可信仓库使用。
+17 -1
View File
@@ -573,7 +573,14 @@ colorize_brew_output() {
run_brew_colored() { run_brew_colored() {
local pipeline_status=() local pipeline_status=()
# 管道输出时禁用 Homebrew 自带的不完整配色,再统一按语义着色 # Homebrew 只有在 stdout 连接 TTY 时才会让 curl 显示动态下载进度
# 交互式终端中保留原始文件描述符,并使用 Homebrew 原生配色。
if [[ -t 1 ]]; then
brew "$@"
return $?
fi
# 非交互式输出无法显示动态进度,继续按行进行语义着色。
if env -u HOMEBREW_COLOR brew "$@" 2>&1 | colorize_brew_output; then if env -u HOMEBREW_COLOR brew "$@" 2>&1 | colorize_brew_output; then
return 0 return 0
fi fi
@@ -697,6 +704,14 @@ run_brew_with_retries() {
fi fi
: > "$ACTIVE_LOG_FILE" : > "$ACTIVE_LOG_FILE"
if [[ -t 0 && -t 1 && -t 2 && "$(uname -s 2>/dev/null || true)" == "Darwin" && -x /usr/bin/script ]]; then
# BSD script 为 brew 分配伪终端:既保留实时进度,又记录完整输出供错误分类。
if /usr/bin/script -q -e "$ACTIVE_LOG_FILE" brew "$@"; then
status=0
else
status=$?
fi
else
if env -u HOMEBREW_COLOR brew "$@" 2>&1 | tee "$ACTIVE_LOG_FILE" | colorize_brew_output; then if env -u HOMEBREW_COLOR brew "$@" 2>&1 | tee "$ACTIVE_LOG_FILE" | colorize_brew_output; then
status=0 status=0
else else
@@ -710,6 +725,7 @@ run_brew_with_retries() {
status="${pipeline_status[2]}" status="${pipeline_status[2]}"
fi fi
fi fi
fi
if ((status == 0)); then if ((status == 0)); then
rm -f "$ACTIVE_LOG_FILE" rm -f "$ACTIVE_LOG_FILE"