mirror of
https://github.com/tw93/Mole.git
synced 2026-03-22 18:30:08 +00:00
fix(clean): avoid stalls in app support scan
This commit is contained in:
@@ -752,6 +752,23 @@ clean_virtualization_tools() {
|
|||||||
|
|
||||||
# Estimate item size for Application Support cleanup.
|
# Estimate item size for Application Support cleanup.
|
||||||
# Files use stat; directories use du with timeout to avoid long blocking scans.
|
# 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() {
|
app_support_item_size_bytes() {
|
||||||
local item="$1"
|
local item="$1"
|
||||||
local timeout_seconds="${2:-0.4}"
|
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
|
# Fast path: if directory has too many items, skip detailed size calculation
|
||||||
# to avoid hanging on deep directories (e.g., node_modules, .git)
|
# to avoid hanging on deep directories (e.g., node_modules, .git)
|
||||||
local item_count
|
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
|
if [[ "$item_count" -gt 10000 ]]; then
|
||||||
# Return 1 to signal "too many items, size unknown"
|
# Return 1 to signal "too many items, size unknown"
|
||||||
return 1
|
return 1
|
||||||
@@ -859,7 +876,7 @@ clean_application_support_logs() {
|
|||||||
if [[ -d "$candidate" ]]; then
|
if [[ -d "$candidate" ]]; then
|
||||||
# Quick count check - skip if too many items to avoid hanging
|
# Quick count check - skip if too many items to avoid hanging
|
||||||
local quick_count
|
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
|
if [[ "$quick_count" -gt 100 ]]; then
|
||||||
# Too many items - use bulk removal instead of item-by-item
|
# Too many items - use bulk removal instead of item-by-item
|
||||||
local app_label="$app_name"
|
local app_label="$app_name"
|
||||||
@@ -935,7 +952,7 @@ clean_application_support_logs() {
|
|||||||
if [[ -d "$candidate" ]]; then
|
if [[ -d "$candidate" ]]; then
|
||||||
# Quick count check - skip if too many items
|
# Quick count check - skip if too many items
|
||||||
local quick_count
|
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
|
if [[ "$quick_count" -gt 100 ]]; then
|
||||||
local container_label="$container"
|
local container_label="$container"
|
||||||
if [[ ${#container_label} -gt 24 ]]; then
|
if [[ ${#container_label} -gt 24 ]]; then
|
||||||
|
|||||||
@@ -220,6 +220,63 @@ EOF
|
|||||||
[[ "$total_kb" -ge 2 ]]
|
[[ "$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" {
|
@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'
|
run env HOME="$HOME" PROJECT_ROOT="$PROJECT_ROOT" DRY_RUN=false /bin/bash --noprofile --norc <<'EOF'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|||||||
Reference in New Issue
Block a user