1
0
mirror of https://github.com/tw93/Mole.git synced 2026-03-22 16:45:07 +00:00

fix(clean): avoid stalls in app support scan

This commit is contained in:
tw93
2026-03-07 18:35:19 +08:00
parent 89a9ae0ce2
commit 300aded07b
2 changed files with 77 additions and 3 deletions

View File

@@ -752,6 +752,23 @@ clean_virtualization_tools() {
# Estimate item size for Application Support cleanup.
# Files use stat; directories use du with timeout to avoid long blocking scans.
app_support_entry_count_capped() {
local dir="$1"
local maxdepth="${2:-1}"
local cap="${3:-101}"
local count=0
while IFS= read -r -d '' _entry; do
count=$((count + 1))
if ((count >= cap)); then
break
fi
done < <(command find "$dir" -mindepth 1 -maxdepth "$maxdepth" -print0 2> /dev/null)
[[ "$count" =~ ^[0-9]+$ ]] || count=0
printf '%s\n' "$count"
}
app_support_item_size_bytes() {
local item="$1"
local timeout_seconds="${2:-0.4}"
@@ -768,7 +785,7 @@ app_support_item_size_bytes() {
# Fast path: if directory has too many items, skip detailed size calculation
# to avoid hanging on deep directories (e.g., node_modules, .git)
local item_count
item_count=$(command find "$item" -maxdepth 2 -print0 2> /dev/null | tr -d '\0' | wc -c)
item_count=$(app_support_entry_count_capped "$item" 2 10001)
if [[ "$item_count" -gt 10000 ]]; then
# Return 1 to signal "too many items, size unknown"
return 1
@@ -859,7 +876,7 @@ clean_application_support_logs() {
if [[ -d "$candidate" ]]; then
# Quick count check - skip if too many items to avoid hanging
local quick_count
quick_count=$(command find "$candidate" -mindepth 1 -maxdepth 1 -printf '1\n' 2> /dev/null | wc -l | tr -d ' ')
quick_count=$(app_support_entry_count_capped "$candidate" 1 101)
if [[ "$quick_count" -gt 100 ]]; then
# Too many items - use bulk removal instead of item-by-item
local app_label="$app_name"
@@ -935,7 +952,7 @@ clean_application_support_logs() {
if [[ -d "$candidate" ]]; then
# Quick count check - skip if too many items
local quick_count
quick_count=$(command find "$candidate" -mindepth 1 -maxdepth 1 -printf '1\n' 2> /dev/null | wc -l | tr -d ' ')
quick_count=$(app_support_entry_count_capped "$candidate" 1 101)
if [[ "$quick_count" -gt 100 ]]; then
local container_label="$container"
if [[ ${#container_label} -gt 24 ]]; then

View File

@@ -220,6 +220,63 @@ EOF
[[ "$total_kb" -ge 2 ]]
}
@test "clean_application_support_logs uses bulk clean for large Application Support directories" {
local support_home="$HOME/support-appsupport-bulk"
run env HOME="$support_home" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=true bash --noprofile --norc <<'EOF'
set -euo pipefail
mkdir -p "$HOME"
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
start_section_spinner() { echo "SPIN:$1"; }
stop_section_spinner() { :; }
note_activity() { :; }
safe_remove() { echo "REMOVE:$1"; }
update_progress_if_needed() { return 1; }
should_protect_data() { return 1; }
is_critical_system_component() { return 1; }
bytes_to_human() { echo "0B"; }
files_cleaned=0
total_size_cleaned=0
total_items=0
mkdir -p "$HOME/Library/Application Support/adspower_global/logs"
for i in $(seq 1 101); do
touch "$HOME/Library/Application Support/adspower_global/logs/file-$i.log"
done
clean_application_support_logs
rm -rf "$HOME/Library/Application Support"
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"SPIN:Scanning Application Support... 1/1 [adspower_global, bulk clean]"* ]]
[[ "$output" == *"Application Support logs/caches"* ]]
[[ "$output" != *"151250 items"* ]]
[[ "$output" != *"REMOVE:"* ]]
}
@test "app_support_entry_count_capped stops at cap without failing under pipefail" {
local support_home="$HOME/support-appsupport-cap"
run env HOME="$support_home" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF'
set -euo pipefail
mkdir -p "$HOME"
source "$PROJECT_ROOT/lib/core/common.sh"
source "$PROJECT_ROOT/lib/clean/user.sh"
mkdir -p "$HOME/Library/Application Support/adspower_global/logs"
for i in $(seq 1 150); do
touch "$HOME/Library/Application Support/adspower_global/logs/file-$i.log"
done
count=$(app_support_entry_count_capped "$HOME/Library/Application Support/adspower_global/logs" 1 101)
echo "COUNT=$count"
rm -rf "$HOME/Library/Application Support"
EOF
[ "$status" -eq 0 ]
[[ "$output" == *"COUNT=101"* ]]
}
@test "clean_group_container_caches keeps protected caches and cleans non-protected caches" {
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=false /bin/bash --noprofile --norc <<'EOF'
set -euo pipefail