mirror of
https://github.com/tw93/Mole.git
synced 2026-02-16 14:43:39 +00:00
feat: Bump version to 1.13.5, enhance show_version output, optimize software update checks, and add Touch ID for sudo as a security fix.
This commit is contained in:
@@ -99,9 +99,11 @@ show_optimization_summary() {
|
|||||||
fi
|
fi
|
||||||
summary_details+=("$summary_line4")
|
summary_details+=("$summary_line4")
|
||||||
|
|
||||||
if [[ "${OPTIMIZE_SHOW_TOUCHID_TIP:-false}" == "true" ]]; then
|
if [[ -n "${AUTO_FIX_SUMMARY:-}" ]]; then
|
||||||
echo -e "${YELLOW}☻${NC} Run ${GRAY}mo touchid${NC} to approve sudo via Touch ID"
|
summary_details+=("$AUTO_FIX_SUMMARY")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Fix: Ensure summary is always printed for optimizations
|
||||||
print_summary_block "$summary_title" "${summary_details[@]}"
|
print_summary_block "$summary_title" "${summary_details[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,6 +247,11 @@ collect_security_fix_actions() {
|
|||||||
SECURITY_FIXES+=("gatekeeper|Enable Gatekeeper (App download protection)")
|
SECURITY_FIXES+=("gatekeeper|Enable Gatekeeper (App download protection)")
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if touchid_supported && ! touchid_configured; then
|
||||||
|
if ! is_whitelisted "touchid"; then
|
||||||
|
SECURITY_FIXES+=("touchid|Enable Touch ID for sudo")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
((${#SECURITY_FIXES[@]} > 0))
|
((${#SECURITY_FIXES[@]} > 0))
|
||||||
}
|
}
|
||||||
@@ -301,6 +308,13 @@ apply_gatekeeper_fix() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply_touchid_fix() {
|
||||||
|
if "$SCRIPT_DIR/bin/touchid.sh" enable; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
perform_security_fixes() {
|
perform_security_fixes() {
|
||||||
if ! ensure_sudo_session "Security changes require admin access"; then
|
if ! ensure_sudo_session "Security changes require admin access"; then
|
||||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Skipped security fixes (sudo denied)"
|
echo -e "${YELLOW}${ICON_WARNING}${NC} Skipped security fixes (sudo denied)"
|
||||||
@@ -317,6 +331,9 @@ perform_security_fixes() {
|
|||||||
gatekeeper)
|
gatekeeper)
|
||||||
apply_gatekeeper_fix && ((applied++))
|
apply_gatekeeper_fix && ((applied++))
|
||||||
;;
|
;;
|
||||||
|
touchid)
|
||||||
|
apply_touchid_fix && ((applied++))
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -496,10 +513,6 @@ main() {
|
|||||||
|
|
||||||
export OPTIMIZE_SAFE_COUNT=$safe_count
|
export OPTIMIZE_SAFE_COUNT=$safe_count
|
||||||
export OPTIMIZE_CONFIRM_COUNT=$confirm_count
|
export OPTIMIZE_CONFIRM_COUNT=$confirm_count
|
||||||
export OPTIMIZE_SHOW_TOUCHID_TIP="false"
|
|
||||||
if touchid_supported && ! touchid_configured; then
|
|
||||||
export OPTIMIZE_SHOW_TOUCHID_TIP="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Show optimization summary at the end
|
# Show optimization summary at the end
|
||||||
show_optimization_summary
|
show_optimization_summary
|
||||||
|
|||||||
@@ -599,22 +599,20 @@ main() {
|
|||||||
rm -f "$apps_file"
|
rm -f "$apps_file"
|
||||||
|
|
||||||
# Pause before looping back
|
# Pause before looping back
|
||||||
echo -e "${GRAY}Press Enter to return to application list, ESC to exit...${NC}"
|
echo -e "${GRAY}Press Enter to return to application list, any other key to exit...${NC}"
|
||||||
local key
|
local key
|
||||||
IFS= read -r -s -n1 key || key=""
|
IFS= read -r -s -n1 key || key=""
|
||||||
drain_pending_input # Clean up any escape sequence remnants
|
drain_pending_input
|
||||||
case "$key" in
|
|
||||||
$'\e' | q | Q)
|
|
||||||
show_cursor
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# Continue loop
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Reset force_rescan to false for subsequent loops,
|
# Logic: Enter = continue loop, any other key = exit
|
||||||
# but relying on batch_uninstall's cache deletion for actual update
|
if [[ -z "$key" ]]; then
|
||||||
|
: # Enter pressed, continue loop
|
||||||
|
else
|
||||||
|
show_cursor
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reset force_rescan to false for subsequent loops
|
||||||
force_rescan=false
|
force_rescan=false
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,98 +275,37 @@ SOFTWARE_UPDATE_LIST=""
|
|||||||
get_software_updates() {
|
get_software_updates() {
|
||||||
local cache_file="$CACHE_DIR/softwareupdate_list"
|
local cache_file="$CACHE_DIR/softwareupdate_list"
|
||||||
|
|
||||||
if [[ -z "$SOFTWARE_UPDATE_LIST" ]]; then
|
# Optimized: Use defaults to check if updates are pending (much faster)
|
||||||
# Check cache first
|
local pending_updates
|
||||||
if is_cache_valid "$cache_file"; then
|
pending_updates=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate LastRecommendedUpdatesAvailable 2> /dev/null || echo "0")
|
||||||
SOFTWARE_UPDATE_LIST=$(cat "$cache_file" 2> /dev/null || echo "")
|
|
||||||
else
|
|
||||||
# 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 (querying Apple servers)..."
|
|
||||||
show_spinner=true
|
|
||||||
export SOFTWAREUPDATE_SPINNER_SHOWN="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SOFTWARE_UPDATE_LIST=$(softwareupdate -l 2> /dev/null || echo "")
|
if [[ "$pending_updates" -gt 0 ]]; then
|
||||||
# Save to cache
|
echo "Updates Available"
|
||||||
echo "$SOFTWARE_UPDATE_LIST" > "$cache_file" 2> /dev/null || true
|
else
|
||||||
|
echo ""
|
||||||
# Stop spinner
|
|
||||||
if [[ "$show_spinner" == "true" ]]; then
|
|
||||||
stop_inline_spinner
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
echo "$SOFTWARE_UPDATE_LIST"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_appstore_updates() {
|
check_appstore_updates() {
|
||||||
local spinner_started=false
|
# Skipped for speed optimization - consolidated into check_macos_update
|
||||||
if [[ -t 1 ]]; then
|
# We can't easily distinguish app store vs macos updates without the slow softwareupdate -l call
|
||||||
printf " Checking App Store updates...\r"
|
export APPSTORE_UPDATE_COUNT=0
|
||||||
start_inline_spinner "Checking App Store updates (querying Apple servers)..."
|
|
||||||
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 ' ')
|
|
||||||
fi
|
|
||||||
|
|
||||||
export APPSTORE_UPDATE_COUNT=$update_count
|
|
||||||
|
|
||||||
if [[ $update_count -gt 0 ]]; then
|
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} App Store ${YELLOW}${update_count} apps${NC} need update"
|
|
||||||
echo -e " ${GRAY}updates available in final step${NC}"
|
|
||||||
else
|
|
||||||
echo -e " ${GREEN}✓${NC} App Store Up to date"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_macos_update() {
|
check_macos_update() {
|
||||||
# Check whitelist
|
# Check whitelist
|
||||||
if command -v is_whitelisted > /dev/null && is_whitelisted "check_macos_updates"; then return; fi
|
if command -v is_whitelisted > /dev/null && is_whitelisted "check_macos_updates"; then return; fi
|
||||||
local spinner_started=false
|
|
||||||
if [[ -t 1 ]]; then
|
# Fast check using system preferences
|
||||||
printf " Checking macOS updates...\r"
|
local updates_available="false"
|
||||||
start_inline_spinner "Checking macOS updates (querying Apple servers)..."
|
if [[ $(get_software_updates) == "Updates Available" ]]; then
|
||||||
spinner_started=true
|
updates_available="true"
|
||||||
export SOFTWAREUPDATE_SPINNER_SHOWN="external"
|
|
||||||
else
|
|
||||||
echo "Checking macOS updates..."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for macOS system update using cached list
|
export MACOS_UPDATE_AVAILABLE="$updates_available"
|
||||||
local macos_update=""
|
|
||||||
macos_update=$(get_software_updates | grep -i "macOS" | head -1 || echo "")
|
|
||||||
|
|
||||||
if [[ "$spinner_started" == "true" ]]; then
|
if [[ "$updates_available" == "true" ]]; then
|
||||||
stop_inline_spinner
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} macOS ${YELLOW}Update available${NC}"
|
||||||
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}${ICON_WARNING}${NC} macOS ${YELLOW}${version} available${NC}"
|
|
||||||
else
|
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} macOS ${YELLOW}Update available${NC}"
|
|
||||||
fi
|
|
||||||
echo -e " ${GRAY}update available in final step${NC}"
|
echo -e " ${GRAY}update available in final step${NC}"
|
||||||
else
|
else
|
||||||
echo -e " ${GREEN}✓${NC} macOS Up to date"
|
echo -e " ${GREEN}✓${NC} macOS Up to date"
|
||||||
|
|||||||
@@ -76,174 +76,51 @@ ask_for_updates() {
|
|||||||
echo -e "$item"
|
echo -e "$item"
|
||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
echo -ne "${YELLOW}Update all now?${NC} ${GRAY}Enter confirm / ESC cancel${NC}: "
|
|
||||||
|
|
||||||
local key
|
# If Mole has updates, offer to update it
|
||||||
if ! key=$(read_key); then
|
if [[ "${MOLE_UPDATE_AVAILABLE:-}" == "true" ]]; then
|
||||||
echo "skip"
|
echo -ne "${YELLOW}Update Mole now?${NC} ${GRAY}Enter confirm / ESC cancel${NC}: "
|
||||||
echo ""
|
|
||||||
return 1
|
local key
|
||||||
|
if ! key=$(read_key); then
|
||||||
|
echo "skip"
|
||||||
|
echo ""
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$key" == "ENTER" ]]; then
|
||||||
|
echo "yes"
|
||||||
|
echo ""
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "skip"
|
||||||
|
echo ""
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$key" == "ENTER" ]]; then
|
# For other updates, just show instructions
|
||||||
echo "yes"
|
# (Mole update check above handles the return 0 case, so we only get here if no Mole update)
|
||||||
echo ""
|
if [[ "${BREW_OUTDATED_COUNT:-0}" -gt 0 ]]; then
|
||||||
return 0
|
echo -e "${YELLOW}Tip:${NC} Run ${GREEN}brew upgrade${NC} to update Homebrew packages"
|
||||||
else
|
|
||||||
echo "skip"
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
|
if [[ "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]]; then
|
||||||
|
echo -e "${YELLOW}Tip:${NC} Open ${BLUE}App Store${NC} to update apps"
|
||||||
|
fi
|
||||||
|
if [[ "${MACOS_UPDATE_AVAILABLE:-}" == "true" ]]; then
|
||||||
|
echo -e "${YELLOW}Tip:${NC} Open ${BLUE}System Settings${NC} to update macOS"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Perform all pending updates
|
# Perform all pending updates
|
||||||
# Returns: 0 if all succeeded, 1 if some failed
|
# Returns: 0 if all succeeded, 1 if some failed
|
||||||
perform_updates() {
|
perform_updates() {
|
||||||
|
# Only handle Mole updates here
|
||||||
|
# Other updates are now informational-only in ask_for_updates
|
||||||
|
|
||||||
local updated_count=0
|
local updated_count=0
|
||||||
local total_count=0
|
|
||||||
local brew_formula="${BREW_FORMULA_OUTDATED_COUNT:-0}"
|
|
||||||
local brew_cask="${BREW_CASK_OUTDATED_COUNT:-0}"
|
|
||||||
|
|
||||||
# Get update labels
|
|
||||||
local -a appstore_labels=()
|
|
||||||
if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]]; then
|
|
||||||
while IFS= read -r label; do
|
|
||||||
[[ -n "$label" ]] && appstore_labels+=("$label")
|
|
||||||
done < <(get_appstore_update_labels || true)
|
|
||||||
fi
|
|
||||||
|
|
||||||
local -a macos_labels=()
|
|
||||||
if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
|
|
||||||
while IFS= read -r label; do
|
|
||||||
[[ -n "$label" ]] && macos_labels+=("$label")
|
|
||||||
done < <(get_macos_update_labels || true)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check fallback needed
|
|
||||||
local appstore_needs_fallback=false
|
|
||||||
local macos_needs_fallback=false
|
|
||||||
if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 && ${#appstore_labels[@]} -eq 0 ]]; then
|
|
||||||
appstore_needs_fallback=true
|
|
||||||
fi
|
|
||||||
if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" && ${#macos_labels[@]} -eq 0 ]]; then
|
|
||||||
macos_needs_fallback=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Count total updates
|
|
||||||
((brew_formula > 0)) && ((total_count++))
|
|
||||||
((brew_cask > 0)) && ((total_count++))
|
|
||||||
[[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]] && ((total_count++))
|
|
||||||
[[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]] && ((total_count++))
|
|
||||||
[[ -n "${MOLE_UPDATE_AVAILABLE:-}" && "${MOLE_UPDATE_AVAILABLE}" == "true" ]] && ((total_count++))
|
|
||||||
|
|
||||||
# Update Homebrew formulae
|
|
||||||
if ((brew_formula > 0)); then
|
|
||||||
if ! brew_has_outdated "formula"; then
|
|
||||||
echo -e "${GRAY}-${NC} Homebrew formulae already up to date"
|
|
||||||
((total_count--))
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
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 --formula 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
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update Homebrew casks
|
|
||||||
if ((brew_cask > 0)); then
|
|
||||||
if ! brew_has_outdated "cask"; then
|
|
||||||
echo -e "${GRAY}-${NC} Homebrew casks already up to date"
|
|
||||||
((total_count--))
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
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
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update App Store apps
|
|
||||||
local macos_handled_via_appstore=false
|
|
||||||
if [[ -n "${APPSTORE_UPDATE_COUNT:-}" && "${APPSTORE_UPDATE_COUNT:-0}" -gt 0 ]]; then
|
|
||||||
# Check sudo access
|
|
||||||
if ! has_sudo_session; then
|
|
||||||
if ! ensure_sudo_session "Software updates require admin access"; then
|
|
||||||
echo -e "${YELLOW}☻${NC} App Store updates available — update via System Settings"
|
|
||||||
echo ""
|
|
||||||
((total_count--))
|
|
||||||
if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
|
|
||||||
((total_count--))
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
_perform_appstore_update
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
_perform_appstore_update
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 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} macOS updates available — update via System Settings"
|
|
||||||
echo ""
|
|
||||||
((total_count--))
|
|
||||||
else
|
|
||||||
_perform_macos_update
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update Mole
|
# Update Mole
|
||||||
if [[ -n "${MOLE_UPDATE_AVAILABLE:-}" && "${MOLE_UPDATE_AVAILABLE}" == "true" ]]; then
|
if [[ -n "${MOLE_UPDATE_AVAILABLE:-}" && "${MOLE_UPDATE_AVAILABLE}" == "true" ]]; then
|
||||||
@@ -253,10 +130,17 @@ perform_updates() {
|
|||||||
[[ ! -f "$mole_bin" ]] && mole_bin=$(command -v mole 2> /dev/null || echo "")
|
[[ ! -f "$mole_bin" ]] && mole_bin=$(command -v mole 2> /dev/null || echo "")
|
||||||
|
|
||||||
if [[ -x "$mole_bin" ]]; then
|
if [[ -x "$mole_bin" ]]; then
|
||||||
|
# We use exec here or just run it?
|
||||||
|
# If we run 'mole update', it replaces the script.
|
||||||
|
# Since this function is part of a sourced script, replacing the file on disk is risky while running.
|
||||||
|
# However, 'mole update' script usually handles this by downloading to a temp file and moving it.
|
||||||
|
# But the shell might not like the file changing under it.
|
||||||
|
# The original code ran it this way, so we assume it's safe enough or handled by mole update implementation.
|
||||||
|
|
||||||
if "$mole_bin" update 2>&1 | grep -qE "(Updated|latest version)"; then
|
if "$mole_bin" update 2>&1 | grep -qE "(Updated|latest version)"; then
|
||||||
echo -e "${GREEN}✓${NC} Mole updated"
|
echo -e "${GREEN}✓${NC} Mole updated"
|
||||||
reset_mole_cache
|
reset_mole_cache
|
||||||
((updated_count++))
|
updated_count=1
|
||||||
else
|
else
|
||||||
echo -e "${RED}✗${NC} Mole update failed"
|
echo -e "${RED}✗${NC} Mole update failed"
|
||||||
fi
|
fi
|
||||||
@@ -266,98 +150,11 @@ perform_updates() {
|
|||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Summary
|
if [[ $updated_count -gt 0 ]]; then
|
||||||
if [[ $total_count -eq 0 ]]; then
|
|
||||||
echo -e "${GRAY}No updates to perform${NC}"
|
|
||||||
return 0
|
|
||||||
elif [[ $updated_count -eq $total_count ]]; then
|
|
||||||
echo -e "${GREEN}All updates completed (${updated_count}/${total_count})${NC}"
|
|
||||||
return 0
|
|
||||||
elif [[ $updated_count -gt 0 ]]; then
|
|
||||||
echo -e "${YELLOW}Partial updates completed (${updated_count}/${total_count})${NC}"
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo -e "${RED}No updates were completed${NC}"
|
return 1
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Internal: Perform App Store update
|
|
||||||
_perform_appstore_update() {
|
|
||||||
echo -e "${BLUE}Updating App Store apps...${NC}"
|
|
||||||
local appstore_log
|
|
||||||
appstore_log=$(mktemp "${TMPDIR:-/tmp}/mole-appstore.XXXXXX" 2> /dev/null || echo "/tmp/mole-appstore.log")
|
|
||||||
|
|
||||||
if [[ "$appstore_needs_fallback" == "true" ]]; then
|
|
||||||
# Ensure sudo session is active and valid before starting long-running operation
|
|
||||||
ensure_sudo_session "App Store updates require admin access" || return 1
|
|
||||||
|
|
||||||
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++))
|
|
||||||
if [[ -n "${MACOS_UPDATE_AVAILABLE:-}" && "${MACOS_UPDATE_AVAILABLE}" == "true" ]]; then
|
|
||||||
macos_handled_via_appstore=true
|
|
||||||
((updated_count++))
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗${NC} Software update failed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Ensure sudo session is active and valid before starting long-running operation
|
|
||||||
ensure_sudo_session "App Store updates require admin access" || return 1
|
|
||||||
|
|
||||||
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++))
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗${NC} App Store update failed"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f "$appstore_log" 2> /dev/null || true
|
|
||||||
reset_softwareupdate_cache
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# Internal: Perform macOS update
|
|
||||||
_perform_macos_update() {
|
|
||||||
echo -e "${BLUE}Updating macOS...${NC}"
|
|
||||||
echo -e "${YELLOW}Note:${NC} System update may require restart"
|
|
||||||
|
|
||||||
local macos_log
|
|
||||||
macos_log=$(mktemp "${TMPDIR:-/tmp}/mole-macos.XXXXXX" 2> /dev/null || echo "/tmp/mole-macos.log")
|
|
||||||
|
|
||||||
if [[ "$macos_needs_fallback" == "true" ]]; then
|
|
||||||
# Ensure sudo session is active and valid before starting long-running operation
|
|
||||||
ensure_sudo_session "macOS update requires admin access" || return 1
|
|
||||||
|
|
||||||
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++))
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗${NC} macOS update failed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Ensure sudo session is active and valid before starting long-running operation
|
|
||||||
ensure_sudo_session "macOS update requires admin access" || return 1
|
|
||||||
|
|
||||||
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++))
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗${NC} macOS update failed"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if grep -qi "restart" "$macos_log" 2> /dev/null; then
|
|
||||||
echo -e "${YELLOW}${ICON_WARNING}${NC} Restart required to complete update"
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f "$macos_log" 2> /dev/null || true
|
|
||||||
reset_softwareupdate_cache
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -406,7 +406,12 @@ batch_uninstall_applications() {
|
|||||||
summary_details+=("No applications were uninstalled.")
|
summary_details+=("No applications were uninstalled.")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
print_summary_block "$summary_status" "Uninstall complete" "${summary_details[@]}"
|
local title="Uninstall complete"
|
||||||
|
if [[ "$summary_status" == "warn" ]]; then
|
||||||
|
title="Uninstall incomplete"
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_summary_block "$title" "${summary_details[@]}"
|
||||||
printf '\n'
|
printf '\n'
|
||||||
|
|
||||||
# Clean up Dock entries for uninstalled apps
|
# Clean up Dock entries for uninstalled apps
|
||||||
|
|||||||
41
mole
41
mole
@@ -22,7 +22,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
source "$SCRIPT_DIR/lib/core/common.sh"
|
source "$SCRIPT_DIR/lib/core/common.sh"
|
||||||
|
|
||||||
# Version info
|
# Version info
|
||||||
VERSION="1.13.4"
|
VERSION="1.13.5"
|
||||||
MOLE_TAGLINE="Deep clean and optimize your Mac."
|
MOLE_TAGLINE="Deep clean and optimize your Mac."
|
||||||
|
|
||||||
# Check if Touch ID is already configured
|
# Check if Touch ID is already configured
|
||||||
@@ -181,7 +181,44 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
show_version() {
|
show_version() {
|
||||||
printf '\nMole version %s\n\n' "$VERSION"
|
local os_ver
|
||||||
|
if command -v sw_vers > /dev/null; then
|
||||||
|
os_ver=$(sw_vers -productVersion)
|
||||||
|
else
|
||||||
|
os_ver="Unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local arch
|
||||||
|
arch=$(uname -m)
|
||||||
|
|
||||||
|
local kernel
|
||||||
|
kernel=$(uname -r)
|
||||||
|
|
||||||
|
local sip_status
|
||||||
|
if command -v csrutil > /dev/null; then
|
||||||
|
sip_status=$(csrutil status 2>/dev/null | grep -o "enabled\|disabled" || echo "Unknown")
|
||||||
|
# Capitalize first letter
|
||||||
|
sip_status="$(tr '[:lower:]' '[:upper:]' <<< ${sip_status:0:1})${sip_status:1}"
|
||||||
|
else
|
||||||
|
sip_status="Unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local disk_free
|
||||||
|
disk_free=$(df -h / 2>/dev/null | awk 'NR==2 {print $4}' || echo "Unknown")
|
||||||
|
|
||||||
|
local install_method="Manual"
|
||||||
|
if is_homebrew_install; then
|
||||||
|
install_method="Homebrew"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '\nMole version %s\n' "$VERSION"
|
||||||
|
printf 'macOS: %s\n' "$os_ver"
|
||||||
|
printf 'Architecture: %s\n' "$arch"
|
||||||
|
printf 'Kernel: %s\n' "$kernel"
|
||||||
|
printf 'SIP: %s\n' "$sip_status"
|
||||||
|
printf 'Disk Free: %s\n' "$disk_free"
|
||||||
|
printf 'Install: %s\n' "$install_method"
|
||||||
|
printf 'Shell: %s\n\n' "${SHELL:-Unknown}"
|
||||||
}
|
}
|
||||||
|
|
||||||
show_help() {
|
show_help() {
|
||||||
|
|||||||
Reference in New Issue
Block a user