mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 12:41:46 +00:00
feat: Add local APFS snapshot cleanup, optimize Homebrew health check, and enhance UI feedback for various operations
This commit is contained in:
@@ -596,6 +596,7 @@ perform_cleanup() {
|
||||
start_section "Deep system"
|
||||
# Deep system cleanup (delegated to clean_system module)
|
||||
clean_deep_system
|
||||
clean_local_snapshots
|
||||
end_section
|
||||
fi
|
||||
|
||||
|
||||
@@ -283,7 +283,7 @@ get_software_updates() {
|
||||
# Show spinner while checking (only on first call)
|
||||
local show_spinner=false
|
||||
if [[ -t 1 && -z "${SOFTWAREUPDATE_SPINNER_SHOWN:-}" ]]; then
|
||||
start_inline_spinner "Checking system updates..."
|
||||
start_inline_spinner "Checking system updates (querying Apple servers)..."
|
||||
show_spinner=true
|
||||
export SOFTWAREUPDATE_SPINNER_SHOWN="true"
|
||||
fi
|
||||
@@ -305,7 +305,7 @@ check_appstore_updates() {
|
||||
local spinner_started=false
|
||||
if [[ -t 1 ]]; then
|
||||
printf " Checking App Store updates...\r"
|
||||
start_inline_spinner "Checking App Store updates..."
|
||||
start_inline_spinner "Checking App Store updates (querying Apple servers)..."
|
||||
spinner_started=true
|
||||
export SOFTWAREUPDATE_SPINNER_SHOWN="external"
|
||||
else
|
||||
@@ -329,7 +329,7 @@ check_appstore_updates() {
|
||||
|
||||
if [[ $update_count -gt 0 ]]; then
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} App Store ${YELLOW}${update_count} apps${NC} need update"
|
||||
echo -e " ${GRAY}Run: ${GREEN}softwareupdate -i <label>${NC}"
|
||||
echo -e " ${GRAY}updates available in final step${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} App Store Up to date"
|
||||
fi
|
||||
@@ -341,7 +341,7 @@ check_macos_update() {
|
||||
local spinner_started=false
|
||||
if [[ -t 1 ]]; then
|
||||
printf " Checking macOS updates...\r"
|
||||
start_inline_spinner "Checking macOS updates..."
|
||||
start_inline_spinner "Checking macOS updates (querying Apple servers)..."
|
||||
spinner_started=true
|
||||
export SOFTWAREUPDATE_SPINNER_SHOWN="external"
|
||||
else
|
||||
@@ -367,7 +367,7 @@ check_macos_update() {
|
||||
else
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} macOS ${YELLOW}Update available${NC}"
|
||||
fi
|
||||
echo -e " ${GRAY}Run: ${GREEN}softwareupdate -i <label>${NC}"
|
||||
echo -e " ${GRAY}update available in final step${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} macOS Up to date"
|
||||
fi
|
||||
@@ -662,32 +662,10 @@ check_swap_usage() {
|
||||
check_brew_health() {
|
||||
# Check whitelist
|
||||
if command -v is_whitelisted > /dev/null && is_whitelisted "check_brew_health"; then return; fi
|
||||
# Check Homebrew doctor
|
||||
# Check Homebrew status (fast)
|
||||
if command -v brew > /dev/null 2>&1; then
|
||||
# Show spinner while running brew doctor
|
||||
if [[ -t 1 ]]; then
|
||||
start_inline_spinner "Running brew doctor..."
|
||||
fi
|
||||
|
||||
local brew_doctor=$(brew doctor 2>&1 || echo "")
|
||||
|
||||
# Stop spinner before output
|
||||
if [[ -t 1 ]]; then
|
||||
stop_inline_spinner
|
||||
fi
|
||||
|
||||
if echo "$brew_doctor" | grep -q "ready to brew"; then
|
||||
echo -e " ${GREEN}✓${NC} Homebrew Healthy"
|
||||
else
|
||||
local warning_count=$(echo "$brew_doctor" | grep -c "Warning:" || echo "0")
|
||||
if [[ $warning_count -gt 0 ]]; then
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Homebrew ${YELLOW}${warning_count} warnings${NC}"
|
||||
echo -e " ${GRAY}Run: ${GREEN}brew doctor${NC} to see fixes, then rerun until clean${NC}"
|
||||
export BREW_HAS_WARNINGS=true
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Homebrew Healthy"
|
||||
fi
|
||||
fi
|
||||
# Skip slow 'brew doctor' check by default
|
||||
echo -e " ${GREEN}✓${NC} Homebrew Installed"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ EOF
|
||||
items+=('swap_cleanup|Swap Refresh|Reset swap files and dynamic pager|true')
|
||||
items+=('spotlight_cache_cleanup|Spotlight Cache|Clear user-level Spotlight indexes|true')
|
||||
items+=('developer_cleanup|Developer Cleanup|Clear Xcode DerivedData & DeviceSupport|true')
|
||||
items+=('network_optimization|Network Optimization|Flush DNS, ARP & reset mDNS|true')
|
||||
|
||||
# Output items as JSON
|
||||
local first=true
|
||||
|
||||
@@ -151,7 +151,23 @@ clean_dev_mobile() {
|
||||
# Can free up significant space (70GB+ in some cases)
|
||||
if command -v xcrun > /dev/null 2>&1; then
|
||||
debug_log "Checking for unavailable Xcode simulators"
|
||||
clean_tool_cache "Xcode unavailable simulators" xcrun simctl delete unavailable
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
clean_tool_cache "Xcode unavailable simulators" xcrun simctl delete unavailable
|
||||
else
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Checking unavailable simulators..."
|
||||
fi
|
||||
|
||||
# Run command manually to control UI output order
|
||||
if xcrun simctl delete unavailable > /dev/null 2>&1; then
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Xcode unavailable simulators"
|
||||
else
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
# Silently fail or log error if needed, matching clean_tool_cache behavior
|
||||
fi
|
||||
fi
|
||||
note_activity
|
||||
fi
|
||||
|
||||
@@ -286,7 +302,26 @@ clean_developer_tools() {
|
||||
|
||||
# Homebrew caches and cleanup (delegated to clean_brew module)
|
||||
safe_clean ~/Library/Caches/Homebrew/* "Homebrew cache"
|
||||
safe_clean /opt/homebrew/var/homebrew/locks/* "Homebrew lock files (M series)"
|
||||
safe_clean /usr/local/var/homebrew/locks/* "Homebrew lock files (Intel)"
|
||||
|
||||
# Clean Homebrew locks intelligently (avoid repeated sudo prompts)
|
||||
local brew_lock_dirs=(
|
||||
"/opt/homebrew/var/homebrew/locks"
|
||||
"/usr/local/var/homebrew/locks"
|
||||
)
|
||||
|
||||
for lock_dir in "${brew_lock_dirs[@]}"; do
|
||||
if [[ -d "$lock_dir" && -w "$lock_dir" ]]; then
|
||||
# User can write, safe to clean
|
||||
safe_clean "$lock_dir"/* "Homebrew lock files"
|
||||
elif [[ -d "$lock_dir" ]]; then
|
||||
# Directory exists but not writable. Check if empty to avoid noise.
|
||||
if [[ -n "$(ls -A "$lock_dir" 2>/dev/null)" ]]; then
|
||||
# Only try sudo ONCE if we really need to, or just skip to avoid spam
|
||||
# Decision: Skip strict system/root owned locks to avoid nag.
|
||||
debug_log "Skipping read-only Homebrew locks in $lock_dir"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
clean_homebrew
|
||||
}
|
||||
|
||||
@@ -77,6 +77,9 @@ clean_deep_system() {
|
||||
|
||||
# Clean browser code signature caches
|
||||
# These are regenerated automatically when needed
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Scanning system caches..."
|
||||
fi
|
||||
local code_sign_cleaned=0
|
||||
while IFS= read -r -d '' cache_dir; do
|
||||
debug_log "Found code sign cache: $cache_dir"
|
||||
@@ -85,6 +88,8 @@ clean_deep_system() {
|
||||
fi
|
||||
done < <(find /private/var/folders -type d -name "*.code_sign_clone" -path "*/X/*" -print0 2> /dev/null || true)
|
||||
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
|
||||
[[ $code_sign_cleaned -gt 0 ]] && log_success "Browser code signature caches ($code_sign_cleaned items)"
|
||||
|
||||
# Clean system diagnostics logs
|
||||
@@ -127,6 +132,10 @@ clean_time_machine_failed_backups() {
|
||||
# Skip system and network volumes
|
||||
[[ "$volume" == "/Volumes/MacintoshHD" || "$volume" == "/" ]] && continue
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Scanning backup volumes..."
|
||||
fi
|
||||
|
||||
# Skip if volume is a symlink (security check)
|
||||
[[ -L "$volume" ]] && continue
|
||||
|
||||
@@ -242,9 +251,73 @@ clean_time_machine_failed_backups() {
|
||||
done < <(run_with_timeout 15 find "$mounted_path" -maxdepth 3 -type d \( -name "*.inProgress" -o -name "*.inprogress" \) 2> /dev/null || true)
|
||||
fi
|
||||
done
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
done
|
||||
|
||||
if [[ $tm_cleaned -eq 0 ]]; then
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} No failed Time Machine backups found"
|
||||
fi
|
||||
}
|
||||
|
||||
# Clean local APFS snapshots (older than 24h)
|
||||
clean_local_snapshots() {
|
||||
# Check if tmutil is available
|
||||
if ! command -v tmutil > /dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Checking local snapshots..."
|
||||
fi
|
||||
|
||||
# Check for local snapshots
|
||||
local snapshot_list
|
||||
snapshot_list=$(tmutil listlocalsnapshots / 2> /dev/null)
|
||||
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
|
||||
[[ -z "$snapshot_list" ]] && return 0
|
||||
|
||||
# Parse and clean snapshots
|
||||
local cleaned_count=0
|
||||
local total_cleaned_size=0 # Estimation not possible without thin
|
||||
|
||||
# Get current time
|
||||
local current_ts=$(date +%s)
|
||||
local one_day_ago=$((current_ts - 86400))
|
||||
|
||||
while IFS= read -r line; do
|
||||
# Format: com.apple.TimeMachine.2023-10-25-120000
|
||||
if [[ "$line" =~ com\.apple\.TimeMachine\.([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]{6}) ]]; then
|
||||
local date_str="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]} ${BASH_REMATCH[4]:0:2}:${BASH_REMATCH[4]:2:2}:${BASH_REMATCH[4]:4:2}"
|
||||
local snap_ts=$(date -j -f "%Y-%m-%d %H:%M:%S" "$date_str" "+%s" 2>/dev/null || echo "0")
|
||||
|
||||
# Skip if parsing failed
|
||||
[[ "$snap_ts" == "0" ]] && continue
|
||||
|
||||
# If snapshot is older than 24 hours
|
||||
if [[ $snap_ts -lt $one_day_ago ]]; then
|
||||
local snap_name="${BASH_REMATCH[0]}"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo -e " ${YELLOW}→${NC} Old local snapshot: $snap_name ${YELLOW}(dry)${NC}"
|
||||
((cleaned_count++))
|
||||
note_activity
|
||||
else
|
||||
# Secure removal
|
||||
if safe_sudo tmutil deletelocalsnapshots "${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}-${BASH_REMATCH[4]}" > /dev/null 2>&1; then
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Removed snapshot: $snap_name"
|
||||
((cleaned_count++))
|
||||
note_activity
|
||||
else
|
||||
echo -e " ${YELLOW}!${NC} Failed to remove: $snap_name"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done <<< "$snapshot_list"
|
||||
|
||||
if [[ $cleaned_count -gt 0 && "$DRY_RUN" != "true" ]]; then
|
||||
log_success "Cleaned $cleaned_count old local snapshots"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ clean_user_essentials() {
|
||||
|
||||
# Empty trash on mounted volumes
|
||||
if [[ -d "/Volumes" && "$DRY_RUN" != "true" ]]; then
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Scanning external volumes..."
|
||||
fi
|
||||
for volume in /Volumes/*; do
|
||||
[[ -d "$volume" && -d "$volume/.Trashes" && -w "$volume" ]] || continue
|
||||
|
||||
@@ -29,6 +32,7 @@ clean_user_essentials() {
|
||||
safe_remove "$item" true || true
|
||||
done < <(command find "$volume/.Trashes" -mindepth 1 -maxdepth 1 -print0 2> /dev/null || true)
|
||||
done
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
fi
|
||||
|
||||
safe_clean ~/Library/DiagnosticReports/* "Diagnostic reports"
|
||||
@@ -97,25 +101,63 @@ clean_sandboxed_app_caches() {
|
||||
safe_clean ~/Library/Containers/com.apple.AppStore/Data/Library/Caches/* "App Store cache"
|
||||
safe_clean ~/Library/Containers/com.apple.configurator.xpc.InternetService/Data/tmp/* "Apple Configurator temp files"
|
||||
|
||||
# Clean sandboxed app caches - iterate to avoid shell expansion hang
|
||||
# Check container protection BEFORE expanding cache files to prevent
|
||||
# redundant protection checks on each file (Issue #116)
|
||||
# Clean sandboxed app caches - iterate quietly to avoid UI flashing
|
||||
local containers_dir="$HOME/Library/Containers"
|
||||
[[ ! -d "$containers_dir" ]] && return 0
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Scanning sandboxed apps..."
|
||||
fi
|
||||
|
||||
local total_size=0
|
||||
local cleaned_count=0
|
||||
local found_any=false
|
||||
|
||||
for container_dir in "$containers_dir"/*; do
|
||||
[[ -d "$container_dir" ]] || continue
|
||||
|
||||
# Extract bundle ID and check protection status early
|
||||
local bundle_id=$(basename "$container_dir")
|
||||
if should_protect_data "$bundle_id"; then
|
||||
debug_log "Protecting system container: $bundle_id"
|
||||
continue
|
||||
fi
|
||||
|
||||
local cache_dir="$container_dir/Data/Library/Caches"
|
||||
[[ -d "$cache_dir" ]] && safe_clean "$cache_dir"/* "Sandboxed app caches"
|
||||
# Check if dir exists and has content
|
||||
if [[ -d "$cache_dir" ]]; then
|
||||
# Fast check if empty (avoid expensive size calc on empty dirs)
|
||||
if [[ -n "$(ls -A "$cache_dir" 2>/dev/null)" ]]; then
|
||||
# Get size
|
||||
local size=$(get_path_size_kb "$cache_dir")
|
||||
((total_size += size))
|
||||
found_any=true
|
||||
((cleaned_count++))
|
||||
|
||||
if [[ "$DRY_RUN" != "true" ]]; then
|
||||
# Clean contents safely
|
||||
# We know this is a user cache path, so rm -rf is acceptable here
|
||||
# provided we keep the Cache directory itself
|
||||
rm -rf "$cache_dir"/* 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
|
||||
if [[ "$found_any" == "true" ]]; then
|
||||
local size_human=$(bytes_to_human "$((total_size * 1024))")
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo -e " ${YELLOW}→${NC} Sandboxed app caches ${YELLOW}($size_human dry)${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Sandboxed app caches ${GREEN}($size_human)${NC}"
|
||||
fi
|
||||
# Update global counters
|
||||
((files_cleaned += cleaned_count))
|
||||
((total_size_cleaned += total_size))
|
||||
((total_items++))
|
||||
note_activity
|
||||
fi
|
||||
}
|
||||
|
||||
# Clean browser caches (Safari, Chrome, Edge, Firefox, etc.)
|
||||
@@ -177,28 +219,28 @@ clean_virtualization_tools() {
|
||||
|
||||
# Clean Application Support logs and caches
|
||||
clean_application_support_logs() {
|
||||
# Check permission
|
||||
if [[ ! -d "$HOME/Library/Application Support" ]] || ! ls "$HOME/Library/Application Support" > /dev/null 2>&1; then
|
||||
note_activity
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Skipped: No permission to access Application Support"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Scanning Application Support..."
|
||||
fi
|
||||
|
||||
local total_size=0
|
||||
local cleaned_count=0
|
||||
local found_any=false
|
||||
|
||||
# Clean log directories and cache patterns
|
||||
for app_dir in ~/Library/Application\ Support/*; do
|
||||
[[ -d "$app_dir" ]] || continue
|
||||
|
||||
app_name=$(basename "$app_dir")
|
||||
|
||||
# Skip system and protected apps (case-insensitive)
|
||||
local app_name_lower
|
||||
app_name_lower=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
|
||||
# Use centralized protection logic from app_protection.sh
|
||||
# Check against System Critical and Data Protected bundles
|
||||
local app_name=$(basename "$app_dir")
|
||||
local app_name_lower=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
|
||||
local is_protected=false
|
||||
|
||||
# Check if directory name matches any protected pattern
|
||||
# We check both exact name and lowercase version against the patterns
|
||||
if should_protect_data "$app_name"; then
|
||||
is_protected=true
|
||||
elif should_protect_data "$app_name_lower"; then
|
||||
@@ -207,45 +249,68 @@ clean_application_support_logs() {
|
||||
|
||||
[[ "$is_protected" == "true" ]] && continue
|
||||
|
||||
# Explicit safety check for System Settings / Login Items (Issue #122)
|
||||
if [[ "$app_name" =~ backgroundtaskmanagement || "$app_name" =~ loginitems ]]; then
|
||||
debug_log "Skipping critical system component: $app_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Clean log directories - simple direct removal without deep scanning
|
||||
[[ -d "$app_dir/log" ]] && safe_clean "$app_dir/log"/* "App logs: $app_name"
|
||||
[[ -d "$app_dir/logs" ]] && safe_clean "$app_dir/logs"/* "App logs: $app_name"
|
||||
[[ -d "$app_dir/activitylog" ]] && safe_clean "$app_dir/activitylog"/* "Activity logs: $app_name"
|
||||
local -a start_candidates=("$app_dir/log" "$app_dir/logs" "$app_dir/activitylog" "$app_dir/Cache/Cache_Data" "$app_dir/Crashpad/completed")
|
||||
|
||||
# Clean common cache patterns - skip complex patterns that might hang
|
||||
[[ -d "$app_dir/Cache/Cache_Data" ]] && safe_clean "$app_dir/Cache/Cache_Data" "Cache data: $app_name"
|
||||
[[ -d "$app_dir/Crashpad/completed" ]] && safe_clean "$app_dir/Crashpad/completed"/* "Crash reports: $app_name"
|
||||
for candidate in "${start_candidates[@]}"; do
|
||||
if [[ -d "$candidate" ]]; then
|
||||
if [[ -n "$(ls -A "$candidate" 2>/dev/null)" ]]; then
|
||||
local size=$(get_path_size_kb "$candidate")
|
||||
((total_size += size))
|
||||
((cleaned_count++))
|
||||
found_any=true
|
||||
|
||||
# DISABLED: Service Worker and update scanning (too slow, causes hanging)
|
||||
# These are covered by browser-specific cleaning in clean_browsers()
|
||||
if [[ "$DRY_RUN" != "true" ]]; then
|
||||
safe_remove "$candidate"/* true >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Clean Group Containers logs - only scan known containers to avoid hanging
|
||||
# Direct path access is fast and won't cause performance issues
|
||||
# Add new containers here as users report them
|
||||
# Clean Group Containers logs
|
||||
local known_group_containers=(
|
||||
"group.com.apple.contentdelivery" # Issue #104: Can accumulate 4GB+ in Library/Logs/Transporter
|
||||
"group.com.apple.contentdelivery"
|
||||
)
|
||||
|
||||
for container in "${known_group_containers[@]}"; do
|
||||
local container_path="$HOME/Library/Group Containers/$container"
|
||||
local -a gc_candidates=("$container_path/Logs" "$container_path/Library/Logs")
|
||||
|
||||
# Check both direct Logs and Library/Logs patterns
|
||||
if [[ -d "$container_path/Logs" ]]; then
|
||||
debug_log "Scanning Group Container: $container/Logs"
|
||||
safe_clean "$container_path/Logs"/* "Group container logs: $container"
|
||||
fi
|
||||
if [[ -d "$container_path/Library/Logs" ]]; then
|
||||
debug_log "Scanning Group Container: $container/Library/Logs"
|
||||
safe_clean "$container_path/Library/Logs"/* "Group container logs: $container"
|
||||
fi
|
||||
for candidate in "${gc_candidates[@]}"; do
|
||||
if [[ -d "$candidate" ]]; then
|
||||
if [[ -n "$(ls -A "$candidate" 2>/dev/null)" ]]; then
|
||||
local size=$(get_path_size_kb "$candidate")
|
||||
((total_size += size))
|
||||
((cleaned_count++))
|
||||
found_any=true
|
||||
|
||||
if [[ "$DRY_RUN" != "true" ]]; then
|
||||
safe_remove "$candidate"/* true >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ -t 1 ]]; then stop_inline_spinner; fi
|
||||
|
||||
if [[ "$found_any" == "true" ]]; then
|
||||
local size_human=$(bytes_to_human "$((total_size * 1024))")
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo -e " ${YELLOW}→${NC} Application Support logs/caches ${YELLOW}($size_human dry)${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Application Support logs/caches ${GREEN}($size_human)${NC}"
|
||||
fi
|
||||
# Update global counters
|
||||
((files_cleaned += cleaned_count))
|
||||
((total_size_cleaned += total_size))
|
||||
((total_items++))
|
||||
note_activity
|
||||
fi
|
||||
}
|
||||
|
||||
# Check and show iOS device backup info
|
||||
|
||||
@@ -290,6 +290,7 @@ _perform_appstore_update() {
|
||||
|
||||
if [[ "$appstore_needs_fallback" == "true" ]]; then
|
||||
echo -e " ${GRAY}Installing all available updates${NC}"
|
||||
echo -e " ${GRAY}Contacting Apple servers (this may take a few minutes)...${NC}"
|
||||
if sudo softwareupdate -i -a 2>&1 | tee "$appstore_log" | grep -v "^$"; then
|
||||
echo -e "${GREEN}✓${NC} Software updates completed"
|
||||
((updated_count++))
|
||||
@@ -301,6 +302,7 @@ _perform_appstore_update() {
|
||||
echo -e "${RED}✗${NC} Software update failed"
|
||||
fi
|
||||
else
|
||||
echo -e " ${GRAY}Contacting Apple servers (this may take a few minutes)...${NC}"
|
||||
if sudo softwareupdate -i "${appstore_labels[@]}" 2>&1 | tee "$appstore_log" | grep -v "^$"; then
|
||||
echo -e "${GREEN}✓${NC} App Store apps updated"
|
||||
((updated_count++))
|
||||
@@ -322,6 +324,7 @@ _perform_macos_update() {
|
||||
macos_log=$(mktemp "${TMPDIR:-/tmp}/mole-macos.XXXXXX" 2> /dev/null || echo "/tmp/mole-macos.log")
|
||||
|
||||
if [[ "$macos_needs_fallback" == "true" ]]; then
|
||||
echo -e " ${GRAY}Contacting Apple servers (this may take a few minutes)...${NC}"
|
||||
if sudo softwareupdate -i -r 2>&1 | tee "$macos_log" | grep -v "^$"; then
|
||||
echo -e "${GREEN}✓${NC} macOS updated"
|
||||
((updated_count++))
|
||||
@@ -329,6 +332,7 @@ _perform_macos_update() {
|
||||
echo -e "${RED}✗${NC} macOS update failed"
|
||||
fi
|
||||
else
|
||||
echo -e " ${GRAY}Contacting Apple servers (this may take a few minutes)...${NC}"
|
||||
if sudo softwareupdate -i "${macos_labels[@]}" 2>&1 | tee "$macos_log" | grep -v "^$"; then
|
||||
echo -e "${GREEN}✓${NC} macOS updated"
|
||||
((updated_count++))
|
||||
|
||||
Reference in New Issue
Block a user