1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-11 17:03:59 +00:00

Fix unable to uninstall data-protected apps like Clash Party

Previously, apps matching DATA_PROTECTED_BUNDLES patterns (VPNs, dev tools, etc.)
could not be uninstalled because should_protect_path blocked their deletion.
Now use MOLE_UNINSTALL_MODE to distinguish between cleanup and explicit uninstall,
allowing users to remove these apps when they choose to while still protecting
their data during normal cleanup operations.

Also allow deletion of installer receipts in /private/var/db/receipts/.
This commit is contained in:
Tw93
2026-01-20 11:53:45 +08:00
parent 6d041a22e1
commit d044b2876e
3 changed files with 37 additions and 12 deletions

View File

@@ -493,6 +493,9 @@ should_protect_data() {
# Check if a path is protected from deletion # Check if a path is protected from deletion
# Centralized logic to protect system settings, control center, and critical apps # Centralized logic to protect system settings, control center, and critical apps
# #
# In uninstall mode (MOLE_UNINSTALL_MODE=1), only system-critical components are protected.
# Data-protected apps (VPNs, dev tools, etc.) can be uninstalled when user explicitly chooses to.
#
# Args: $1 - path to check # Args: $1 - path to check
# Returns: 0 if protected, 1 if safe to delete # Returns: 0 if protected, 1 if safe to delete
should_protect_path() { should_protect_path() {
@@ -577,17 +580,31 @@ should_protect_path() {
# 6. Match full path against protected patterns # 6. Match full path against protected patterns
# This catches things like /Users/tw93/Library/Caches/Claude when pattern is *Claude* # This catches things like /Users/tw93/Library/Caches/Claude when pattern is *Claude*
for pattern in "${SYSTEM_CRITICAL_BUNDLES[@]}" "${DATA_PROTECTED_BUNDLES[@]}"; do # In uninstall mode, only check system-critical bundles (user explicitly chose to uninstall)
if bundle_matches_pattern "$path" "$pattern"; then if [[ "${MOLE_UNINSTALL_MODE:-0}" == "1" ]]; then
return 0 # Uninstall mode: only protect system-critical components
fi for pattern in "${SYSTEM_CRITICAL_BUNDLES[@]}"; do
done if bundle_matches_pattern "$path" "$pattern"; then
return 0
fi
done
else
# Normal mode (cleanup): protect both system-critical and data-protected bundles
for pattern in "${SYSTEM_CRITICAL_BUNDLES[@]}" "${DATA_PROTECTED_BUNDLES[@]}"; do
if bundle_matches_pattern "$path" "$pattern"; then
return 0
fi
done
fi
# 7. Check if the filename itself matches any protected patterns # 7. Check if the filename itself matches any protected patterns
local filename # Skip in uninstall mode - user explicitly chose to remove this app
filename=$(basename "$path") if [[ "${MOLE_UNINSTALL_MODE:-0}" != "1" ]]; then
if should_protect_data "$filename"; then local filename
return 0 filename=$(basename "$path")
if should_protect_data "$filename"; then
return 0
fi
fi fi
return 1 return 1

View File

@@ -102,7 +102,8 @@ validate_path_for_deletion() {
/private/var/db/diagnostics | /private/var/db/diagnostics/* | \ /private/var/db/diagnostics | /private/var/db/diagnostics/* | \
/private/var/db/DiagnosticPipeline | /private/var/db/DiagnosticPipeline/* | \ /private/var/db/DiagnosticPipeline | /private/var/db/DiagnosticPipeline/* | \
/private/var/db/powerlog | /private/var/db/powerlog/* | \ /private/var/db/powerlog | /private/var/db/powerlog/* | \
/private/var/db/reportmemoryexception | /private/var/db/reportmemoryexception/*) /private/var/db/reportmemoryexception | /private/var/db/reportmemoryexception/* | \
/private/var/db/receipts/*.bom | /private/var/db/receipts/*.plist)
return 0 return 0
;; ;;
esac esac

View File

@@ -169,8 +169,8 @@ remove_file_list() {
batch_uninstall_applications() { batch_uninstall_applications() {
local total_size_freed=0 local total_size_freed=0
# Trap to clean up spinner on interrupt # Trap to clean up spinner and uninstall mode on interrupt
trap 'stop_inline_spinner 2>/dev/null; echo ""; return 130' INT TERM trap 'stop_inline_spinner 2>/dev/null; unset MOLE_UNINSTALL_MODE; echo ""; return 130' INT TERM
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if [[ ${#selected_apps[@]} -eq 0 ]]; then if [[ ${#selected_apps[@]} -eq 0 ]]; then
@@ -360,6 +360,10 @@ batch_uninstall_applications() {
;; ;;
esac esac
# Enable uninstall mode - allows deletion of data-protected apps (VPNs, dev tools, etc.)
# that user explicitly chose to uninstall. System-critical components remain protected.
export MOLE_UNINSTALL_MODE=1
# Request sudo if needed. # Request sudo if needed.
if [[ ${#sudo_apps[@]} -gt 0 ]]; then if [[ ${#sudo_apps[@]} -gt 0 ]]; then
if ! sudo -n true 2> /dev/null; then if ! sudo -n true 2> /dev/null; then
@@ -635,6 +639,9 @@ batch_uninstall_applications() {
sudo_keepalive_pid="" sudo_keepalive_pid=""
fi fi
# Disable uninstall mode
unset MOLE_UNINSTALL_MODE
# Invalidate cache if any apps were successfully uninstalled. # Invalidate cache if any apps were successfully uninstalled.
if [[ $success_count -gt 0 ]]; then if [[ $success_count -gt 0 ]]; then
local cache_file="$HOME/.cache/mole/app_scan_cache" local cache_file="$HOME/.cache/mole/app_scan_cache"