mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 15:39:42 +00:00
System optimization and massive updates
This commit is contained in:
133
bin/optimize.sh
133
bin/optimize.sh
@@ -27,6 +27,7 @@ print_header() {
|
||||
|
||||
# System check functions (real-time display)
|
||||
run_system_checks() {
|
||||
unset AUTO_FIX_SUMMARY AUTO_FIX_DETAILS
|
||||
echo ""
|
||||
echo -e "${PURPLE}System Check${NC}"
|
||||
echo ""
|
||||
@@ -44,6 +45,9 @@ run_system_checks() {
|
||||
# Check security - real-time display
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Security posture"
|
||||
check_all_security
|
||||
if ask_for_security_fixes; then
|
||||
perform_security_fixes
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check configuration - real-time display
|
||||
@@ -67,30 +71,32 @@ run_system_checks() {
|
||||
}
|
||||
|
||||
show_optimization_summary() {
|
||||
if [[ -z "${OPTIMIZE_SAFE_COUNT:-}" ]]; then
|
||||
local safe_count="${OPTIMIZE_SAFE_COUNT:-0}"
|
||||
local confirm_count="${OPTIMIZE_CONFIRM_COUNT:-0}"
|
||||
if (( safe_count == 0 && confirm_count == 0 )) && [[ -z "${AUTO_FIX_SUMMARY:-}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo ""
|
||||
local summary_title="Optimization and Check Complete"
|
||||
local -a summary_details=()
|
||||
|
||||
# Optimization results
|
||||
if ((OPTIMIZE_SAFE_COUNT > 0)); then
|
||||
summary_details+=("Applied ${GREEN}${OPTIMIZE_SAFE_COUNT}${NC} optimizations")
|
||||
summary_details+=("Optimizations: ${GREEN}${safe_count}${NC} applied, ${YELLOW}${confirm_count}${NC} manual checks")
|
||||
summary_details+=("Caches refreshed; services restarted; system tuned")
|
||||
summary_details+=("Updates & security reviewed across system")
|
||||
|
||||
local summary_line4=""
|
||||
if [[ -n "${AUTO_FIX_SUMMARY:-}" ]]; then
|
||||
summary_line4="${AUTO_FIX_SUMMARY}"
|
||||
if [[ -n "${AUTO_FIX_DETAILS:-}" ]]; then
|
||||
local detail_join
|
||||
detail_join=$(echo "${AUTO_FIX_DETAILS}" | paste -sd ", " -)
|
||||
[[ -n "$detail_join" ]] && summary_line4+=" — ${detail_join}"
|
||||
fi
|
||||
else
|
||||
summary_details+=("System already optimized")
|
||||
summary_line4="Mac should feel faster and more responsive"
|
||||
fi
|
||||
|
||||
if ((OPTIMIZE_CONFIRM_COUNT > 0)); then
|
||||
summary_details+=("${YELLOW}${OPTIMIZE_CONFIRM_COUNT}${NC} manual checks suggested")
|
||||
fi
|
||||
|
||||
summary_details+=("Caches cleared, databases rebuilt, services refreshed")
|
||||
|
||||
# System check results
|
||||
summary_details+=("System updates, health, security, and config reviewed")
|
||||
summary_details+=("System should feel faster and more responsive")
|
||||
summary_details+=("$summary_line4")
|
||||
|
||||
if [[ "${OPTIMIZE_SHOW_TOUCHID_TIP:-false}" == "true" ]]; then
|
||||
echo -e "${YELLOW}☻${NC} Run ${GRAY}mo touchid${NC} to approve sudo via Touch ID"
|
||||
@@ -218,6 +224,97 @@ count_local_snapshots() {
|
||||
echo "$output" | grep -c "com.apple.TimeMachine." | tr -d ' '
|
||||
}
|
||||
|
||||
declare -a SECURITY_FIXES=()
|
||||
|
||||
collect_security_fix_actions() {
|
||||
SECURITY_FIXES=()
|
||||
if [[ "${FIREWALL_DISABLED:-}" == "true" ]]; then
|
||||
SECURITY_FIXES+=("firewall|Enable macOS firewall")
|
||||
fi
|
||||
if [[ "${GATEKEEPER_DISABLED:-}" == "true" ]]; then
|
||||
SECURITY_FIXES+=("gatekeeper|Enable Gatekeeper (App download protection)")
|
||||
fi
|
||||
|
||||
((${#SECURITY_FIXES[@]} > 0))
|
||||
}
|
||||
|
||||
ask_for_security_fixes() {
|
||||
if ! collect_security_fix_actions; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}SECURITY FIXES${NC}"
|
||||
for entry in "${SECURITY_FIXES[@]}"; do
|
||||
IFS='|' read -r _ label <<< "$entry"
|
||||
echo -e " ${ICON_LIST} $label"
|
||||
done
|
||||
echo ""
|
||||
echo -ne "${YELLOW}Apply now?${NC} ${GRAY}Enter confirm / ESC cancel${NC}: "
|
||||
|
||||
local key
|
||||
if ! key=$(read_key); then
|
||||
echo "skip"
|
||||
echo ""
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$key" == "ENTER" ]]; then
|
||||
echo "apply"
|
||||
echo ""
|
||||
return 0
|
||||
else
|
||||
echo "skip"
|
||||
echo ""
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
apply_firewall_fix() {
|
||||
if sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1; then
|
||||
sudo pkill -HUP socketfilterfw 2> /dev/null || true
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Firewall enabled"
|
||||
FIREWALL_DISABLED=false
|
||||
return 0
|
||||
fi
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Failed to enable firewall (check permissions)"
|
||||
return 1
|
||||
}
|
||||
|
||||
apply_gatekeeper_fix() {
|
||||
if sudo spctl --master-enable 2> /dev/null; then
|
||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Gatekeeper enabled"
|
||||
GATEKEEPER_DISABLED=false
|
||||
return 0
|
||||
fi
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Failed to enable Gatekeeper"
|
||||
return 1
|
||||
}
|
||||
|
||||
perform_security_fixes() {
|
||||
if ! ensure_sudo_session "Security changes require admin access"; then
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Skipped security fixes (sudo denied)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local applied=0
|
||||
for entry in "${SECURITY_FIXES[@]}"; do
|
||||
IFS='|' read -r action _ <<< "$entry"
|
||||
case "$action" in
|
||||
firewall)
|
||||
apply_firewall_fix && ((applied++))
|
||||
;;
|
||||
gatekeeper)
|
||||
apply_gatekeeper_fix && ((applied++))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ((applied > 0)); then
|
||||
log_success "Security settings updated"
|
||||
fi
|
||||
SECURITY_FIXES=()
|
||||
}
|
||||
|
||||
|
||||
cleanup_all() {
|
||||
stop_sudo_session
|
||||
@@ -364,6 +461,9 @@ main() {
|
||||
local safe_count=${#safe_items[@]}
|
||||
local confirm_count=${#confirm_items[@]}
|
||||
|
||||
# Run system checks first
|
||||
run_system_checks
|
||||
|
||||
export OPTIMIZE_SAFE_COUNT=$safe_count
|
||||
export OPTIMIZE_CONFIRM_COUNT=$confirm_count
|
||||
export OPTIMIZE_SHOW_TOUCHID_TIP="false"
|
||||
@@ -371,9 +471,6 @@ main() {
|
||||
export OPTIMIZE_SHOW_TOUCHID_TIP="true"
|
||||
fi
|
||||
|
||||
# Run system checks first
|
||||
run_system_checks
|
||||
|
||||
# Show optimization summary at the end
|
||||
show_optimization_summary
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ show_suggestions() {
|
||||
# Show auto-fix items
|
||||
if [[ ${#auto_fix_items[@]} -gt 0 ]]; then
|
||||
for item in "${auto_fix_items[@]}"; do
|
||||
echo -e " ${YELLOW}⚠${NC} ${item} ${GREEN}[auto]${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} ${item} ${GREEN}[auto]${NC}"
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -78,7 +78,7 @@ show_suggestions() {
|
||||
for item in "${manual_items[@]}"; do
|
||||
local title="${item%%|*}"
|
||||
local hint="${item#*|}"
|
||||
echo -e " ${YELLOW}⚠${NC} ${title}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} ${title}"
|
||||
echo -e " ${GRAY}${hint}${NC}"
|
||||
done
|
||||
fi
|
||||
@@ -94,7 +94,7 @@ ask_for_auto_fix() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -ne "Fix issues marked ${GREEN}[auto]${NC}? ${GRAY}Enter yes / ESC no${NC}: "
|
||||
echo -ne "${PURPLE}${ICON_ARROW}${NC} Auto-fix issues now? ${GRAY}Enter confirm / ESC cancel${NC}: "
|
||||
|
||||
local key
|
||||
if ! key=$(read_key); then
|
||||
@@ -118,6 +118,7 @@ ask_for_auto_fix() {
|
||||
# Returns: number of fixes applied
|
||||
perform_auto_fix() {
|
||||
local fixed_count=0
|
||||
local -a fixed_items=()
|
||||
|
||||
# Ensure sudo access
|
||||
if ! has_sudo_session; then
|
||||
@@ -134,6 +135,7 @@ perform_auto_fix() {
|
||||
if sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1 2>/dev/null; then
|
||||
echo -e "${GREEN}✓${NC} Firewall enabled"
|
||||
((fixed_count++))
|
||||
fixed_items+=("Firewall enabled")
|
||||
else
|
||||
echo -e "${RED}✗${NC} Failed to enable Firewall"
|
||||
fi
|
||||
@@ -142,13 +144,14 @@ perform_auto_fix() {
|
||||
|
||||
# Fix Touch ID
|
||||
if [[ -n "${TOUCHID_NOT_CONFIGURED:-}" && "${TOUCHID_NOT_CONFIGURED}" == "true" ]]; then
|
||||
echo -e "${BLUE}Configuring Touch ID for sudo...${NC}"
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Configuring Touch ID for sudo..."
|
||||
local pam_file="/etc/pam.d/sudo"
|
||||
if sudo bash -c "grep -q 'pam_tid.so' '$pam_file' 2>/dev/null || sed -i '' '2i\\
|
||||
auth sufficient pam_tid.so
|
||||
' '$pam_file'" 2>/dev/null; then
|
||||
echo -e "${GREEN}✓${NC} Touch ID configured"
|
||||
((fixed_count++))
|
||||
fixed_items+=("Touch ID configured for sudo")
|
||||
else
|
||||
echo -e "${RED}✗${NC} Failed to configure Touch ID"
|
||||
fi
|
||||
@@ -161,6 +164,7 @@ auth sufficient pam_tid.so
|
||||
if sudo softwareupdate --install-rosetta --agree-to-license 2>&1 | grep -qE "(Installing|Installed|already installed)"; then
|
||||
echo -e "${GREEN}✓${NC} Rosetta 2 installed"
|
||||
((fixed_count++))
|
||||
fixed_items+=("Rosetta 2 installed")
|
||||
else
|
||||
echo -e "${RED}✗${NC} Failed to install Rosetta 2"
|
||||
fi
|
||||
@@ -168,11 +172,16 @@ auth sufficient pam_tid.so
|
||||
fi
|
||||
|
||||
if [[ $fixed_count -gt 0 ]]; then
|
||||
echo -e "${GREEN}Fixed ${fixed_count} issue(s)${NC}"
|
||||
AUTO_FIX_SUMMARY="Auto fixes applied: ${fixed_count} issue(s)"
|
||||
if [[ ${#fixed_items[@]} -gt 0 ]]; then
|
||||
AUTO_FIX_DETAILS=$(printf '%s\n' "${fixed_items[@]}")
|
||||
else
|
||||
AUTO_FIX_DETAILS=""
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}No issues were fixed${NC}"
|
||||
AUTO_FIX_SUMMARY="Auto fixes skipped: No changes were required"
|
||||
AUTO_FIX_DETAILS=""
|
||||
fi
|
||||
echo ""
|
||||
|
||||
return $fixed_count
|
||||
export AUTO_FIX_SUMMARY AUTO_FIX_DETAILS
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ check_touchid_sudo() {
|
||||
fi
|
||||
|
||||
if [[ "$is_supported" == "true" ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Touch ID ${YELLOW}Not configured${NC} for sudo"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Touch ID ${YELLOW}Not configured${NC} for sudo"
|
||||
export TOUCHID_NOT_CONFIGURED=true
|
||||
fi
|
||||
fi
|
||||
@@ -31,7 +31,7 @@ check_rosetta() {
|
||||
if [[ -f "/Library/Apple/usr/share/rosetta/rosetta" ]]; then
|
||||
echo -e " ${GREEN}✓${NC} Rosetta 2 Installed"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} Rosetta 2 ${YELLOW}Not installed${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Rosetta 2 ${YELLOW}Not installed${NC}"
|
||||
export ROSETTA_NOT_INSTALLED=true
|
||||
fi
|
||||
fi
|
||||
@@ -46,7 +46,7 @@ check_git_config() {
|
||||
if [[ -n "$git_name" && -n "$git_email" ]]; then
|
||||
echo -e " ${GREEN}✓${NC} Git Config Configured"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} Git Config ${YELLOW}Not configured${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Git Config ${YELLOW}Not configured${NC}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ check_disk_space() {
|
||||
if [[ $free_num -lt 20 ]]; then
|
||||
echo -e " ${RED}✗${NC} Disk Space ${RED}${free_gb}GB free${NC} (Critical)"
|
||||
elif [[ $free_num -lt 50 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Disk Space ${YELLOW}${free_gb}GB free${NC} (Low)"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Disk Space ${YELLOW}${free_gb}GB free${NC} (Low)"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Disk Space ${free_gb}GB free"
|
||||
fi
|
||||
@@ -58,7 +58,7 @@ check_memory_usage() {
|
||||
if [[ $used_percent -gt 90 ]]; then
|
||||
echo -e " ${RED}✗${NC} Memory ${RED}${used_percent}% used${NC} (Critical)"
|
||||
elif [[ $used_percent -gt 80 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Memory ${YELLOW}${used_percent}% used${NC} (High)"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Memory ${YELLOW}${used_percent}% used${NC} (High)"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Memory ${used_percent}% used"
|
||||
fi
|
||||
@@ -86,7 +86,7 @@ check_login_items() {
|
||||
fi
|
||||
|
||||
if [[ $login_items_count -gt 15 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Login Items ${YELLOW}${login_items_count} apps${NC} auto-start (High)"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Login Items ${YELLOW}${login_items_count} apps${NC} auto-start (High)"
|
||||
elif [[ $login_items_count -gt 0 ]]; then
|
||||
echo -e " ${GREEN}✓${NC} Login Items ${login_items_count} apps auto-start"
|
||||
else
|
||||
@@ -151,9 +151,9 @@ check_cache_size() {
|
||||
local cache_size_int=$(echo "$cache_size_gb" | cut -d'.' -f1)
|
||||
|
||||
if [[ $cache_size_int -gt 10 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Cache Size ${YELLOW}${cache_size_gb}GB${NC} cleanable"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Cache Size ${YELLOW}${cache_size_gb}GB${NC} cleanable"
|
||||
elif [[ $cache_size_int -gt 5 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Cache Size ${YELLOW}${cache_size_gb}GB${NC} cleanable"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Cache Size ${YELLOW}${cache_size_gb}GB${NC} cleanable"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Cache Size ${cache_size_gb}GB"
|
||||
fi
|
||||
@@ -170,7 +170,7 @@ check_swap_usage() {
|
||||
if [[ "$swap_used" == *"G"* ]]; then
|
||||
local swap_gb=${swap_num%.*}
|
||||
if [[ $swap_gb -gt 2 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Swap Usage ${YELLOW}${swap_used}${NC} (High)"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Swap Usage ${YELLOW}${swap_used}${NC} (High)"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Swap Usage ${swap_used}"
|
||||
fi
|
||||
@@ -186,7 +186,7 @@ check_timemachine() {
|
||||
if command -v tmutil > /dev/null 2>&1; then
|
||||
local tm_status=$(tmutil latestbackup 2>/dev/null || echo "")
|
||||
if [[ -z "$tm_status" ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Time Machine No backups found"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Time Machine No backups found"
|
||||
echo -e " ${GRAY}Set up in System Settings → General → Time Machine (optional but recommended)${NC}"
|
||||
else
|
||||
# Get last backup time
|
||||
@@ -194,7 +194,7 @@ check_timemachine() {
|
||||
if [[ -n "$backup_date" ]]; then
|
||||
echo -e " ${GREEN}✓${NC} Time Machine Backup active"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} Time Machine Not configured"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Time Machine Not configured"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -220,7 +220,7 @@ check_brew_health() {
|
||||
else
|
||||
local warning_count=$(echo "$brew_doctor" | grep -c "Warning:" || echo "0")
|
||||
if [[ $warning_count -gt 0 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} Homebrew ${YELLOW}${warning_count} warnings${NC}"
|
||||
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
|
||||
|
||||
@@ -17,11 +17,12 @@ check_filevault() {
|
||||
|
||||
check_firewall() {
|
||||
# Check firewall status
|
||||
unset FIREWALL_DISABLED
|
||||
local firewall_status=$(defaults read /Library/Preferences/com.apple.alf globalstate 2>/dev/null || echo "0")
|
||||
if [[ "$firewall_status" == "1" || "$firewall_status" == "2" ]]; then
|
||||
echo -e " ${GREEN}✓${NC} Firewall Enabled"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} Firewall ${YELLOW}Disabled${NC} (Consider enabling)"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Firewall ${YELLOW}Disabled${NC} (Consider enabling)"
|
||||
echo -e " ${GRAY}System Settings → Network → Firewall, or run:${NC}"
|
||||
echo -e " ${GRAY}sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1${NC}"
|
||||
export FIREWALL_DISABLED=true
|
||||
@@ -34,10 +35,12 @@ check_gatekeeper() {
|
||||
local gk_status=$(spctl --status 2>/dev/null || echo "")
|
||||
if echo "$gk_status" | grep -q "enabled"; then
|
||||
echo -e " ${GREEN}✓${NC} Gatekeeper Active"
|
||||
unset GATEKEEPER_DISABLED
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} Gatekeeper ${YELLOW}Disabled${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Gatekeeper ${YELLOW}Disabled${NC}"
|
||||
echo -e " ${GRAY}Enable via System Settings → Privacy & Security, or:${NC}"
|
||||
echo -e " ${GRAY}sudo spctl --master-enable${NC}"
|
||||
export GATEKEEPER_DISABLED=true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -49,7 +52,7 @@ check_sip() {
|
||||
if echo "$sip_status" | grep -q "enabled"; then
|
||||
echo -e " ${GREEN}✓${NC} SIP Enabled"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} SIP ${YELLOW}Disabled${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} SIP ${YELLOW}Disabled${NC}"
|
||||
echo -e " ${GRAY}Restart into Recovery → Utilities → Terminal → run: csrutil enable${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -94,7 +94,7 @@ check_homebrew_updates() {
|
||||
elif [[ $cask_count -gt 0 ]]; then
|
||||
breakdown=" (${cask_count} cask)"
|
||||
fi
|
||||
echo -e " ${YELLOW}⚠${NC} Homebrew ${YELLOW}${total_count} updates${NC}${breakdown}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Homebrew ${YELLOW}${total_count} updates${NC}${breakdown}"
|
||||
echo -e " ${GRAY}Run: ${GREEN}brew upgrade${NC} ${GRAY}and/or${NC} ${GREEN}brew upgrade --cask${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Homebrew Up to date"
|
||||
@@ -134,9 +134,24 @@ get_software_updates() {
|
||||
}
|
||||
|
||||
check_appstore_updates() {
|
||||
local spinner_started=false
|
||||
if [[ -t 1 ]]; then
|
||||
printf " Checking App Store updates...\r"
|
||||
start_inline_spinner "Checking App Store updates..."
|
||||
spinner_started=true
|
||||
export SOFTWAREUPDATE_SPINNER_SHOWN="external"
|
||||
else
|
||||
echo "Checking App Store updates..."
|
||||
fi
|
||||
|
||||
local update_list=""
|
||||
update_list=$(get_software_updates | grep -v "Software Update Tool" | grep "^\*" | grep -vi "macOS" || echo "")
|
||||
|
||||
if [[ "$spinner_started" == "true" ]]; then
|
||||
stop_inline_spinner
|
||||
unset SOFTWAREUPDATE_SPINNER_SHOWN
|
||||
fi
|
||||
|
||||
local update_count=0
|
||||
if [[ -n "$update_list" ]]; then
|
||||
update_count=$(echo "$update_list" | wc -l | tr -d ' ')
|
||||
@@ -145,7 +160,7 @@ check_appstore_updates() {
|
||||
export APPSTORE_UPDATE_COUNT=$update_count
|
||||
|
||||
if [[ $update_count -gt 0 ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} App Store ${YELLOW}${update_count} apps${NC} need update"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} App Store ${YELLOW}${update_count} apps${NC} need update"
|
||||
echo -e " ${GRAY}Run: ${GREEN}softwareupdate -i <label>${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} App Store Up to date"
|
||||
@@ -153,19 +168,34 @@ check_appstore_updates() {
|
||||
}
|
||||
|
||||
check_macos_update() {
|
||||
local spinner_started=false
|
||||
if [[ -t 1 ]]; then
|
||||
printf " Checking macOS updates...\r"
|
||||
start_inline_spinner "Checking macOS updates..."
|
||||
spinner_started=true
|
||||
export SOFTWAREUPDATE_SPINNER_SHOWN="external"
|
||||
else
|
||||
echo "Checking macOS updates..."
|
||||
fi
|
||||
|
||||
# Check for macOS system update using cached list
|
||||
local macos_update=""
|
||||
macos_update=$(get_software_updates | grep -i "macOS" | head -1 || echo "")
|
||||
|
||||
if [[ "$spinner_started" == "true" ]]; then
|
||||
stop_inline_spinner
|
||||
unset SOFTWAREUPDATE_SPINNER_SHOWN
|
||||
fi
|
||||
|
||||
export MACOS_UPDATE_AVAILABLE="false"
|
||||
|
||||
if [[ -n "$macos_update" ]]; then
|
||||
export MACOS_UPDATE_AVAILABLE="true"
|
||||
local version=$(echo "$macos_update" | grep -o '[0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?' | head -1)
|
||||
if [[ -n "$version" ]]; then
|
||||
echo -e " ${YELLOW}⚠${NC} macOS ${YELLOW}${version} available${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} macOS ${YELLOW}${version} available${NC}"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠${NC} macOS ${YELLOW}Update available${NC}"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} macOS ${YELLOW}Update available${NC}"
|
||||
fi
|
||||
echo -e " ${GRAY}Run: ${GREEN}softwareupdate -i <label>${NC}"
|
||||
else
|
||||
@@ -220,7 +250,7 @@ check_mole_update() {
|
||||
# Compare versions
|
||||
if [[ "$(printf '%s\n' "$current_version" "$latest_version" | sort -V | head -1)" == "$current_version" ]]; then
|
||||
export MOLE_UPDATE_AVAILABLE="true"
|
||||
echo -e " ${YELLOW}⚠${NC} Mole ${YELLOW}${latest_version} available${NC} (current: ${current_version})"
|
||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Mole ${YELLOW}${latest_version} available${NC} (current: ${current_version})"
|
||||
echo -e " ${GRAY}Run: ${GREEN}mo update${NC}"
|
||||
else
|
||||
echo -e " ${GREEN}✓${NC} Mole Up to date (${current_version})"
|
||||
|
||||
103
lib/common.sh
103
lib/common.sh
@@ -356,6 +356,53 @@ drain_pending_input() {
|
||||
done
|
||||
}
|
||||
|
||||
# Shared timeout helper -------------------------------------------------------
|
||||
if [[ -z "${MO_TIMEOUT_INITIALIZED:-}" ]]; then
|
||||
MO_TIMEOUT_BIN=""
|
||||
for candidate in gtimeout timeout; do
|
||||
if command -v "$candidate" > /dev/null 2>&1; then
|
||||
MO_TIMEOUT_BIN="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
export MO_TIMEOUT_INITIALIZED=1
|
||||
fi
|
||||
|
||||
run_with_timeout() {
|
||||
local duration="${1:-0}"
|
||||
shift || true
|
||||
|
||||
if [[ ! "$duration" =~ ^[0-9]+$ ]]; then
|
||||
duration=0
|
||||
fi
|
||||
|
||||
if [[ "$duration" -le 0 ]]; then
|
||||
"$@"
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [[ -n "${MO_TIMEOUT_BIN:-}" ]]; then
|
||||
"$MO_TIMEOUT_BIN" "$duration" "$@"
|
||||
return $?
|
||||
fi
|
||||
|
||||
"$@" &
|
||||
local cmd_pid=$!
|
||||
local elapsed=0
|
||||
while kill -0 "$cmd_pid" 2> /dev/null; do
|
||||
if [[ $elapsed -ge $duration ]]; then
|
||||
kill -TERM "$cmd_pid" 2> /dev/null || true
|
||||
sleep 1
|
||||
kill -KILL "$cmd_pid" 2> /dev/null || true
|
||||
wait "$cmd_pid" 2> /dev/null || true
|
||||
return 124
|
||||
fi
|
||||
sleep 1
|
||||
((elapsed++))
|
||||
done
|
||||
wait "$cmd_pid"
|
||||
}
|
||||
|
||||
# Menu display helper
|
||||
show_menu_option() {
|
||||
local number="$1"
|
||||
@@ -594,35 +641,41 @@ request_sudo_access() {
|
||||
|
||||
[[ -z "$tty_path" ]] && return 1
|
||||
|
||||
local password=""
|
||||
local saved_stty=""
|
||||
if command -v stty > /dev/null 2>&1; then
|
||||
saved_stty=$(stty -g < "$tty_path" 2> /dev/null || echo "")
|
||||
stty -echo < "$tty_path" 2> /dev/null || true
|
||||
fi
|
||||
local attempts=0
|
||||
while ((attempts < 3)); do
|
||||
local password=""
|
||||
local saved_stty=""
|
||||
if command -v stty > /dev/null 2>&1; then
|
||||
saved_stty=$(stty -g < "$tty_path" 2> /dev/null || echo "")
|
||||
stty -echo < "$tty_path" 2> /dev/null || true
|
||||
fi
|
||||
|
||||
printf "${PURPLE}${ICON_ARROW}${NC} Enter admin password: " > "$tty_path" 2> /dev/null || true
|
||||
IFS= read -r password < "$tty_path" || password=""
|
||||
printf "\n" > "$tty_path" 2> /dev/null || true
|
||||
printf "${PURPLE}${ICON_ARROW}${NC} Enter admin password: " > "$tty_path" 2> /dev/null || true
|
||||
IFS= read -r password < "$tty_path" || password=""
|
||||
printf "\n" > "$tty_path" 2> /dev/null || true
|
||||
|
||||
if [[ -n "$saved_stty" ]]; then
|
||||
stty "$saved_stty" < "$tty_path" 2> /dev/null || stty echo < "$tty_path" 2> /dev/null || true
|
||||
else
|
||||
stty echo < "$tty_path" 2> /dev/null || true
|
||||
fi
|
||||
if [[ -n "$saved_stty" ]]; then
|
||||
stty "$saved_stty" < "$tty_path" 2> /dev/null || stty echo < "$tty_path" 2> /dev/null || true
|
||||
else
|
||||
stty echo < "$tty_path" 2> /dev/null || true
|
||||
fi
|
||||
|
||||
if [[ -z "$password" ]]; then
|
||||
unset password
|
||||
((attempts++))
|
||||
continue
|
||||
fi
|
||||
|
||||
if printf '%s\n' "$password" | "${sudo_stdin_cmd[@]}" > /dev/null 2>&1; then
|
||||
unset password
|
||||
sudo -n true 2> /dev/null || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "$password" ]]; then
|
||||
unset password
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf '%s\n' "$password" | "${sudo_stdin_cmd[@]}" > /dev/null 2>&1; then
|
||||
unset password
|
||||
sudo -n true 2> /dev/null || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
unset password
|
||||
((attempts++))
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Incorrect password, try again" > "$tty_path" 2> /dev/null || true
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,18 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly MAIL_DOWNLOADS_MIN_KB=5120 # ~5MB threshold
|
||||
|
||||
_opt_get_dir_size_kb() {
|
||||
local path="$1"
|
||||
[[ -e "$path" ]] || { echo 0; return; }
|
||||
du -sk "$path" 2> /dev/null | awk '{print $1}' || echo 0
|
||||
}
|
||||
|
||||
# System maintenance: rebuild databases and flush caches
|
||||
opt_system_maintenance() {
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Rebuilding LaunchServices database..."
|
||||
timeout 10 /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user > /dev/null 2>&1 || true
|
||||
run_with_timeout 10 /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user > /dev/null 2>&1 || true
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} LaunchServices database rebuilt"
|
||||
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Clearing DNS cache..."
|
||||
@@ -29,9 +37,30 @@ opt_system_maintenance() {
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} Font cache rebuilt"
|
||||
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Rebuilding Spotlight index (runs in background)..."
|
||||
# mdutil triggers background indexing - don't wait
|
||||
timeout 10 sudo mdutil -E / > /dev/null 2>&1 || true
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} Spotlight rebuild initiated"
|
||||
local md_status
|
||||
md_status=$(mdutil -s / 2> /dev/null || echo "")
|
||||
if echo "$md_status" | grep -qi "Indexing disabled"; then
|
||||
echo -e "${GRAY}-${NC} Spotlight indexing disabled, skipping rebuild"
|
||||
else
|
||||
# mdutil triggers background indexing - don't wait
|
||||
run_with_timeout 10 sudo mdutil -E / > /dev/null 2>&1 || true
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} Spotlight rebuild initiated"
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Refreshing Bluetooth services..."
|
||||
sudo pkill -f blued 2> /dev/null || true
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} Bluetooth controller refreshed"
|
||||
|
||||
if command -v log > /dev/null 2>&1 && [[ "${MO_ENABLE_LOG_CLEANUP:-0}" == "1" ]]; then
|
||||
echo -e "${BLUE}${ICON_ARROW}${NC} Compressing system logs..."
|
||||
if command -v has_sudo_session > /dev/null 2>&1 && ! has_sudo_session; then
|
||||
echo -e "${YELLOW}!${NC} Skipped log compression ${GRAY}(admin session inactive)${NC}"
|
||||
elif run_with_timeout 15 sudo -n log erase --all --force > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}${ICON_SUCCESS}${NC} logarchive trimmed"
|
||||
else
|
||||
echo -e "${YELLOW}!${NC} Skipped log compression ${GRAY}(requires Full Disk Access)${NC}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Cache refresh: update Finder/Safari caches
|
||||
@@ -68,19 +97,19 @@ opt_maintenance_scripts() {
|
||||
|
||||
# Run periodic scripts silently with timeout
|
||||
if [[ -x "$periodic_cmd" ]]; then
|
||||
if ! timeout 180 sudo "$periodic_cmd" daily weekly monthly > /dev/null 2>&1; then
|
||||
if ! run_with_timeout 180 sudo "$periodic_cmd" daily weekly monthly > /dev/null 2>&1; then
|
||||
success=false
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run newsyslog silently with timeout
|
||||
if ! timeout 120 sudo newsyslog > /dev/null 2>&1; then
|
||||
if ! run_with_timeout 120 sudo newsyslog > /dev/null 2>&1; then
|
||||
success=false
|
||||
fi
|
||||
|
||||
# Run repair_packages silently with timeout
|
||||
if [[ -x "/usr/libexec/repair_packages" ]]; then
|
||||
if ! timeout 180 sudo /usr/libexec/repair_packages --repair --standard-pkgs --volume / > /dev/null 2>&1; then
|
||||
if ! run_with_timeout 180 sudo /usr/libexec/repair_packages --repair --standard-pkgs --volume / > /dev/null 2>&1; then
|
||||
success=false
|
||||
fi
|
||||
fi
|
||||
@@ -162,6 +191,18 @@ opt_mail_downloads() {
|
||||
"$HOME/Library/Mail Downloads|Mail Downloads"
|
||||
"$HOME/Library/Containers/com.apple.mail/Data/Library/Mail Downloads|Mail Container Downloads"
|
||||
)
|
||||
|
||||
local total_kb=0
|
||||
for target in "${mail_dirs[@]}"; do
|
||||
IFS='|' read -r target_path _ <<< "$target"
|
||||
total_kb=$((total_kb + $(_opt_get_dir_size_kb "$target_path")))
|
||||
done
|
||||
|
||||
if [[ $total_kb -lt $MAIL_DOWNLOADS_MIN_KB ]]; then
|
||||
echo -e "${GRAY}-${NC} Only $(bytes_to_human $((total_kb * 1024))) detected, skipping cleanup"
|
||||
return
|
||||
fi
|
||||
|
||||
for target in "${mail_dirs[@]}"; do
|
||||
IFS='|' read -r target_path label <<< "$target"
|
||||
cleanup_path "$target_path" "$label"
|
||||
@@ -220,16 +261,16 @@ opt_startup_cache() {
|
||||
fi
|
||||
|
||||
if [[ "$macos_version" -ge 11 ]] || [[ "$(uname -m)" == "arm64" ]]; then
|
||||
if ! timeout 120 sudo kextcache -i / > /dev/null 2>&1; then
|
||||
if ! run_with_timeout 120 sudo kextcache -i / > /dev/null 2>&1; then
|
||||
success=false
|
||||
fi
|
||||
else
|
||||
if ! timeout 180 sudo kextcache -i / > /dev/null 2>&1; then
|
||||
if ! run_with_timeout 180 sudo kextcache -i / > /dev/null 2>&1; then
|
||||
success=false
|
||||
fi
|
||||
|
||||
sudo rm -rf /System/Library/PrelinkedKernels/* > /dev/null 2>&1 || true
|
||||
timeout 120 sudo kextcache -system-prelinked-kernel > /dev/null 2>&1 || true
|
||||
run_with_timeout 120 sudo kextcache -system-prelinked-kernel > /dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
@@ -262,7 +303,7 @@ opt_local_snapshots() {
|
||||
fi
|
||||
|
||||
local success=false
|
||||
if timeout 180 sudo tmutil thinlocalsnapshots / 9999999999 4 > /dev/null 2>&1; then
|
||||
if run_with_timeout 180 sudo tmutil thinlocalsnapshots / 9999999999 4 > /dev/null 2>&1; then
|
||||
success=true
|
||||
fi
|
||||
|
||||
|
||||
@@ -25,6 +25,17 @@ format_brew_update_label() {
|
||||
printf " • Homebrew %s" "$detail_str"
|
||||
}
|
||||
|
||||
brew_has_outdated() {
|
||||
local kind="${1:-formula}"
|
||||
command -v brew > /dev/null 2>&1 || return 1
|
||||
|
||||
if [[ "$kind" == "cask" ]]; then
|
||||
brew outdated --cask --quiet 2> /dev/null | grep -q .
|
||||
else
|
||||
brew outdated --quiet 2> /dev/null | grep -q .
|
||||
fi
|
||||
}
|
||||
|
||||
# Ask user if they want to update
|
||||
# Returns: 0 if yes, 1 if no
|
||||
ask_for_updates() {
|
||||
@@ -62,7 +73,7 @@ ask_for_updates() {
|
||||
echo -e "$item"
|
||||
done
|
||||
echo ""
|
||||
echo -ne "${YELLOW}Update all now?${NC} ${GRAY}Enter yes / ESC skip${NC}: "
|
||||
echo -ne "${YELLOW}Update all now?${NC} ${GRAY}Enter confirm / ESC cancel${NC}: "
|
||||
|
||||
local key
|
||||
if ! key=$(read_key); then
|
||||
@@ -124,28 +135,80 @@ perform_updates() {
|
||||
|
||||
# Update Homebrew formulae
|
||||
if ((brew_formula > 0)); then
|
||||
echo -e "${BLUE}Updating Homebrew formulae...${NC}"
|
||||
if brew upgrade 2>&1 | grep -v "^==>" | grep -v "^Warning:" || true; then
|
||||
echo -e "${GREEN}✓${NC} Homebrew formulae updated"
|
||||
reset_brew_cache
|
||||
((updated_count++))
|
||||
if ! brew_has_outdated "formula"; then
|
||||
echo -e "${GRAY}-${NC} Homebrew formulae already up to date"
|
||||
((total_count--))
|
||||
echo ""
|
||||
else
|
||||
echo -e "${RED}✗${NC} Homebrew formula update failed"
|
||||
echo -e "${BLUE}Updating Homebrew formulae...${NC}"
|
||||
local spinner_started=false
|
||||
if [[ -t 1 ]]; then
|
||||
start_inline_spinner "Running brew upgrade"
|
||||
spinner_started=true
|
||||
fi
|
||||
|
||||
local brew_output=""
|
||||
local brew_status=0
|
||||
if ! brew_output=$(brew upgrade 2>&1); then
|
||||
brew_status=$?
|
||||
fi
|
||||
|
||||
if [[ "$spinner_started" == "true" ]]; then
|
||||
stop_inline_spinner
|
||||
fi
|
||||
|
||||
local filtered_output
|
||||
filtered_output=$(echo "$brew_output" | grep -Ev "^(==>|Warning:)" || true)
|
||||
[[ -n "$filtered_output" ]] && echo "$filtered_output"
|
||||
|
||||
if [[ ${brew_status:-0} -eq 0 ]]; then
|
||||
echo -e "${GREEN}✓${NC} Homebrew formulae updated"
|
||||
reset_brew_cache
|
||||
((updated_count++))
|
||||
else
|
||||
echo -e "${RED}✗${NC} Homebrew formula update failed"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Update Homebrew casks
|
||||
if ((brew_cask > 0)); then
|
||||
echo -e "${BLUE}Updating Homebrew casks...${NC}"
|
||||
if brew upgrade --cask 2>&1 | grep -v "^==>" | grep -v "^Warning:" || true; then
|
||||
echo -e "${GREEN}✓${NC} Homebrew casks updated"
|
||||
reset_brew_cache
|
||||
((updated_count++))
|
||||
if ! brew_has_outdated "cask"; then
|
||||
echo -e "${GRAY}-${NC} Homebrew casks already up to date"
|
||||
((total_count--))
|
||||
echo ""
|
||||
else
|
||||
echo -e "${RED}✗${NC} Homebrew cask update failed"
|
||||
echo -e "${BLUE}Updating Homebrew casks...${NC}"
|
||||
local spinner_started=false
|
||||
if [[ -t 1 ]]; then
|
||||
start_inline_spinner "Running brew upgrade --cask"
|
||||
spinner_started=true
|
||||
fi
|
||||
|
||||
local brew_output=""
|
||||
local brew_status=0
|
||||
if ! brew_output=$(brew upgrade --cask 2>&1); then
|
||||
brew_status=$?
|
||||
fi
|
||||
|
||||
if [[ "$spinner_started" == "true" ]]; then
|
||||
stop_inline_spinner
|
||||
fi
|
||||
|
||||
local filtered_output
|
||||
filtered_output=$(echo "$brew_output" | grep -Ev "^(==>|Warning:)" || true)
|
||||
[[ -n "$filtered_output" ]] && echo "$filtered_output"
|
||||
|
||||
if [[ ${brew_status:-0} -eq 0 ]]; then
|
||||
echo -e "${GREEN}✓${NC} Homebrew casks updated"
|
||||
reset_brew_cache
|
||||
((updated_count++))
|
||||
else
|
||||
echo -e "${RED}✗${NC} Homebrew cask update failed"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Update App Store apps
|
||||
@@ -154,7 +217,7 @@ perform_updates() {
|
||||
# Check sudo access
|
||||
if ! has_sudo_session; then
|
||||
if ! ensure_sudo_session "Software updates require admin access"; then
|
||||
echo -e "${YELLOW}⚠${NC} Skipping App Store updates (admin authentication required)"
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Skipping App Store updates (admin authentication required)"
|
||||
echo ""
|
||||
((total_count--))
|
||||
if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
|
||||
@@ -171,7 +234,7 @@ perform_updates() {
|
||||
# Update macOS
|
||||
if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" && "$macos_handled_via_appstore" != "true" ]]; then
|
||||
if ! has_sudo_session; then
|
||||
echo -e "${YELLOW}⚠${NC} Skipping macOS updates (admin authentication required)"
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Skipping macOS updates (admin authentication required)"
|
||||
echo ""
|
||||
else
|
||||
_perform_macos_update
|
||||
@@ -260,7 +323,7 @@ _perform_macos_update() {
|
||||
fi
|
||||
|
||||
if grep -qi "restart" "$macos_log" 2>/dev/null; then
|
||||
echo -e "${YELLOW}⚠${NC} Restart required to complete update"
|
||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Restart required to complete update"
|
||||
fi
|
||||
|
||||
rm -f "$macos_log" 2>/dev/null || true
|
||||
|
||||
26
tests/optimization_tasks.bats
Normal file
26
tests/optimization_tasks.bats
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
setup_file() {
|
||||
PROJECT_ROOT="$(cd "${BATS_TEST_DIRNAME}/.." && pwd)"
|
||||
export PROJECT_ROOT
|
||||
}
|
||||
|
||||
@test "run_with_timeout succeeds without GNU timeout" {
|
||||
run bash --noprofile --norc -c '
|
||||
set -euo pipefail
|
||||
PATH="/usr/bin:/bin"
|
||||
source "'"$PROJECT_ROOT"'/lib/common.sh"
|
||||
run_with_timeout 1 sleep 0.1
|
||||
'
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "run_with_timeout enforces timeout and returns 124" {
|
||||
run bash --noprofile --norc -c '
|
||||
set -euo pipefail
|
||||
PATH="/usr/bin:/bin"
|
||||
source "'"$PROJECT_ROOT"'/lib/common.sh"
|
||||
run_with_timeout 1 sleep 5
|
||||
'
|
||||
[ "$status" -eq 124 ]
|
||||
}
|
||||
@@ -97,3 +97,20 @@ setup() {
|
||||
fi
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "mo clean --whitelist persists selections" {
|
||||
whitelist_file="$HOME/.config/mole/whitelist"
|
||||
mkdir -p "$(dirname "$whitelist_file")"
|
||||
|
||||
run bash --noprofile --norc -c "cd '$PROJECT_ROOT'; printf \$'\\n' | HOME='$HOME' ./mo clean --whitelist"
|
||||
[ "$status" -eq 0 ]
|
||||
grep -q "\\.m2/repository" "$whitelist_file"
|
||||
|
||||
run bash --noprofile --norc -c "cd '$PROJECT_ROOT'; printf \$' \\n' | HOME='$HOME' ./mo clean --whitelist"
|
||||
[ "$status" -eq 0 ]
|
||||
! grep -q "\\.m2/repository" "$whitelist_file"
|
||||
|
||||
run bash --noprofile --norc -c "cd '$PROJECT_ROOT'; printf \$'\\n' | HOME='$HOME' ./mo clean --whitelist"
|
||||
[ "$status" -eq 0 ]
|
||||
! grep -q "\\.m2/repository" "$whitelist_file"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user