mirror of
https://github.com/tw93/Mole.git
synced 2026-03-22 17:55:08 +00:00
@@ -244,6 +244,44 @@ is_bundle_orphaned() {
|
|||||||
# All checks passed - this is an orphan
|
# All checks passed - this is an orphan
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_claude_vm_bundle_orphaned() {
|
||||||
|
local vm_bundle_path="$1"
|
||||||
|
local installed_bundles="$2"
|
||||||
|
local claude_bundle_id="com.anthropic.claudefordesktop"
|
||||||
|
|
||||||
|
[[ -d "$vm_bundle_path" ]] || return 1
|
||||||
|
|
||||||
|
# Extra guard in case the running-app scan missed Claude Desktop.
|
||||||
|
if pgrep -x "Claude" > /dev/null 2>&1; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Fxq "$claude_bundle_id" "$installed_bundles" 2> /dev/null; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ORPHAN_MDFIND_CACHE_FILE" ]]; then
|
||||||
|
ORPHAN_MDFIND_CACHE_FILE=$(mktemp "${TMPDIR:-/tmp}/mole_mdfind_cache.XXXXXX")
|
||||||
|
register_temp_file "$ORPHAN_MDFIND_CACHE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Fxq "FOUND:$claude_bundle_id" "$ORPHAN_MDFIND_CACHE_FILE" 2> /dev/null; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if ! grep -Fxq "NOTFOUND:$claude_bundle_id" "$ORPHAN_MDFIND_CACHE_FILE" 2> /dev/null; then
|
||||||
|
local app_exists
|
||||||
|
app_exists=$(run_with_timeout 2 mdfind "kMDItemCFBundleIdentifier == '$claude_bundle_id'" 2> /dev/null | head -1 || echo "")
|
||||||
|
if [[ -n "$app_exists" ]]; then
|
||||||
|
echo "FOUND:$claude_bundle_id" >> "$ORPHAN_MDFIND_CACHE_FILE"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "NOTFOUND:$claude_bundle_id" >> "$ORPHAN_MDFIND_CACHE_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Orphaned app data sweep.
|
# Orphaned app data sweep.
|
||||||
clean_orphaned_app_data() {
|
clean_orphaned_app_data() {
|
||||||
if ! ls "$HOME/Library/Caches" > /dev/null 2>&1; then
|
if ! ls "$HOME/Library/Caches" > /dev/null 2>&1; then
|
||||||
@@ -260,6 +298,19 @@ clean_orphaned_app_data() {
|
|||||||
local orphaned_count=0
|
local orphaned_count=0
|
||||||
local total_orphaned_kb=0
|
local total_orphaned_kb=0
|
||||||
start_section_spinner "Scanning orphaned app resources..."
|
start_section_spinner "Scanning orphaned app resources..."
|
||||||
|
|
||||||
|
local claude_vm_bundle="$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle"
|
||||||
|
if is_claude_vm_bundle_orphaned "$claude_vm_bundle" "$installed_bundles"; then
|
||||||
|
local claude_vm_size_kb
|
||||||
|
claude_vm_size_kb=$(get_path_size_kb "$claude_vm_bundle")
|
||||||
|
if [[ -n "$claude_vm_size_kb" && "$claude_vm_size_kb" != "0" ]]; then
|
||||||
|
if safe_clean "$claude_vm_bundle" "Orphaned Claude workspace VM"; then
|
||||||
|
orphaned_count=$((orphaned_count + 1))
|
||||||
|
total_orphaned_kb=$((total_orphaned_kb + claude_vm_size_kb))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# CRITICAL: NEVER add LaunchAgents or LaunchDaemons (breaks login items/startup apps).
|
# CRITICAL: NEVER add LaunchAgents or LaunchDaemons (breaks login items/startup apps).
|
||||||
local -a resource_types=(
|
local -a resource_types=(
|
||||||
"$HOME/Library/Caches|Caches|com.*:org.*:net.*:io.*"
|
"$HOME/Library/Caches|Caches|com.*:org.*:net.*:io.*"
|
||||||
@@ -269,7 +320,6 @@ clean_orphaned_app_data() {
|
|||||||
"$HOME/Library/HTTPStorages|HTTP|com.*:org.*:net.*:io.*"
|
"$HOME/Library/HTTPStorages|HTTP|com.*:org.*:net.*:io.*"
|
||||||
"$HOME/Library/Cookies|Cookies|*.binarycookies"
|
"$HOME/Library/Cookies|Cookies|*.binarycookies"
|
||||||
)
|
)
|
||||||
orphaned_count=0
|
|
||||||
for resource_type in "${resource_types[@]}"; do
|
for resource_type in "${resource_types[@]}"; do
|
||||||
IFS='|' read -r base_path label patterns <<< "$resource_type"
|
IFS='|' read -r base_path label patterns <<< "$resource_type"
|
||||||
if [[ ! -d "$base_path" ]]; then
|
if [[ ! -d "$base_path" ]]; then
|
||||||
|
|||||||
@@ -210,6 +210,88 @@ EOF
|
|||||||
[[ "$output" == *"PASS: Successful deletion removed"* ]]
|
[[ "$output" == *"PASS: Successful deletion removed"* ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "clean_orphaned_app_data removes orphaned Claude VM bundle" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/apps.sh"
|
||||||
|
|
||||||
|
scan_installed_apps() {
|
||||||
|
: > "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdfind() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pgrep() {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
run_with_timeout() { shift; "$@"; }
|
||||||
|
|
||||||
|
safe_clean() {
|
||||||
|
echo "$2"
|
||||||
|
rm -rf "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
start_section_spinner() { :; }
|
||||||
|
stop_section_spinner() { :; }
|
||||||
|
|
||||||
|
mkdir -p "$HOME/Library/Caches"
|
||||||
|
mkdir -p "$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle"
|
||||||
|
echo "vm data" > "$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle/rootfs.img"
|
||||||
|
|
||||||
|
clean_orphaned_app_data
|
||||||
|
|
||||||
|
if [[ ! -d "$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle" ]]; then
|
||||||
|
echo "PASS: Claude VM removed"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" == *"Orphaned Claude workspace VM"* ]]
|
||||||
|
[[ "$output" == *"PASS: Claude VM removed"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "clean_orphaned_app_data keeps Claude VM bundle when Claude is installed" {
|
||||||
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
|
||||||
|
set -euo pipefail
|
||||||
|
source "$PROJECT_ROOT/lib/core/common.sh"
|
||||||
|
source "$PROJECT_ROOT/lib/clean/apps.sh"
|
||||||
|
|
||||||
|
scan_installed_apps() {
|
||||||
|
echo "com.anthropic.claudefordesktop" > "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
pgrep() {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_clean() {
|
||||||
|
echo "UNEXPECTED:$2"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
start_section_spinner() { :; }
|
||||||
|
stop_section_spinner() { :; }
|
||||||
|
|
||||||
|
mkdir -p "$HOME/Library/Caches"
|
||||||
|
mkdir -p "$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle"
|
||||||
|
echo "vm data" > "$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle/rootfs.img"
|
||||||
|
|
||||||
|
clean_orphaned_app_data
|
||||||
|
|
||||||
|
if [[ -d "$HOME/Library/Application Support/Claude/vm_bundles/claudevm.bundle" ]]; then
|
||||||
|
echo "PASS: Claude VM kept"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" != *"UNEXPECTED:Orphaned Claude workspace VM"* ]]
|
||||||
|
[[ "$output" == *"PASS: Claude VM kept"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@test "is_critical_system_component matches known system services" {
|
@test "is_critical_system_component matches known system services" {
|
||||||
run bash --noprofile --norc <<'EOF'
|
run bash --noprofile --norc <<'EOF'
|
||||||
|
|||||||
Reference in New Issue
Block a user