1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 16:49:41 +00:00

feat: enhance uninstall with launch items and login items cleanup

- Add automatic cleanup of LaunchAgents/Daemons (Issue #315)
- Support both system and user-level launch paths
- Add Login Items cleanup (fixing broken entries like CodexBar)
- Improve Homebrew uninstall logging visibility
- Update security audit and tests
This commit is contained in:
Tw93
2026-01-15 11:39:33 +08:00
parent cac2909093
commit c34d91b36f
4 changed files with 79 additions and 21 deletions

View File

@@ -660,6 +660,7 @@ find_app_files() {
"$HOME/Library/HTTPStorages/$bundle_id"
"$HOME/Library/Cookies/$bundle_id.binarycookies"
"$HOME/Library/LaunchAgents/$bundle_id.plist"
"$HOME/Library/LaunchDaemons/$bundle_id.plist"
"$HOME/Library/Application Scripts/$bundle_id"
"$HOME/Library/Services/$app_name.workflow"
"$HOME/Library/QuickLook/$app_name.qlgenerator"
@@ -734,11 +735,18 @@ find_app_files() {
fi
fi
# Launch Agents by name (special handling)
if [[ ${#app_name} -gt 3 ]] && [[ -d ~/Library/LaunchAgents ]]; then
while IFS= read -r -d '' plist; do
files_to_clean+=("$plist")
done < <(command find ~/Library/LaunchAgents -maxdepth 1 \( -name "*$app_name*.plist" \) -print0 2> /dev/null)
# Launch Agents and Daemons by name (special handling)
if [[ ${#app_name} -gt 3 ]]; then
if [[ -d ~/Library/LaunchAgents ]]; then
while IFS= read -r -d '' plist; do
files_to_clean+=("$plist")
done < <(command find ~/Library/LaunchAgents -maxdepth 1 \( -name "*$app_name*.plist" \) -print0 2> /dev/null)
fi
if [[ -d ~/Library/LaunchDaemons ]]; then
while IFS= read -r -d '' plist; do
files_to_clean+=("$plist")
done < <(command find ~/Library/LaunchDaemons -maxdepth 1 \( -name "*$app_name*.plist" \) -print0 2> /dev/null)
fi
fi
# Handle specialized toolchains and development environments

View File

@@ -88,6 +88,40 @@ stop_launch_services() {
fi
}
# Remove macOS Login Items for an app
remove_login_item() {
local app_name="$1"
local bundle_id="$2"
# Skip if no identifiers provided
[[ -z "$app_name" && -z "$bundle_id" ]] && return 0
# Strip .app suffix if present (login items don't include it)
local clean_name="${app_name%.app}"
# Remove from Login Items using index-based deletion (handles broken items)
if [[ -n "$clean_name" ]]; then
osascript <<-EOF 2>/dev/null || true
tell application "System Events"
try
set itemCount to count of login items
-- Delete in reverse order to avoid index shifting
repeat with i from itemCount to 1 by -1
try
set itemName to name of login item i
if itemName is "$clean_name" then
delete login item i
end if
end try
end repeat
end try
end tell
EOF
fi
}
# Remove files (handles symlinks, optional sudo).
remove_file_list() {
local file_list="$1"
@@ -364,6 +398,9 @@ batch_uninstall_applications() {
[[ -n "$system_files" ]] && has_system_files="true"
stop_launch_services "$bundle_id" "$has_system_files"
# Remove from Login Items
remove_login_item "$app_name" "$bundle_id"
if ! force_kill_app "$app_name" "$app_path"; then
reason="still running"
fi
@@ -371,15 +408,20 @@ batch_uninstall_applications() {
# Remove the application only if not running.
if [[ -z "$reason" ]]; then
if [[ "$is_brew_cask" == "true" && -n "$cask_name" ]]; then
# Use brew uninstall --cask with progress indicator
local brew_output_file=$(mktemp)
# Stop spinner before brew output
if [[ -t 1 ]]; then
stop_inline_spinner
fi
# Use brew uninstall --cask - show output directly
local brew_failed=false
if ! run_with_timeout 120 brew uninstall --cask "$cask_name" > "$brew_output_file" 2>&1; then
if ! run_with_timeout 120 brew uninstall --cask "$cask_name" 2>&1; then
brew_failed=true
log_warning "brew uninstall failed for $app_name, falling back to manual cleanup"
fi
rm -f "$brew_output_file"
if [[ "$brew_failed" == "true" ]]; then
# Fallback to manual cleanup
[[ -z "$related_files" ]] && related_files=$(find_app_files "$bundle_id" "$app_name")
[[ -z "$system_files" ]] && system_files=$(find_app_system_files "$bundle_id" "$app_name")
if [[ "$needs_sudo" == true ]]; then