mirror of
https://github.com/tw93/Mole.git
synced 2026-02-11 12:59:16 +00:00
Fix the problems in pr
This commit is contained in:
@@ -1,124 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Maintenance Cleanup Module
|
# Maintenance Cleanup Module
|
||||||
# Universal binary slimming, broken preferences, broken login items
|
# Broken preferences and broken login items cleanup
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# Universal Binary Slimming
|
|
||||||
# Remove unused architecture code from universal binaries
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
# Slim universal binaries to current architecture only
|
|
||||||
# Only processes apps in /Applications, skips signed/notarized apps
|
|
||||||
# Env: DRY_RUN
|
|
||||||
# Globals: files_cleaned, total_size_cleaned, total_items (modified)
|
|
||||||
clean_universal_binaries() {
|
|
||||||
# Only run on Apple Silicon (most benefit)
|
|
||||||
if [[ "$(uname -m)" != "arm64" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if lipo is available
|
|
||||||
if ! command -v lipo > /dev/null 2>&1; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local current_arch="arm64"
|
|
||||||
local remove_arch="x86_64"
|
|
||||||
local total_saved_kb=0
|
|
||||||
local apps_slimmed=0
|
|
||||||
local max_apps=50 # Limit to prevent long runs
|
|
||||||
|
|
||||||
if [[ -t 1 ]]; then
|
|
||||||
MOLE_SPINNER_PREFIX=" " start_inline_spinner "Scanning universal binaries..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
local app_count=0
|
|
||||||
while IFS= read -r app_path; do
|
|
||||||
[[ -d "$app_path" ]] || continue
|
|
||||||
|
|
||||||
((app_count++))
|
|
||||||
if [[ $app_count -gt $max_apps ]]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
|
|
||||||
local binary_path="$app_path/Contents/MacOS"
|
|
||||||
[[ -d "$binary_path" ]] || continue
|
|
||||||
|
|
||||||
# Get the main executable
|
|
||||||
local info_plist="$app_path/Contents/Info.plist"
|
|
||||||
[[ -f "$info_plist" ]] || continue
|
|
||||||
|
|
||||||
local exec_name
|
|
||||||
exec_name=$(defaults read "$info_plist" CFBundleExecutable 2> /dev/null || echo "")
|
|
||||||
[[ -z "$exec_name" ]] && continue
|
|
||||||
|
|
||||||
local exec_path="$binary_path/$exec_name"
|
|
||||||
[[ -f "$exec_path" ]] || continue
|
|
||||||
|
|
||||||
# Check if it's a universal binary with both architectures
|
|
||||||
local archs
|
|
||||||
archs=$(lipo -archs "$exec_path" 2> /dev/null || echo "")
|
|
||||||
if [[ "$archs" != *"$current_arch"* ]] || [[ "$archs" != *"$remove_arch"* ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Skip if app is code signed (removing arch breaks signature)
|
|
||||||
if codesign -v "$app_path" 2> /dev/null; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Calculate size before
|
|
||||||
local size_before
|
|
||||||
size_before=$(du -sk "$exec_path" 2> /dev/null | awk '{print $1}' || echo "0")
|
|
||||||
|
|
||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
|
||||||
# Create backup and slim
|
|
||||||
local backup_path="${exec_path}.universal.bak"
|
|
||||||
if cp "$exec_path" "$backup_path" 2> /dev/null; then
|
|
||||||
if lipo "$backup_path" -remove "$remove_arch" -output "$exec_path" 2> /dev/null; then
|
|
||||||
rm -f "$backup_path"
|
|
||||||
local size_after
|
|
||||||
size_after=$(du -sk "$exec_path" 2> /dev/null | awk '{print $1}' || echo "0")
|
|
||||||
local saved=$((size_before - size_after))
|
|
||||||
if [[ $saved -gt 0 ]]; then
|
|
||||||
((total_saved_kb += saved))
|
|
||||||
((apps_slimmed++))
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Restore backup on failure
|
|
||||||
mv "$backup_path" "$exec_path" 2> /dev/null || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Dry run: estimate savings (roughly 40-50% of binary size)
|
|
||||||
local estimated_save=$((size_before / 2))
|
|
||||||
((total_saved_kb += estimated_save))
|
|
||||||
((apps_slimmed++))
|
|
||||||
fi
|
|
||||||
done < <(find /Applications -maxdepth 2 -type d -name "*.app" 2> /dev/null || true)
|
|
||||||
|
|
||||||
if [[ -t 1 ]]; then
|
|
||||||
stop_inline_spinner
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $apps_slimmed -gt 0 && $total_saved_kb -gt 1024 ]]; then
|
|
||||||
local saved_human
|
|
||||||
saved_human=$(bytes_to_human "$((total_saved_kb * 1024))")
|
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
|
||||||
echo -e " ${YELLOW}→${NC} Universal binaries: $apps_slimmed apps ${YELLOW}(~$saved_human dry)${NC}"
|
|
||||||
else
|
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Slimmed $apps_slimmed apps ${GREEN}($saved_human)${NC}"
|
|
||||||
fi
|
|
||||||
# Update global statistics
|
|
||||||
((files_cleaned += apps_slimmed))
|
|
||||||
((total_size_cleaned += total_saved_kb))
|
|
||||||
((total_items++))
|
|
||||||
note_activity
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Broken Preferences Detection and Cleanup
|
# Broken Preferences Detection and Cleanup
|
||||||
# Find and remove corrupted .plist files
|
# Find and remove corrupted .plist files
|
||||||
@@ -243,13 +128,13 @@ clean_broken_login_items() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Extract Program or ProgramArguments[0] from plist
|
# Extract Program or ProgramArguments[0] from plist using plutil
|
||||||
local program=""
|
local program=""
|
||||||
program=$(defaults read "$plist_file" Program 2> /dev/null || echo "")
|
program=$(plutil -extract Program raw "$plist_file" 2> /dev/null || echo "")
|
||||||
|
|
||||||
if [[ -z "$program" ]]; then
|
if [[ -z "$program" ]]; then
|
||||||
# Try ProgramArguments array
|
# Try ProgramArguments array (first element)
|
||||||
program=$(defaults read "$plist_file" ProgramArguments 2> /dev/null | head -2 | tail -1 | sed 's/^[[:space:]]*"//' | sed 's/".*$//' || echo "")
|
program=$(plutil -extract ProgramArguments.0 raw "$plist_file" 2> /dev/null || echo "")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Skip if no program found or program exists
|
# Skip if no program found or program exists
|
||||||
@@ -295,8 +180,4 @@ clean_broken_login_items() {
|
|||||||
clean_maintenance() {
|
clean_maintenance() {
|
||||||
clean_broken_preferences
|
clean_broken_preferences
|
||||||
clean_broken_login_items
|
clean_broken_login_items
|
||||||
# Universal binary slimming is risky, only run if explicitly enabled
|
|
||||||
if [[ "${MOLE_SLIM_BINARIES:-false}" == "true" ]]; then
|
|
||||||
clean_universal_binaries
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|||||||
29
lib/clean_user_apps.sh
Executable file → Normal file
29
lib/clean_user_apps.sh
Executable file → Normal file
@@ -95,21 +95,30 @@ clean_productivity_apps() {
|
|||||||
# Note: Spotify cache is protected by default (may contain offline music)
|
# Note: Spotify cache is protected by default (may contain offline music)
|
||||||
# Users can override via whitelist settings
|
# Users can override via whitelist settings
|
||||||
clean_media_players() {
|
clean_media_players() {
|
||||||
# Spotify cache protection: skip if has offline music (>500MB cache)
|
# Spotify cache protection: check for offline music indicators
|
||||||
local spotify_cache="$HOME/Library/Caches/com.spotify.client"
|
local spotify_cache="$HOME/Library/Caches/com.spotify.client"
|
||||||
if [[ -d "$spotify_cache" ]]; then
|
local spotify_data="$HOME/Library/Application Support/Spotify"
|
||||||
|
local has_offline_music=false
|
||||||
|
|
||||||
|
# Check for offline music database or large cache (>500MB)
|
||||||
|
if [[ -f "$spotify_data/PersistentCache/Storage/offline.bnk" ]] || \
|
||||||
|
[[ -d "$spotify_data/PersistentCache/Storage" && -n "$(find "$spotify_data/PersistentCache/Storage" -type f -name "*.file" 2>/dev/null | head -1)" ]]; then
|
||||||
|
has_offline_music=true
|
||||||
|
elif [[ -d "$spotify_cache" ]]; then
|
||||||
local cache_size_kb
|
local cache_size_kb
|
||||||
cache_size_kb=$(du -sk "$spotify_cache" 2> /dev/null | awk '{print $1}' || echo "0")
|
cache_size_kb=$(du -sk "$spotify_cache" 2> /dev/null | awk '{print $1}' || echo "0")
|
||||||
# Only clean if cache is small (<500MB, unlikely to have offline music)
|
# Large cache (>500MB) likely contains offline music
|
||||||
if [[ $cache_size_kb -lt 512000 ]]; then
|
if [[ $cache_size_kb -ge 512000 ]]; then
|
||||||
safe_clean ~/Library/Caches/com.spotify.client/* "Spotify cache"
|
has_offline_music=true
|
||||||
else
|
|
||||||
local cache_human
|
|
||||||
cache_human=$(bytes_to_human "$((cache_size_kb * 1024))")
|
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Spotify cache protected ($cache_human, may contain offline music)"
|
|
||||||
note_activity
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$has_offline_music" == "true" ]]; then
|
||||||
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Spotify cache protected (offline music detected)"
|
||||||
|
note_activity
|
||||||
|
else
|
||||||
|
safe_clean ~/Library/Caches/com.spotify.client/* "Spotify cache"
|
||||||
|
fi
|
||||||
safe_clean ~/Library/Caches/com.apple.Music "Apple Music cache"
|
safe_clean ~/Library/Caches/com.apple.Music "Apple Music cache"
|
||||||
safe_clean ~/Library/Caches/com.apple.podcasts "Apple Podcasts cache"
|
safe_clean ~/Library/Caches/com.apple.podcasts "Apple Podcasts cache"
|
||||||
safe_clean ~/Library/Caches/com.apple.TV/* "Apple TV cache"
|
safe_clean ~/Library/Caches/com.apple.TV/* "Apple TV cache"
|
||||||
|
|||||||
28
lib/clean_user_data.sh
Executable file → Normal file
28
lib/clean_user_data.sh
Executable file → Normal file
@@ -103,26 +103,16 @@ clean_sandboxed_app_caches() {
|
|||||||
clean_browsers() {
|
clean_browsers() {
|
||||||
# Check for running browsers and warn user
|
# Check for running browsers and warn user
|
||||||
local running_browsers=""
|
local running_browsers=""
|
||||||
local -a browser_checks=(
|
|
||||||
"Safari"
|
|
||||||
"Google Chrome"
|
|
||||||
"Firefox"
|
|
||||||
"Microsoft Edge"
|
|
||||||
"Brave Browser"
|
|
||||||
"Arc"
|
|
||||||
"Opera"
|
|
||||||
"Vivaldi"
|
|
||||||
)
|
|
||||||
|
|
||||||
for browser in "${browser_checks[@]}"; do
|
# Check each browser with case-insensitive process name matching
|
||||||
if pgrep -x "$browser" > /dev/null 2>&1; then
|
pgrep -i "safari" > /dev/null 2>&1 && running_browsers="Safari"
|
||||||
if [[ -z "$running_browsers" ]]; then
|
pgrep -i "chrome" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Chrome"
|
||||||
running_browsers="$browser"
|
pgrep -i "firefox" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Firefox"
|
||||||
else
|
pgrep -i "edge" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Edge"
|
||||||
running_browsers="$running_browsers, $browser"
|
pgrep -i "brave" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Brave"
|
||||||
fi
|
pgrep -i "arc" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Arc"
|
||||||
fi
|
pgrep -i "opera" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Opera"
|
||||||
done
|
pgrep -i "vivaldi" > /dev/null 2>&1 && running_browsers="${running_browsers:+$running_browsers, }Vivaldi"
|
||||||
|
|
||||||
if [[ -n "$running_browsers" ]]; then
|
if [[ -n "$running_browsers" ]]; then
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Running: $running_browsers (some files may be locked)"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Running: $running_browsers (some files may be locked)"
|
||||||
|
|||||||
Reference in New Issue
Block a user