feat(homebrew): 添加彩色列表打印和改进升级管理功能
- 新增 print_colored_list 函数用于彩色化列表输出 - 在 brew 命令中禁用 HOMEBREW_COLOR 环境变量 - 添加 run_brew_doctor 函数处理 brew doctor 输出并着色 - 添加初始公式和应用更新前的状态检查与显示 - 改进缓存清理功能,区分下载文件和内部文件 - 更新清理结果显示,仅显示下载文件并统计隐藏文件数量 - 使用 run_brew_doctor 替代原始 brew doctor 调用 - 优化升级流程中的状态提示信息显示
This commit is contained in:
@@ -129,6 +129,16 @@ print_info() {
|
||||
printf '%b%s%b\n' "$CYAN" "$*" "$NC"
|
||||
}
|
||||
|
||||
print_colored_list() {
|
||||
local label="$1" color="$2" items="$3" item
|
||||
|
||||
printf '%b%s%b\n' "$color" "$label" "$NC"
|
||||
while IFS= read -r item; do
|
||||
[[ -n "$item" ]] || continue
|
||||
printf ' %b%s%b\n' "$color" "$item" "$NC"
|
||||
done <<< "$items"
|
||||
}
|
||||
|
||||
is_enabled() {
|
||||
case "${1:-}" in
|
||||
1|true|TRUE|yes|YES|on|ON) return 0 ;;
|
||||
@@ -279,19 +289,58 @@ run_brew_with_retries() {
|
||||
}
|
||||
|
||||
get_outdated_formulae() {
|
||||
brew outdated --formula 2>/dev/null
|
||||
env -u HOMEBREW_COLOR brew outdated --formula 2>/dev/null
|
||||
}
|
||||
|
||||
get_outdated_casks() {
|
||||
brew outdated --cask --greedy 2>/dev/null
|
||||
env -u HOMEBREW_COLOR brew outdated --cask --greedy 2>/dev/null
|
||||
}
|
||||
|
||||
run_brew_doctor() {
|
||||
local output status=0 line
|
||||
|
||||
if output="$(env -u HOMEBREW_COLOR brew doctor 2>&1)"; then
|
||||
status=0
|
||||
else
|
||||
status=$?
|
||||
fi
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
Warning:*|*deprecated*|*disabled*|*pre-release*|*"find replacements"*|*"do not provide support"*|*"Tier 2 configuration"*)
|
||||
printf '%b%s%b\n' "$YELLOW" "$line" "$NC"
|
||||
;;
|
||||
' '*|' https://'*)
|
||||
printf '%b%s%b\n' "$CYAN" "$line" "$NC"
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "$line"
|
||||
;;
|
||||
esac
|
||||
done <<< "$output"
|
||||
return "$status"
|
||||
}
|
||||
|
||||
run_formula_upgrade() {
|
||||
local bulk_status=0 outdated_formulae remaining_formulae formula
|
||||
local bulk_status=0 initial_formulae="" initial_formulae_known=1
|
||||
local outdated_formulae remaining_formulae formula
|
||||
local failed_formulae=()
|
||||
|
||||
if ! initial_formulae="$(get_outdated_formulae)"; then
|
||||
initial_formulae_known=0
|
||||
print_warning "unable to list Formulae requiring updates before upgrade."
|
||||
elif [[ -n "$initial_formulae" ]]; then
|
||||
print_colored_list "Formulae requiring updates:" "$YELLOW" "$initial_formulae"
|
||||
else
|
||||
print_success "No Formulae require updates."
|
||||
fi
|
||||
|
||||
brew upgrade --formula || bulk_status=$?
|
||||
if ((bulk_status == 0)); then
|
||||
if ((initial_formulae_known)) && [[ -n "$initial_formulae" ]]; then
|
||||
print_colored_list "Updated Formulae:" "$GREEN" "$initial_formulae"
|
||||
else
|
||||
print_success "Formula upgrade completed."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -301,11 +350,14 @@ run_formula_upgrade() {
|
||||
return "$bulk_status"
|
||||
fi
|
||||
if [[ -z "$outdated_formulae" ]]; then
|
||||
print_notice "No outdated Formulae remain; treating the bulk error as recovered."
|
||||
if [[ -n "$initial_formulae" ]]; then
|
||||
print_colored_list "Updated Formulae:" "$GREEN" "$initial_formulae"
|
||||
else
|
||||
print_success "No outdated Formulae remain; the bulk error was recovered."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "$outdated_formulae"
|
||||
while IFS= read -r formula; do
|
||||
[[ -n "$formula" ]] || continue
|
||||
print_info "Retrying Formula: ${formula}"
|
||||
@@ -322,20 +374,24 @@ run_formula_upgrade() {
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "$remaining_formulae" ]]; then
|
||||
print_success "All outdated Formulae were upgraded after isolated retries."
|
||||
if [[ -n "$initial_formulae" ]]; then
|
||||
print_colored_list "Updated Formulae after isolated retries:" "$GREEN" "$initial_formulae"
|
||||
else
|
||||
print_success "All outdated Formulae were upgraded after isolated retries."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r formula; do
|
||||
[[ -n "$formula" ]] && FAILED_FORMULAE+=("$formula")
|
||||
done <<< "$remaining_formulae"
|
||||
print_warning "Formulae still outdated after retries:"
|
||||
printf '%s\n' "$remaining_formulae"
|
||||
print_colored_list "Outdated Formulae remaining after retries:" "$RED" "$remaining_formulae"
|
||||
return 1
|
||||
}
|
||||
|
||||
run_cask_upgrade() {
|
||||
local bulk_status=0 outdated_casks remaining_casks cask
|
||||
local bulk_status=0 initial_casks="" initial_casks_known=1
|
||||
local outdated_casks remaining_casks cask
|
||||
local bulk_args=(upgrade --cask --greedy)
|
||||
local failed_casks=()
|
||||
|
||||
@@ -344,8 +400,22 @@ run_cask_upgrade() {
|
||||
print_warning "HB_CASK_FORCE is enabled; existing Cask files may be overwritten."
|
||||
fi
|
||||
|
||||
if ! initial_casks="$(get_outdated_casks)"; then
|
||||
initial_casks_known=0
|
||||
print_warning "unable to list Casks requiring updates before upgrade."
|
||||
elif [[ -n "$initial_casks" ]]; then
|
||||
print_colored_list "Casks requiring updates:" "$YELLOW" "$initial_casks"
|
||||
else
|
||||
print_success "No Casks require updates."
|
||||
fi
|
||||
|
||||
brew "${bulk_args[@]}" || bulk_status=$?
|
||||
if ((bulk_status == 0)); then
|
||||
if ((initial_casks_known)) && [[ -n "$initial_casks" ]]; then
|
||||
print_colored_list "Updated Casks:" "$GREEN" "$initial_casks"
|
||||
else
|
||||
print_success "Cask upgrade completed."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -355,11 +425,14 @@ run_cask_upgrade() {
|
||||
return "$bulk_status"
|
||||
fi
|
||||
if [[ -z "$outdated_casks" ]]; then
|
||||
print_notice "No outdated Casks remain; treating the bulk error as recovered."
|
||||
if [[ -n "$initial_casks" ]]; then
|
||||
print_colored_list "Updated Casks:" "$GREEN" "$initial_casks"
|
||||
else
|
||||
print_success "No outdated Casks remain; the bulk error was recovered."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s\n' "$outdated_casks"
|
||||
while IFS= read -r cask; do
|
||||
[[ -n "$cask" ]] || continue
|
||||
print_info "Retrying Cask: ${cask} (without --force)"
|
||||
@@ -376,15 +449,18 @@ run_cask_upgrade() {
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "$remaining_casks" ]]; then
|
||||
print_success "All outdated Casks were upgraded after isolated retries."
|
||||
if [[ -n "$initial_casks" ]]; then
|
||||
print_colored_list "Updated Casks after isolated retries:" "$GREEN" "$initial_casks"
|
||||
else
|
||||
print_success "All outdated Casks were upgraded after isolated retries."
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
while IFS= read -r cask; do
|
||||
[[ -n "$cask" ]] && FAILED_CASKS+=("$cask")
|
||||
done <<< "$remaining_casks"
|
||||
print_warning "Casks still outdated after retries:"
|
||||
printf '%s\n' "$remaining_casks"
|
||||
print_colored_list "Outdated Casks remaining after retries:" "$RED" "$remaining_casks"
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -405,9 +481,23 @@ format_bytes() {
|
||||
printf '%d.%d %s' "$((tenths / 10))" "$((tenths % 10))" "${units[unit]}"
|
||||
}
|
||||
|
||||
is_cache_download_artifact() {
|
||||
[[ "$1" == downloads/* ]]
|
||||
}
|
||||
|
||||
cache_artifact_display_name() {
|
||||
local name="${1#downloads/}"
|
||||
|
||||
# Homebrew 下载文件通常以 SHA-256-- 开头;终端只显示有意义的原文件名。
|
||||
[[ "$name" == *--* ]] && name="${name#*--}"
|
||||
printf '%s' "$name"
|
||||
}
|
||||
|
||||
prune_cache_before_today() {
|
||||
local cache_dir cutoff_stamp cutoff_date file file_size relative_path
|
||||
local cache_dir cutoff_stamp cutoff_date file file_size relative_path display_name hidden_count
|
||||
local removed_count=0 removed_bytes=0 kept_count=0 kept_bytes=0 cleanup_failed=0
|
||||
local removed_artifact_count=0 removed_artifact_bytes=0
|
||||
local kept_artifact_count=0 kept_artifact_bytes=0
|
||||
|
||||
cache_dir="$(brew --cache)"
|
||||
if [[ ! -d "$cache_dir" || "$cache_dir" == "/" || "$cache_dir" == "$HOME" ]]; then
|
||||
@@ -429,7 +519,7 @@ prune_cache_before_today() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%bRemoved cache files:%b\n' "$YELLOW" "$NC"
|
||||
printf '%bRemoved download artifacts:%b\n' "$YELLOW" "$NC"
|
||||
while IFS= read -r -d '' file; do
|
||||
if ! file_size="$(stat -f '%z' -- "$file" 2>/dev/null)"; then
|
||||
file_size=0
|
||||
@@ -438,18 +528,25 @@ prune_cache_before_today() {
|
||||
if rm -f -- "$file"; then
|
||||
removed_count=$((removed_count + 1))
|
||||
removed_bytes=$((removed_bytes + file_size))
|
||||
printf ' %b%10s%b %q\n' "$CYAN" "$(format_bytes "$file_size")" "$NC" "$relative_path"
|
||||
if is_cache_download_artifact "$relative_path"; then
|
||||
removed_artifact_count=$((removed_artifact_count + 1))
|
||||
removed_artifact_bytes=$((removed_artifact_bytes + file_size))
|
||||
display_name="$(cache_artifact_display_name "$relative_path")"
|
||||
printf ' %b%10s%b %q\n' "$CYAN" "$(format_bytes "$file_size")" "$NC" "$display_name"
|
||||
fi
|
||||
else
|
||||
print_warning "failed to remove cache file: $file" >&2
|
||||
cleanup_failed=1
|
||||
fi
|
||||
done < "$ACTIVE_CLEANUP_MANIFEST"
|
||||
if ((removed_count == 0)); then
|
||||
printf ' (none)\n'
|
||||
fi
|
||||
printf '%bRemoved%b %b%d%b Homebrew cache file(s) dated before %b%s%b (%b%s total%b).\n' \
|
||||
"$YELLOW" "$NC" "$CYAN" "$removed_count" "$NC" "$BLUE" "$cutoff_date" "$NC" \
|
||||
"$CYAN" "$(format_bytes "$removed_bytes")" "$NC"
|
||||
((removed_artifact_count > 0)) || printf ' (none)\n'
|
||||
hidden_count=$((removed_count - removed_artifact_count))
|
||||
printf '%bRemoved:%b %b%d files / %s%b before %b%s%b.\n' \
|
||||
"$YELLOW" "$NC" "$CYAN" "$removed_count" "$(format_bytes "$removed_bytes")" "$NC" \
|
||||
"$BLUE" "$cutoff_date" "$NC"
|
||||
printf ' Downloads shown: %b%d / %s%b; internal files hidden: %b%d%b.\n' \
|
||||
"$CYAN" "$removed_artifact_count" "$(format_bytes "$removed_artifact_bytes")" "$NC" \
|
||||
"$CYAN" "$hidden_count" "$NC"
|
||||
|
||||
if ! find "$cache_dir" -mindepth 1 \( -type f -o -type l \) \
|
||||
-newer "$ACTIVE_CLEANUP_MARKER" -print0 > "$ACTIVE_CLEANUP_MANIFEST"; then
|
||||
@@ -457,7 +554,7 @@ prune_cache_before_today() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%bRetained cache files dated today or later:%b\n' "$GREEN" "$NC"
|
||||
printf '%bRetained download artifacts from today:%b\n' "$GREEN" "$NC"
|
||||
while IFS= read -r -d '' file; do
|
||||
if ! file_size="$(stat -f '%z' -- "$file" 2>/dev/null)"; then
|
||||
file_size=0
|
||||
@@ -465,14 +562,21 @@ prune_cache_before_today() {
|
||||
relative_path="${file#"$cache_dir"/}"
|
||||
kept_count=$((kept_count + 1))
|
||||
kept_bytes=$((kept_bytes + file_size))
|
||||
printf ' %b%10s%b %q\n' "$CYAN" "$(format_bytes "$file_size")" "$NC" "$relative_path"
|
||||
if is_cache_download_artifact "$relative_path"; then
|
||||
kept_artifact_count=$((kept_artifact_count + 1))
|
||||
kept_artifact_bytes=$((kept_artifact_bytes + file_size))
|
||||
display_name="$(cache_artifact_display_name "$relative_path")"
|
||||
printf ' %b%10s%b %q\n' "$CYAN" "$(format_bytes "$file_size")" "$NC" "$display_name"
|
||||
fi
|
||||
done < "$ACTIVE_CLEANUP_MANIFEST"
|
||||
if ((kept_count == 0)); then
|
||||
printf ' (none)\n'
|
||||
fi
|
||||
printf '%bRetained%b %b%d%b Homebrew cache file(s) dated %b%s%b or later (%b%s total%b).\n' \
|
||||
"$GREEN" "$NC" "$CYAN" "$kept_count" "$NC" "$BLUE" "$cutoff_date" "$NC" \
|
||||
"$CYAN" "$(format_bytes "$kept_bytes")" "$NC"
|
||||
((kept_artifact_count > 0)) || printf ' (none)\n'
|
||||
hidden_count=$((kept_count - kept_artifact_count))
|
||||
printf '%bRetained:%b %b%d files / %s%b dated %b%s%b or later.\n' \
|
||||
"$GREEN" "$NC" "$CYAN" "$kept_count" "$(format_bytes "$kept_bytes")" "$NC" \
|
||||
"$BLUE" "$cutoff_date" "$NC"
|
||||
printf ' Downloads shown: %b%d / %s%b; internal files hidden: %b%d%b.\n' \
|
||||
"$CYAN" "$kept_artifact_count" "$(format_bytes "$kept_artifact_bytes")" "$NC" \
|
||||
"$CYAN" "$hidden_count" "$NC"
|
||||
|
||||
rm -f "$ACTIVE_CLEANUP_MARKER"
|
||||
ACTIVE_CLEANUP_MARKER=""
|
||||
@@ -543,7 +647,7 @@ separator
|
||||
print_header "Step 2: Performing health check (brew doctor)"
|
||||
if is_enabled "${HB_SKIP_DOCTOR:-0}"; then
|
||||
print_notice "brew doctor skipped because HB_SKIP_DOCTOR is enabled."
|
||||
elif ! brew doctor; then
|
||||
elif ! run_brew_doctor; then
|
||||
print_warning "'brew doctor' detected issues. Manual review is recommended."
|
||||
else
|
||||
print_success "Homebrew environment is in good health."
|
||||
@@ -570,7 +674,7 @@ separator
|
||||
printf '\n'
|
||||
|
||||
separator
|
||||
print_header "Step 4: Cleaning cache dated before today (keeping today's downloads)"
|
||||
print_header "Step 4: Cleaning old cache (showing download artifacts only)"
|
||||
if ! run_cleanup; then
|
||||
overall_status=1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user