mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 18:34:46 +00:00
chore: auto format code
This commit is contained in:
82
bin/clean.sh
82
bin/clean.sh
@@ -69,10 +69,10 @@ if [[ -f "$HOME/.config/mole/whitelist" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
case "$line" in
|
case "$line" in
|
||||||
/ | /System | /System/* | /bin | /bin/* | /sbin | /sbin/* | /usr/bin | /usr/bin/* | /usr/sbin | /usr/sbin/* | /etc | /etc/* | /var/db | /var/db/*)
|
/ | /System | /System/* | /bin | /bin/* | /sbin | /sbin/* | /usr/bin | /usr/bin/* | /usr/sbin | /usr/sbin/* | /etc | /etc/* | /var/db | /var/db/*)
|
||||||
WHITELIST_WARNINGS+=("Protected system path: $line")
|
WHITELIST_WARNINGS+=("Protected system path: $line")
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
duplicate="false"
|
duplicate="false"
|
||||||
@@ -86,7 +86,7 @@ if [[ -f "$HOME/.config/mole/whitelist" ]]; then
|
|||||||
fi
|
fi
|
||||||
[[ "$duplicate" == "true" ]] && continue
|
[[ "$duplicate" == "true" ]] && continue
|
||||||
WHITELIST_PATTERNS+=("$line")
|
WHITELIST_PATTERNS+=("$line")
|
||||||
done <"$HOME/.config/mole/whitelist"
|
done < "$HOME/.config/mole/whitelist"
|
||||||
else
|
else
|
||||||
WHITELIST_PATTERNS=("${DEFAULT_WHITELIST_PATTERNS[@]}")
|
WHITELIST_PATTERNS=("${DEFAULT_WHITELIST_PATTERNS[@]}")
|
||||||
fi
|
fi
|
||||||
@@ -140,7 +140,7 @@ cleanup() {
|
|||||||
fi
|
fi
|
||||||
CLEANUP_DONE=true
|
CLEANUP_DONE=true
|
||||||
|
|
||||||
stop_inline_spinner 2>/dev/null || true
|
stop_inline_spinner 2> /dev/null || true
|
||||||
|
|
||||||
if [[ -t 1 ]]; then
|
if [[ -t 1 ]]; then
|
||||||
printf "\r\033[K" >&2 || true
|
printf "\r\033[K" >&2 || true
|
||||||
@@ -166,8 +166,8 @@ start_section() {
|
|||||||
|
|
||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
if [[ "$DRY_RUN" == "true" ]]; then
|
||||||
ensure_user_file "$EXPORT_LIST_FILE"
|
ensure_user_file "$EXPORT_LIST_FILE"
|
||||||
echo "" >>"$EXPORT_LIST_FILE"
|
echo "" >> "$EXPORT_LIST_FILE"
|
||||||
echo "=== $1 ===" >>"$EXPORT_LIST_FILE"
|
echo "=== $1 ===" >> "$EXPORT_LIST_FILE"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ normalize_paths_for_cleanup() {
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
[[ "$is_child" == "true" ]] || result_paths+=("$path")
|
[[ "$is_child" == "true" ]] || result_paths+=("$path")
|
||||||
done <<<"$sorted_paths"
|
done <<< "$sorted_paths"
|
||||||
|
|
||||||
if [[ ${#result_paths[@]} -gt 0 ]]; then
|
if [[ ${#result_paths[@]} -gt 0 ]]; then
|
||||||
printf '%s\n' "${result_paths[@]}"
|
printf '%s\n' "${result_paths[@]}"
|
||||||
@@ -232,9 +232,9 @@ get_cleanup_path_size_kb() {
|
|||||||
local path="$1"
|
local path="$1"
|
||||||
|
|
||||||
if [[ -f "$path" && ! -L "$path" ]]; then
|
if [[ -f "$path" && ! -L "$path" ]]; then
|
||||||
if command -v stat >/dev/null 2>&1; then
|
if command -v stat > /dev/null 2>&1; then
|
||||||
local bytes
|
local bytes
|
||||||
bytes=$(stat -f%z "$path" 2>/dev/null || echo "0")
|
bytes=$(stat -f%z "$path" 2> /dev/null || echo "0")
|
||||||
if [[ "$bytes" =~ ^[0-9]+$ && "$bytes" -gt 0 ]]; then
|
if [[ "$bytes" =~ ^[0-9]+$ && "$bytes" -gt 0 ]]; then
|
||||||
echo $(((bytes + 1023) / 1024))
|
echo $(((bytes + 1023) / 1024))
|
||||||
return 0
|
return 0
|
||||||
@@ -243,9 +243,9 @@ get_cleanup_path_size_kb() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -L "$path" ]]; then
|
if [[ -L "$path" ]]; then
|
||||||
if command -v stat >/dev/null 2>&1; then
|
if command -v stat > /dev/null 2>&1; then
|
||||||
local bytes
|
local bytes
|
||||||
bytes=$(stat -f%z "$path" 2>/dev/null || echo "0")
|
bytes=$(stat -f%z "$path" 2> /dev/null || echo "0")
|
||||||
if [[ "$bytes" =~ ^[0-9]+$ && "$bytes" -gt 0 ]]; then
|
if [[ "$bytes" =~ ^[0-9]+$ && "$bytes" -gt 0 ]]; then
|
||||||
echo $(((bytes + 1023) / 1024))
|
echo $(((bytes + 1023) / 1024))
|
||||||
else
|
else
|
||||||
@@ -461,9 +461,9 @@ safe_clean() {
|
|||||||
[[ ! "$size" =~ ^[0-9]+$ ]] && size=0
|
[[ ! "$size" =~ ^[0-9]+$ ]] && size=0
|
||||||
|
|
||||||
if [[ "$size" -gt 0 ]]; then
|
if [[ "$size" -gt 0 ]]; then
|
||||||
echo "$size 1" >"$temp_dir/result_${idx}"
|
echo "$size 1" > "$temp_dir/result_${idx}"
|
||||||
else
|
else
|
||||||
echo "0 0" >"$temp_dir/result_${idx}"
|
echo "0 0" > "$temp_dir/result_${idx}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
((idx++))
|
((idx++))
|
||||||
@@ -488,17 +488,17 @@ safe_clean() {
|
|||||||
[[ ! "$size" =~ ^[0-9]+$ ]] && size=0
|
[[ ! "$size" =~ ^[0-9]+$ ]] && size=0
|
||||||
local tmp_file="$temp_dir/result_${idx}.$$"
|
local tmp_file="$temp_dir/result_${idx}.$$"
|
||||||
if [[ "$size" -gt 0 ]]; then
|
if [[ "$size" -gt 0 ]]; then
|
||||||
echo "$size 1" >"$tmp_file"
|
echo "$size 1" > "$tmp_file"
|
||||||
else
|
else
|
||||||
echo "0 0" >"$tmp_file"
|
echo "0 0" > "$tmp_file"
|
||||||
fi
|
fi
|
||||||
mv "$tmp_file" "$temp_dir/result_${idx}" 2>/dev/null || true
|
mv "$tmp_file" "$temp_dir/result_${idx}" 2> /dev/null || true
|
||||||
) &
|
) &
|
||||||
pids+=($!)
|
pids+=($!)
|
||||||
((idx++))
|
((idx++))
|
||||||
|
|
||||||
if ((${#pids[@]} >= MOLE_MAX_PARALLEL_JOBS)); then
|
if ((${#pids[@]} >= MOLE_MAX_PARALLEL_JOBS)); then
|
||||||
wait "${pids[0]}" 2>/dev/null || true
|
wait "${pids[0]}" 2> /dev/null || true
|
||||||
pids=("${pids[@]:1}")
|
pids=("${pids[@]:1}")
|
||||||
((completed++))
|
((completed++))
|
||||||
|
|
||||||
@@ -511,7 +511,7 @@ safe_clean() {
|
|||||||
|
|
||||||
if [[ ${#pids[@]} -gt 0 ]]; then
|
if [[ ${#pids[@]} -gt 0 ]]; then
|
||||||
for pid in "${pids[@]}"; do
|
for pid in "${pids[@]}"; do
|
||||||
wait "$pid" 2>/dev/null || true
|
wait "$pid" 2> /dev/null || true
|
||||||
((completed++))
|
((completed++))
|
||||||
|
|
||||||
if [[ "$show_spinner" == "true" && -t 1 ]]; then
|
if [[ "$show_spinner" == "true" && -t 1 ]]; then
|
||||||
@@ -527,11 +527,11 @@ safe_clean() {
|
|||||||
for path in "${existing_paths[@]}"; do
|
for path in "${existing_paths[@]}"; do
|
||||||
local result_file="$temp_dir/result_${idx}"
|
local result_file="$temp_dir/result_${idx}"
|
||||||
if [[ -f "$result_file" ]]; then
|
if [[ -f "$result_file" ]]; then
|
||||||
read -r size count <"$result_file" 2>/dev/null || true
|
read -r size count < "$result_file" 2> /dev/null || true
|
||||||
local removed=0
|
local removed=0
|
||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
if [[ -L "$path" ]]; then
|
if [[ -L "$path" ]]; then
|
||||||
rm "$path" 2>/dev/null && removed=1
|
rm "$path" 2> /dev/null && removed=1
|
||||||
else
|
else
|
||||||
if safe_remove "$path" true; then
|
if safe_remove "$path" true; then
|
||||||
removed=1
|
removed=1
|
||||||
@@ -568,7 +568,7 @@ safe_clean() {
|
|||||||
local removed=0
|
local removed=0
|
||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
if [[ -L "$path" ]]; then
|
if [[ -L "$path" ]]; then
|
||||||
rm "$path" 2>/dev/null && removed=1
|
rm "$path" 2> /dev/null && removed=1
|
||||||
else
|
else
|
||||||
if safe_remove "$path" true; then
|
if safe_remove "$path" true; then
|
||||||
removed=1
|
removed=1
|
||||||
@@ -629,9 +629,9 @@ safe_clean() {
|
|||||||
local size=0
|
local size=0
|
||||||
|
|
||||||
if [[ -n "${temp_dir:-}" && -f "$temp_dir/result_${idx}" ]]; then
|
if [[ -n "${temp_dir:-}" && -f "$temp_dir/result_${idx}" ]]; then
|
||||||
read -r size count <"$temp_dir/result_${idx}" 2>/dev/null || true
|
read -r size count < "$temp_dir/result_${idx}" 2> /dev/null || true
|
||||||
else
|
else
|
||||||
size=$(get_cleanup_path_size_kb "$path" 2>/dev/null || echo "0")
|
size=$(get_cleanup_path_size_kb "$path" 2> /dev/null || echo "0")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ "$size" == "0" || -z "$size" ]] && {
|
[[ "$size" == "0" || -z "$size" ]] && {
|
||||||
@@ -639,7 +639,7 @@ safe_clean() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "$(dirname "$path")|$size|$path" >>"$paths_temp"
|
echo "$(dirname "$path")|$size|$path" >> "$paths_temp"
|
||||||
((idx++))
|
((idx++))
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
@@ -670,9 +670,9 @@ safe_clean() {
|
|||||||
' | while IFS='|' read -r display_path total_size child_count; do
|
' | while IFS='|' read -r display_path total_size child_count; do
|
||||||
local size_human=$(bytes_to_human "$((total_size * 1024))")
|
local size_human=$(bytes_to_human "$((total_size * 1024))")
|
||||||
if [[ $child_count -gt 1 ]]; then
|
if [[ $child_count -gt 1 ]]; then
|
||||||
echo "$display_path # $size_human ($child_count items)" >>"$EXPORT_LIST_FILE"
|
echo "$display_path # $size_human ($child_count items)" >> "$EXPORT_LIST_FILE"
|
||||||
else
|
else
|
||||||
echo "$display_path # $size_human" >>"$EXPORT_LIST_FILE"
|
echo "$display_path # $size_human" >> "$EXPORT_LIST_FILE"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -708,7 +708,7 @@ start_cleanup() {
|
|||||||
SYSTEM_CLEAN=false
|
SYSTEM_CLEAN=false
|
||||||
|
|
||||||
ensure_user_file "$EXPORT_LIST_FILE"
|
ensure_user_file "$EXPORT_LIST_FILE"
|
||||||
cat >"$EXPORT_LIST_FILE" <<EOF
|
cat > "$EXPORT_LIST_FILE" << EOF
|
||||||
# Mole Cleanup Preview - $(date '+%Y-%m-%d %H:%M:%S')
|
# Mole Cleanup Preview - $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
#
|
#
|
||||||
# How to protect files:
|
# How to protect files:
|
||||||
@@ -998,7 +998,7 @@ perform_cleanup() {
|
|||||||
echo "# Potential cleanup: ${freed_gb}GB"
|
echo "# Potential cleanup: ${freed_gb}GB"
|
||||||
echo "# Items: $files_cleaned"
|
echo "# Items: $files_cleaned"
|
||||||
echo "# Categories: $total_items"
|
echo "# Categories: $total_items"
|
||||||
} >>"$EXPORT_LIST_FILE"
|
} >> "$EXPORT_LIST_FILE"
|
||||||
|
|
||||||
summary_details+=("Detailed file list: ${GRAY}$EXPORT_LIST_FILE${NC}")
|
summary_details+=("Detailed file list: ${GRAY}$EXPORT_LIST_FILE${NC}")
|
||||||
summary_details+=("Use ${GRAY}mo clean --whitelist${NC} to add protection rules")
|
summary_details+=("Use ${GRAY}mo clean --whitelist${NC} to add protection rules")
|
||||||
@@ -1047,17 +1047,17 @@ perform_cleanup() {
|
|||||||
main() {
|
main() {
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
"--debug")
|
"--debug")
|
||||||
export MO_DEBUG=1
|
export MO_DEBUG=1
|
||||||
;;
|
;;
|
||||||
"--dry-run" | "-n")
|
"--dry-run" | "-n")
|
||||||
DRY_RUN=true
|
DRY_RUN=true
|
||||||
;;
|
;;
|
||||||
"--whitelist")
|
"--whitelist")
|
||||||
source "$SCRIPT_DIR/../lib/manage/whitelist.sh"
|
source "$SCRIPT_DIR/../lib/manage/whitelist.sh"
|
||||||
manage_whitelist "clean"
|
manage_whitelist "clean"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ clean_deep_system() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
local item_flags
|
local item_flags
|
||||||
item_flags=$($STAT_BSD -f%Sf "$item" 2>/dev/null || echo "")
|
item_flags=$($STAT_BSD -f%Sf "$item" 2> /dev/null || echo "")
|
||||||
if [[ "$item_flags" == *"restricted"* ]]; then
|
if [[ "$item_flags" == *"restricted"* ]]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if safe_sudo_remove "$item"; then
|
if safe_sudo_remove "$item"; then
|
||||||
((updates_cleaned++))
|
((updates_cleaned++))
|
||||||
fi
|
fi
|
||||||
done < <(find /Library/Updates -mindepth 1 -maxdepth 1 -print0 2>/dev/null || true)
|
done < <(find /Library/Updates -mindepth 1 -maxdepth 1 -print0 2> /dev/null || true)
|
||||||
[[ $updates_cleaned -gt 0 ]] && log_success "System library updates"
|
[[ $updates_cleaned -gt 0 ]] && log_success "System library updates"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -76,7 +76,7 @@ clean_deep_system() {
|
|||||||
last_update_time=$current_time
|
last_update_time=$current_time
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done < <(run_with_timeout 5 command find /private/var/folders -type d -name "*.code_sign_clone" -path "*/X/*" -print0 2>/dev/null || true)
|
done < <(run_with_timeout 5 command find /private/var/folders -type d -name "*.code_sign_clone" -path "*/X/*" -print0 2> /dev/null || true)
|
||||||
stop_section_spinner
|
stop_section_spinner
|
||||||
[[ $code_sign_cleaned -gt 0 ]] && log_success "Browser code signature caches ($code_sign_cleaned items)"
|
[[ $code_sign_cleaned -gt 0 ]] && log_success "Browser code signature caches ($code_sign_cleaned items)"
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ clean_deep_system() {
|
|||||||
# Incomplete Time Machine backups.
|
# Incomplete Time Machine backups.
|
||||||
clean_time_machine_failed_backups() {
|
clean_time_machine_failed_backups() {
|
||||||
local tm_cleaned=0
|
local tm_cleaned=0
|
||||||
if ! command -v tmutil >/dev/null 2>&1; then
|
if ! command -v tmutil > /dev/null 2>&1; then
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} No incomplete backups found"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} No incomplete backups found"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -155,9 +155,9 @@ clean_time_machine_failed_backups() {
|
|||||||
fi
|
fi
|
||||||
for volume in "${backup_volumes[@]}"; do
|
for volume in "${backup_volumes[@]}"; do
|
||||||
local fs_type
|
local fs_type
|
||||||
fs_type=$(run_with_timeout 1 command df -T "$volume" 2>/dev/null | tail -1 | awk '{print $2}' || echo "unknown")
|
fs_type=$(run_with_timeout 1 command df -T "$volume" 2> /dev/null | tail -1 | awk '{print $2}' || echo "unknown")
|
||||||
case "$fs_type" in
|
case "$fs_type" in
|
||||||
nfs | smbfs | afpfs | cifs | webdav | unknown) continue ;;
|
nfs | smbfs | afpfs | cifs | webdav | unknown) continue ;;
|
||||||
esac
|
esac
|
||||||
local backupdb_dir="$volume/Backups.backupdb"
|
local backupdb_dir="$volume/Backups.backupdb"
|
||||||
if [[ -d "$backupdb_dir" ]]; then
|
if [[ -d "$backupdb_dir" ]]; then
|
||||||
@@ -185,11 +185,11 @@ clean_time_machine_failed_backups() {
|
|||||||
note_activity
|
note_activity
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if ! command -v tmutil >/dev/null 2>&1; then
|
if ! command -v tmutil > /dev/null 2>&1; then
|
||||||
echo -e " ${YELLOW}!${NC} tmutil not available, skipping: $backup_name"
|
echo -e " ${YELLOW}!${NC} tmutil not available, skipping: $backup_name"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if tmutil delete "$inprogress_file" 2>/dev/null; then
|
if tmutil delete "$inprogress_file" 2> /dev/null; then
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Incomplete backup: $backup_name ${GREEN}($size_human)${NC}"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Incomplete backup: $backup_name ${GREEN}($size_human)${NC}"
|
||||||
((tm_cleaned++))
|
((tm_cleaned++))
|
||||||
((files_cleaned++))
|
((files_cleaned++))
|
||||||
@@ -199,14 +199,14 @@ clean_time_machine_failed_backups() {
|
|||||||
else
|
else
|
||||||
echo -e " ${YELLOW}!${NC} Could not delete: $backup_name · try manually with sudo"
|
echo -e " ${YELLOW}!${NC} Could not delete: $backup_name · try manually with sudo"
|
||||||
fi
|
fi
|
||||||
done < <(run_with_timeout 15 find "$backupdb_dir" -maxdepth 3 -type d \( -name "*.inProgress" -o -name "*.inprogress" \) 2>/dev/null || true)
|
done < <(run_with_timeout 15 find "$backupdb_dir" -maxdepth 3 -type d \( -name "*.inProgress" -o -name "*.inprogress" \) 2> /dev/null || true)
|
||||||
fi
|
fi
|
||||||
# APFS bundles.
|
# APFS bundles.
|
||||||
for bundle in "$volume"/*.backupbundle "$volume"/*.sparsebundle; do
|
for bundle in "$volume"/*.backupbundle "$volume"/*.sparsebundle; do
|
||||||
[[ -e "$bundle" ]] || continue
|
[[ -e "$bundle" ]] || continue
|
||||||
[[ -d "$bundle" ]] || continue
|
[[ -d "$bundle" ]] || continue
|
||||||
local bundle_name=$(basename "$bundle")
|
local bundle_name=$(basename "$bundle")
|
||||||
local mounted_path=$(hdiutil info 2>/dev/null | grep -A 5 "image-path.*$bundle_name" | grep "/Volumes/" | awk '{print $1}' | head -1 || echo "")
|
local mounted_path=$(hdiutil info 2> /dev/null | grep -A 5 "image-path.*$bundle_name" | grep "/Volumes/" | awk '{print $1}' | head -1 || echo "")
|
||||||
if [[ -n "$mounted_path" && -d "$mounted_path" ]]; then
|
if [[ -n "$mounted_path" && -d "$mounted_path" ]]; then
|
||||||
while IFS= read -r inprogress_file; do
|
while IFS= read -r inprogress_file; do
|
||||||
[[ -d "$inprogress_file" ]] || continue
|
[[ -d "$inprogress_file" ]] || continue
|
||||||
@@ -231,10 +231,10 @@ clean_time_machine_failed_backups() {
|
|||||||
note_activity
|
note_activity
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if ! command -v tmutil >/dev/null 2>&1; then
|
if ! command -v tmutil > /dev/null 2>&1; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if tmutil delete "$inprogress_file" 2>/dev/null; then
|
if tmutil delete "$inprogress_file" 2> /dev/null; then
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Incomplete APFS backup in $bundle_name: $backup_name ${GREEN}($size_human)${NC}"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Incomplete APFS backup in $bundle_name: $backup_name ${GREEN}($size_human)${NC}"
|
||||||
((tm_cleaned++))
|
((tm_cleaned++))
|
||||||
((files_cleaned++))
|
((files_cleaned++))
|
||||||
@@ -244,7 +244,7 @@ clean_time_machine_failed_backups() {
|
|||||||
else
|
else
|
||||||
echo -e " ${YELLOW}!${NC} Could not delete from bundle: $backup_name"
|
echo -e " ${YELLOW}!${NC} Could not delete from bundle: $backup_name"
|
||||||
fi
|
fi
|
||||||
done < <(run_with_timeout 15 find "$mounted_path" -maxdepth 3 -type d \( -name "*.inProgress" -o -name "*.inprogress" \) 2>/dev/null || true)
|
done < <(run_with_timeout 15 find "$mounted_path" -maxdepth 3 -type d \( -name "*.inProgress" -o -name "*.inprogress" \) 2> /dev/null || true)
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
@@ -260,20 +260,20 @@ clean_time_machine_failed_backups() {
|
|||||||
# Returns 2 if status cannot be determined
|
# Returns 2 if status cannot be determined
|
||||||
tm_is_running() {
|
tm_is_running() {
|
||||||
local st
|
local st
|
||||||
st="$(tmutil status 2>/dev/null)" || return 2
|
st="$(tmutil status 2> /dev/null)" || return 2
|
||||||
|
|
||||||
# If we can't find a Running field at all, treat as unknown.
|
# If we can't find a Running field at all, treat as unknown.
|
||||||
if ! grep -qE '(^|[[:space:]])("Running"|Running)[[:space:]]*=' <<<"$st"; then
|
if ! grep -qE '(^|[[:space:]])("Running"|Running)[[:space:]]*=' <<< "$st"; then
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Match: Running = 1; OR "Running" = 1 (with or without trailing ;)
|
# Match: Running = 1; OR "Running" = 1 (with or without trailing ;)
|
||||||
grep -qE '(^|[[:space:]])("Running"|Running)[[:space:]]*=[[:space:]]*1([[:space:]]*;|$)' <<<"$st"
|
grep -qE '(^|[[:space:]])("Running"|Running)[[:space:]]*=[[:space:]]*1([[:space:]]*;|$)' <<< "$st"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Local APFS snapshots (keep the most recent).
|
# Local APFS snapshots (keep the most recent).
|
||||||
clean_local_snapshots() {
|
clean_local_snapshots() {
|
||||||
if ! command -v tmutil >/dev/null 2>&1; then
|
if ! command -v tmutil > /dev/null 2>&1; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -292,7 +292,7 @@ clean_local_snapshots() {
|
|||||||
|
|
||||||
start_section_spinner "Checking local snapshots..."
|
start_section_spinner "Checking local snapshots..."
|
||||||
local snapshot_list
|
local snapshot_list
|
||||||
snapshot_list=$(tmutil listlocalsnapshots / 2>/dev/null)
|
snapshot_list=$(tmutil listlocalsnapshots / 2> /dev/null)
|
||||||
stop_section_spinner
|
stop_section_spinner
|
||||||
[[ -z "$snapshot_list" ]] && return 0
|
[[ -z "$snapshot_list" ]] && return 0
|
||||||
local cleaned_count=0
|
local cleaned_count=0
|
||||||
@@ -305,14 +305,14 @@ clean_local_snapshots() {
|
|||||||
local snap_name="${BASH_REMATCH[0]}"
|
local snap_name="${BASH_REMATCH[0]}"
|
||||||
snapshots+=("$snap_name")
|
snapshots+=("$snap_name")
|
||||||
local date_str="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]} ${BASH_REMATCH[4]:0:2}:${BASH_REMATCH[4]:2:2}:${BASH_REMATCH[4]:4:2}"
|
local date_str="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]} ${BASH_REMATCH[4]:0:2}:${BASH_REMATCH[4]:2:2}:${BASH_REMATCH[4]:4:2}"
|
||||||
local snap_ts=$(date -j -f "%Y-%m-%d %H:%M:%S" "$date_str" "+%s" 2>/dev/null || echo "0")
|
local snap_ts=$(date -j -f "%Y-%m-%d %H:%M:%S" "$date_str" "+%s" 2> /dev/null || echo "0")
|
||||||
[[ "$snap_ts" == "0" ]] && continue
|
[[ "$snap_ts" == "0" ]] && continue
|
||||||
if [[ "$snap_ts" -gt "$newest_ts" ]]; then
|
if [[ "$snap_ts" -gt "$newest_ts" ]]; then
|
||||||
newest_ts="$snap_ts"
|
newest_ts="$snap_ts"
|
||||||
newest_name="$snap_name"
|
newest_name="$snap_name"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done <<<"$snapshot_list"
|
done <<< "$snapshot_list"
|
||||||
|
|
||||||
[[ ${#snapshots[@]} -eq 0 ]] && return 0
|
[[ ${#snapshots[@]} -eq 0 ]] && return 0
|
||||||
[[ -z "$newest_name" ]] && return 0
|
[[ -z "$newest_name" ]] && return 0
|
||||||
@@ -331,7 +331,7 @@ clean_local_snapshots() {
|
|||||||
echo -e " ${GRAY}The most recent snapshot will be kept.${NC}"
|
echo -e " ${GRAY}The most recent snapshot will be kept.${NC}"
|
||||||
echo -ne " ${PURPLE}${ICON_ARROW}${NC} Remove all local snapshots except the most recent one? ${GREEN}Enter${NC} continue, ${GRAY}Space${NC} skip: "
|
echo -ne " ${PURPLE}${ICON_ARROW}${NC} Remove all local snapshots except the most recent one? ${GREEN}Enter${NC} continue, ${GRAY}Space${NC} skip: "
|
||||||
local choice
|
local choice
|
||||||
if type read_key >/dev/null 2>&1; then
|
if type read_key > /dev/null 2>&1; then
|
||||||
choice=$(read_key)
|
choice=$(read_key)
|
||||||
else
|
else
|
||||||
IFS= read -r -s -n 1 choice || choice=""
|
IFS= read -r -s -n 1 choice || choice=""
|
||||||
@@ -356,7 +356,7 @@ clean_local_snapshots() {
|
|||||||
((cleaned_count++))
|
((cleaned_count++))
|
||||||
note_activity
|
note_activity
|
||||||
else
|
else
|
||||||
if sudo tmutil deletelocalsnapshots "${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}-${BASH_REMATCH[4]}" >/dev/null 2>&1; then
|
if sudo tmutil deletelocalsnapshots "${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}-${BASH_REMATCH[4]}" > /dev/null 2>&1; then
|
||||||
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Removed snapshot: $snap_name"
|
echo -e " ${GREEN}${ICON_SUCCESS}${NC} Removed snapshot: $snap_name"
|
||||||
((cleaned_count++))
|
((cleaned_count++))
|
||||||
note_activity
|
note_activity
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ clean_chrome_old_versions() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Match the exact Chrome process name to avoid false positives
|
# Match the exact Chrome process name to avoid false positives
|
||||||
if pgrep -x "Google Chrome" >/dev/null 2>&1; then
|
if pgrep -x "Google Chrome" > /dev/null 2>&1; then
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Google Chrome running · old versions cleanup skipped"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Google Chrome running · old versions cleanup skipped"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -39,7 +39,7 @@ clean_chrome_old_versions() {
|
|||||||
[[ -L "$current_link" ]] || continue
|
[[ -L "$current_link" ]] || continue
|
||||||
|
|
||||||
local current_version
|
local current_version
|
||||||
current_version=$(readlink "$current_link" 2>/dev/null || true)
|
current_version=$(readlink "$current_link" 2> /dev/null || true)
|
||||||
current_version="${current_version##*/}"
|
current_version="${current_version##*/}"
|
||||||
[[ -n "$current_version" ]] || continue
|
[[ -n "$current_version" ]] || continue
|
||||||
|
|
||||||
@@ -69,9 +69,9 @@ clean_chrome_old_versions() {
|
|||||||
cleaned_any=true
|
cleaned_any=true
|
||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
if has_sudo_session; then
|
if has_sudo_session; then
|
||||||
safe_sudo_remove "$dir" >/dev/null 2>&1 || true
|
safe_sudo_remove "$dir" > /dev/null 2>&1 || true
|
||||||
else
|
else
|
||||||
safe_remove "$dir" true >/dev/null 2>&1 || true
|
safe_remove "$dir" true > /dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -100,7 +100,7 @@ clean_edge_old_versions() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Match the exact Edge process name to avoid false positives (e.g., Microsoft Teams)
|
# Match the exact Edge process name to avoid false positives (e.g., Microsoft Teams)
|
||||||
if pgrep -x "Microsoft Edge" >/dev/null 2>&1; then
|
if pgrep -x "Microsoft Edge" > /dev/null 2>&1; then
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Microsoft Edge running · old versions cleanup skipped"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Microsoft Edge running · old versions cleanup skipped"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -119,7 +119,7 @@ clean_edge_old_versions() {
|
|||||||
[[ -L "$current_link" ]] || continue
|
[[ -L "$current_link" ]] || continue
|
||||||
|
|
||||||
local current_version
|
local current_version
|
||||||
current_version=$(readlink "$current_link" 2>/dev/null || true)
|
current_version=$(readlink "$current_link" 2> /dev/null || true)
|
||||||
current_version="${current_version##*/}"
|
current_version="${current_version##*/}"
|
||||||
[[ -n "$current_version" ]] || continue
|
[[ -n "$current_version" ]] || continue
|
||||||
|
|
||||||
@@ -149,9 +149,9 @@ clean_edge_old_versions() {
|
|||||||
cleaned_any=true
|
cleaned_any=true
|
||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
if has_sudo_session; then
|
if has_sudo_session; then
|
||||||
safe_sudo_remove "$dir" >/dev/null 2>&1 || true
|
safe_sudo_remove "$dir" > /dev/null 2>&1 || true
|
||||||
else
|
else
|
||||||
safe_remove "$dir" true >/dev/null 2>&1 || true
|
safe_remove "$dir" true > /dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -177,7 +177,7 @@ clean_edge_updater_old_versions() {
|
|||||||
local updater_dir="$HOME/Library/Application Support/Microsoft/EdgeUpdater/apps/msedge-stable"
|
local updater_dir="$HOME/Library/Application Support/Microsoft/EdgeUpdater/apps/msedge-stable"
|
||||||
[[ -d "$updater_dir" ]] || return 0
|
[[ -d "$updater_dir" ]] || return 0
|
||||||
|
|
||||||
if pgrep -x "Microsoft Edge" >/dev/null 2>&1; then
|
if pgrep -x "Microsoft Edge" > /dev/null 2>&1; then
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Microsoft Edge running · updater cleanup skipped"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Microsoft Edge running · updater cleanup skipped"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -215,7 +215,7 @@ clean_edge_updater_old_versions() {
|
|||||||
((cleaned_count++))
|
((cleaned_count++))
|
||||||
cleaned_any=true
|
cleaned_any=true
|
||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
safe_remove "$dir" true >/dev/null 2>&1 || true
|
safe_remove "$dir" true > /dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -242,20 +242,20 @@ scan_external_volumes() {
|
|||||||
[[ -d "$volume" && -w "$volume" && ! -L "$volume" ]] || continue
|
[[ -d "$volume" && -w "$volume" && ! -L "$volume" ]] || continue
|
||||||
[[ "$volume" == "/" || "$volume" == "/Volumes/Macintosh HD" ]] && continue
|
[[ "$volume" == "/" || "$volume" == "/Volumes/Macintosh HD" ]] && continue
|
||||||
local protocol=""
|
local protocol=""
|
||||||
protocol=$(run_with_timeout 1 command diskutil info "$volume" 2>/dev/null | grep -i "Protocol:" | awk '{print $2}' || echo "")
|
protocol=$(run_with_timeout 1 command diskutil info "$volume" 2> /dev/null | grep -i "Protocol:" | awk '{print $2}' || echo "")
|
||||||
case "$protocol" in
|
case "$protocol" in
|
||||||
SMB | NFS | AFP | CIFS | WebDAV)
|
SMB | NFS | AFP | CIFS | WebDAV)
|
||||||
network_volumes+=("$volume")
|
network_volumes+=("$volume")
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
local fs_type=""
|
local fs_type=""
|
||||||
fs_type=$(run_with_timeout 1 command df -T "$volume" 2>/dev/null | tail -1 | awk '{print $2}' || echo "")
|
fs_type=$(run_with_timeout 1 command df -T "$volume" 2> /dev/null | tail -1 | awk '{print $2}' || echo "")
|
||||||
case "$fs_type" in
|
case "$fs_type" in
|
||||||
nfs | smbfs | afpfs | cifs | webdav)
|
nfs | smbfs | afpfs | cifs | webdav)
|
||||||
network_volumes+=("$volume")
|
network_volumes+=("$volume")
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
candidate_volumes+=("$volume")
|
candidate_volumes+=("$volume")
|
||||||
done
|
done
|
||||||
@@ -275,7 +275,7 @@ scan_external_volumes() {
|
|||||||
if [[ -d "$volume_trash" && "$DRY_RUN" != "true" ]] && ! is_path_whitelisted "$volume_trash"; then
|
if [[ -d "$volume_trash" && "$DRY_RUN" != "true" ]] && ! is_path_whitelisted "$volume_trash"; then
|
||||||
while IFS= read -r -d '' item; do
|
while IFS= read -r -d '' item; do
|
||||||
safe_remove "$item" true || true
|
safe_remove "$item" true || true
|
||||||
done < <(command find "$volume_trash" -mindepth 1 -maxdepth 1 -print0 2>/dev/null || true)
|
done < <(command find "$volume_trash" -mindepth 1 -maxdepth 1 -print0 2> /dev/null || true)
|
||||||
fi
|
fi
|
||||||
if [[ "$PROTECT_FINDER_METADATA" != "true" ]]; then
|
if [[ "$PROTECT_FINDER_METADATA" != "true" ]]; then
|
||||||
clean_ds_store_tree "$volume" "$(basename "$volume") volume (.DS_Store)"
|
clean_ds_store_tree "$volume" "$(basename "$volume") volume (.DS_Store)"
|
||||||
@@ -362,7 +362,7 @@ clean_mail_downloads() {
|
|||||||
((cleaned_kb += file_size_kb))
|
((cleaned_kb += file_size_kb))
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done < <(command find "$target_path" -type f -mtime +"$mail_age_days" -print0 2>/dev/null || true)
|
done < <(command find "$target_path" -type f -mtime +"$mail_age_days" -print0 2> /dev/null || true)
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [[ $count -gt 0 ]]; then
|
if [[ $count -gt 0 ]]; then
|
||||||
@@ -420,7 +420,7 @@ process_container_cache() {
|
|||||||
local cache_dir="$container_dir/Data/Library/Caches"
|
local cache_dir="$container_dir/Data/Library/Caches"
|
||||||
[[ -d "$cache_dir" ]] || return 0
|
[[ -d "$cache_dir" ]] || return 0
|
||||||
# Fast non-empty check.
|
# Fast non-empty check.
|
||||||
if find "$cache_dir" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep -q .; then
|
if find "$cache_dir" -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q .; then
|
||||||
local size=$(get_path_size_kb "$cache_dir")
|
local size=$(get_path_size_kb "$cache_dir")
|
||||||
((total_size += size))
|
((total_size += size))
|
||||||
found_any=true
|
found_any=true
|
||||||
@@ -451,7 +451,7 @@ clean_browsers() {
|
|||||||
safe_clean ~/Library/Caches/company.thebrowser.dia/* "Dia cache"
|
safe_clean ~/Library/Caches/company.thebrowser.dia/* "Dia cache"
|
||||||
safe_clean ~/Library/Caches/BraveSoftware/Brave-Browser/* "Brave cache"
|
safe_clean ~/Library/Caches/BraveSoftware/Brave-Browser/* "Brave cache"
|
||||||
local firefox_running=false
|
local firefox_running=false
|
||||||
if pgrep -x "Firefox" >/dev/null 2>&1; then
|
if pgrep -x "Firefox" > /dev/null 2>&1; then
|
||||||
firefox_running=true
|
firefox_running=true
|
||||||
fi
|
fi
|
||||||
if [[ "$firefox_running" == "true" ]]; then
|
if [[ "$firefox_running" == "true" ]]; then
|
||||||
@@ -504,7 +504,7 @@ clean_virtualization_tools() {
|
|||||||
}
|
}
|
||||||
# Application Support logs/caches.
|
# Application Support logs/caches.
|
||||||
clean_application_support_logs() {
|
clean_application_support_logs() {
|
||||||
if [[ ! -d "$HOME/Library/Application Support" ]] || ! ls "$HOME/Library/Application Support" >/dev/null 2>&1; then
|
if [[ ! -d "$HOME/Library/Application Support" ]] || ! ls "$HOME/Library/Application Support" > /dev/null 2>&1; then
|
||||||
note_activity
|
note_activity
|
||||||
echo -e " ${YELLOW}${ICON_WARNING}${NC} Skipped: No permission to access Application Support"
|
echo -e " ${YELLOW}${ICON_WARNING}${NC} Skipped: No permission to access Application Support"
|
||||||
return 0
|
return 0
|
||||||
@@ -536,7 +536,7 @@ clean_application_support_logs() {
|
|||||||
local -a start_candidates=("$app_dir/log" "$app_dir/logs" "$app_dir/activitylog" "$app_dir/Cache/Cache_Data" "$app_dir/Crashpad/completed")
|
local -a start_candidates=("$app_dir/log" "$app_dir/logs" "$app_dir/activitylog" "$app_dir/Cache/Cache_Data" "$app_dir/Crashpad/completed")
|
||||||
for candidate in "${start_candidates[@]}"; do
|
for candidate in "${start_candidates[@]}"; do
|
||||||
if [[ -d "$candidate" ]]; then
|
if [[ -d "$candidate" ]]; then
|
||||||
if find "$candidate" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep -q .; then
|
if find "$candidate" -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q .; then
|
||||||
local size=$(get_path_size_kb "$candidate")
|
local size=$(get_path_size_kb "$candidate")
|
||||||
((total_size += size))
|
((total_size += size))
|
||||||
((cleaned_count++))
|
((cleaned_count++))
|
||||||
@@ -544,7 +544,7 @@ clean_application_support_logs() {
|
|||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
for item in "$candidate"/*; do
|
for item in "$candidate"/*; do
|
||||||
[[ -e "$item" ]] || continue
|
[[ -e "$item" ]] || continue
|
||||||
safe_remove "$item" true >/dev/null 2>&1 || true
|
safe_remove "$item" true > /dev/null 2>&1 || true
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -560,7 +560,7 @@ clean_application_support_logs() {
|
|||||||
local -a gc_candidates=("$container_path/Logs" "$container_path/Library/Logs")
|
local -a gc_candidates=("$container_path/Logs" "$container_path/Library/Logs")
|
||||||
for candidate in "${gc_candidates[@]}"; do
|
for candidate in "${gc_candidates[@]}"; do
|
||||||
if [[ -d "$candidate" ]]; then
|
if [[ -d "$candidate" ]]; then
|
||||||
if find "$candidate" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null | grep -q .; then
|
if find "$candidate" -mindepth 1 -maxdepth 1 -print -quit 2> /dev/null | grep -q .; then
|
||||||
local size=$(get_path_size_kb "$candidate")
|
local size=$(get_path_size_kb "$candidate")
|
||||||
((total_size += size))
|
((total_size += size))
|
||||||
((cleaned_count++))
|
((cleaned_count++))
|
||||||
@@ -568,7 +568,7 @@ clean_application_support_logs() {
|
|||||||
if [[ "$DRY_RUN" != "true" ]]; then
|
if [[ "$DRY_RUN" != "true" ]]; then
|
||||||
for item in "$candidate"/*; do
|
for item in "$candidate"/*; do
|
||||||
[[ -e "$item" ]] || continue
|
[[ -e "$item" ]] || continue
|
||||||
safe_remove "$item" true >/dev/null 2>&1 || true
|
safe_remove "$item" true > /dev/null 2>&1 || true
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -597,7 +597,7 @@ check_ios_device_backups() {
|
|||||||
if [[ -d "$backup_dir" ]]; then
|
if [[ -d "$backup_dir" ]]; then
|
||||||
local backup_kb=$(get_path_size_kb "$backup_dir")
|
local backup_kb=$(get_path_size_kb "$backup_dir")
|
||||||
if [[ -n "${backup_kb:-}" && "$backup_kb" -gt 102400 ]]; then
|
if [[ -n "${backup_kb:-}" && "$backup_kb" -gt 102400 ]]; then
|
||||||
local backup_human=$(command du -sh "$backup_dir" 2>/dev/null | awk '{print $1}')
|
local backup_human=$(command du -sh "$backup_dir" 2> /dev/null | awk '{print $1}')
|
||||||
if [[ -n "$backup_human" ]]; then
|
if [[ -n "$backup_human" ]]; then
|
||||||
note_activity
|
note_activity
|
||||||
echo -e " Found ${GREEN}${backup_human}${NC} iOS backups"
|
echo -e " Found ${GREEN}${backup_human}${NC} iOS backups"
|
||||||
|
|||||||
200
lib/core/ui.sh
200
lib/core/ui.sh
@@ -168,47 +168,47 @@ read_key() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
case "$key" in
|
case "$key" in
|
||||||
$'\n' | $'\r') echo "ENTER" ;;
|
$'\n' | $'\r') echo "ENTER" ;;
|
||||||
$'\x7f' | $'\x08') echo "DELETE" ;;
|
$'\x7f' | $'\x08') echo "DELETE" ;;
|
||||||
$'\x1b')
|
$'\x1b')
|
||||||
# Check if this is an escape sequence (arrow keys) or ESC key
|
# Check if this is an escape sequence (arrow keys) or ESC key
|
||||||
if IFS= read -r -s -n 1 -t 0.1 rest 2>/dev/null; then
|
if IFS= read -r -s -n 1 -t 0.1 rest 2> /dev/null; then
|
||||||
if [[ "$rest" == "[" ]]; then
|
if [[ "$rest" == "[" ]]; then
|
||||||
if IFS= read -r -s -n 1 -t 0.1 rest2 2>/dev/null; then
|
if IFS= read -r -s -n 1 -t 0.1 rest2 2> /dev/null; then
|
||||||
case "$rest2" in
|
case "$rest2" in
|
||||||
"A") echo "UP" ;;
|
"A") echo "UP" ;;
|
||||||
"B") echo "DOWN" ;;
|
"B") echo "DOWN" ;;
|
||||||
"C") echo "RIGHT" ;;
|
"C") echo "RIGHT" ;;
|
||||||
"D") echo "LEFT" ;;
|
"D") echo "LEFT" ;;
|
||||||
"3")
|
"3")
|
||||||
IFS= read -r -s -n 1 -t 0.1 rest3 2>/dev/null
|
IFS= read -r -s -n 1 -t 0.1 rest3 2> /dev/null
|
||||||
[[ "$rest3" == "~" ]] && echo "DELETE" || echo "OTHER"
|
[[ "$rest3" == "~" ]] && echo "DELETE" || echo "OTHER"
|
||||||
;;
|
;;
|
||||||
*) echo "OTHER" ;;
|
*) echo "OTHER" ;;
|
||||||
esac
|
esac
|
||||||
else echo "QUIT"; fi
|
else echo "QUIT"; fi
|
||||||
elif [[ "$rest" == "O" ]]; then
|
elif [[ "$rest" == "O" ]]; then
|
||||||
if IFS= read -r -s -n 1 -t 0.1 rest2 2>/dev/null; then
|
if IFS= read -r -s -n 1 -t 0.1 rest2 2> /dev/null; then
|
||||||
case "$rest2" in
|
case "$rest2" in
|
||||||
"A") echo "UP" ;;
|
"A") echo "UP" ;;
|
||||||
"B") echo "DOWN" ;;
|
"B") echo "DOWN" ;;
|
||||||
"C") echo "RIGHT" ;;
|
"C") echo "RIGHT" ;;
|
||||||
"D") echo "LEFT" ;;
|
"D") echo "LEFT" ;;
|
||||||
*) echo "OTHER" ;;
|
*) echo "OTHER" ;;
|
||||||
esac
|
esac
|
||||||
else echo "OTHER"; fi
|
else echo "OTHER"; fi
|
||||||
|
else
|
||||||
|
# Not an escape sequence, it's ESC key
|
||||||
|
echo "QUIT"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Not an escape sequence, it's ESC key
|
# No following characters, it's ESC key
|
||||||
echo "QUIT"
|
echo "QUIT"
|
||||||
fi
|
fi
|
||||||
else
|
;;
|
||||||
# No following characters, it's ESC key
|
' ') echo "SPACE" ;; # Allow space in filter mode for selection
|
||||||
echo "QUIT"
|
[[:print:]]) echo "CHAR:$key" ;;
|
||||||
fi
|
*) echo "OTHER" ;;
|
||||||
;;
|
|
||||||
' ') echo "SPACE" ;; # Allow space in filter mode for selection
|
|
||||||
[[:print:]]) echo "CHAR:$key" ;;
|
|
||||||
*) echo "OTHER" ;;
|
|
||||||
esac
|
esac
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -218,53 +218,53 @@ read_key() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
case "$key" in
|
case "$key" in
|
||||||
$'\n' | $'\r') echo "ENTER" ;;
|
$'\n' | $'\r') echo "ENTER" ;;
|
||||||
' ') echo "SPACE" ;;
|
' ') echo "SPACE" ;;
|
||||||
'/') echo "FILTER" ;;
|
'/') echo "FILTER" ;;
|
||||||
'q' | 'Q') echo "QUIT" ;;
|
'q' | 'Q') echo "QUIT" ;;
|
||||||
'R') echo "RETRY" ;;
|
'R') echo "RETRY" ;;
|
||||||
'm' | 'M') echo "MORE" ;;
|
'm' | 'M') echo "MORE" ;;
|
||||||
'u' | 'U') echo "UPDATE" ;;
|
'u' | 'U') echo "UPDATE" ;;
|
||||||
't' | 'T') echo "TOUCHID" ;;
|
't' | 'T') echo "TOUCHID" ;;
|
||||||
'j' | 'J') echo "DOWN" ;;
|
'j' | 'J') echo "DOWN" ;;
|
||||||
'k' | 'K') echo "UP" ;;
|
'k' | 'K') echo "UP" ;;
|
||||||
'h' | 'H') echo "LEFT" ;;
|
'h' | 'H') echo "LEFT" ;;
|
||||||
'l' | 'L') echo "RIGHT" ;;
|
'l' | 'L') echo "RIGHT" ;;
|
||||||
$'\x03') echo "QUIT" ;;
|
$'\x03') echo "QUIT" ;;
|
||||||
$'\x7f' | $'\x08') echo "DELETE" ;;
|
$'\x7f' | $'\x08') echo "DELETE" ;;
|
||||||
$'\x1b')
|
$'\x1b')
|
||||||
if IFS= read -r -s -n 1 -t 1 rest 2>/dev/null; then
|
if IFS= read -r -s -n 1 -t 1 rest 2> /dev/null; then
|
||||||
if [[ "$rest" == "[" ]]; then
|
if [[ "$rest" == "[" ]]; then
|
||||||
if IFS= read -r -s -n 1 -t 1 rest2 2>/dev/null; then
|
if IFS= read -r -s -n 1 -t 1 rest2 2> /dev/null; then
|
||||||
case "$rest2" in
|
case "$rest2" in
|
||||||
"A") echo "UP" ;; "B") echo "DOWN" ;;
|
"A") echo "UP" ;; "B") echo "DOWN" ;;
|
||||||
"C") echo "RIGHT" ;; "D") echo "LEFT" ;;
|
"C") echo "RIGHT" ;; "D") echo "LEFT" ;;
|
||||||
"3")
|
"3")
|
||||||
IFS= read -r -s -n 1 -t 1 rest3 2>/dev/null
|
IFS= read -r -s -n 1 -t 1 rest3 2> /dev/null
|
||||||
[[ "$rest3" == "~" ]] && echo "DELETE" || echo "OTHER"
|
[[ "$rest3" == "~" ]] && echo "DELETE" || echo "OTHER"
|
||||||
;;
|
;;
|
||||||
*) echo "OTHER" ;;
|
*) echo "OTHER" ;;
|
||||||
esac
|
esac
|
||||||
else echo "QUIT"; fi
|
else echo "QUIT"; fi
|
||||||
elif [[ "$rest" == "O" ]]; then
|
elif [[ "$rest" == "O" ]]; then
|
||||||
if IFS= read -r -s -n 1 -t 1 rest2 2>/dev/null; then
|
if IFS= read -r -s -n 1 -t 1 rest2 2> /dev/null; then
|
||||||
case "$rest2" in
|
case "$rest2" in
|
||||||
"A") echo "UP" ;; "B") echo "DOWN" ;;
|
"A") echo "UP" ;; "B") echo "DOWN" ;;
|
||||||
"C") echo "RIGHT" ;; "D") echo "LEFT" ;;
|
"C") echo "RIGHT" ;; "D") echo "LEFT" ;;
|
||||||
*) echo "OTHER" ;;
|
*) echo "OTHER" ;;
|
||||||
esac
|
esac
|
||||||
|
else echo "OTHER"; fi
|
||||||
else echo "OTHER"; fi
|
else echo "OTHER"; fi
|
||||||
else echo "OTHER"; fi
|
else echo "QUIT"; fi
|
||||||
else echo "QUIT"; fi
|
;;
|
||||||
;;
|
[[:print:]]) echo "CHAR:$key" ;;
|
||||||
[[:print:]]) echo "CHAR:$key" ;;
|
*) echo "OTHER" ;;
|
||||||
*) echo "OTHER" ;;
|
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
drain_pending_input() {
|
drain_pending_input() {
|
||||||
local drained=0
|
local drained=0
|
||||||
while IFS= read -r -s -n 1 -t 0.01 _ 2>/dev/null; do
|
while IFS= read -r -s -n 1 -t 0.01 _ 2> /dev/null; do
|
||||||
((drained++))
|
((drained++))
|
||||||
[[ $drained -gt 100 ]] && break
|
[[ $drained -gt 100 ]] && break
|
||||||
done
|
done
|
||||||
@@ -288,7 +288,7 @@ INLINE_SPINNER_PID=""
|
|||||||
INLINE_SPINNER_STOP_FILE=""
|
INLINE_SPINNER_STOP_FILE=""
|
||||||
|
|
||||||
start_inline_spinner() {
|
start_inline_spinner() {
|
||||||
stop_inline_spinner 2>/dev/null || true
|
stop_inline_spinner 2> /dev/null || true
|
||||||
local message="$1"
|
local message="$1"
|
||||||
|
|
||||||
if [[ -t 1 ]]; then
|
if [[ -t 1 ]]; then
|
||||||
@@ -312,11 +312,11 @@ start_inline_spinner() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Clean up stop file before exiting
|
# Clean up stop file before exiting
|
||||||
rm -f "$stop_file" 2>/dev/null || true
|
rm -f "$stop_file" 2> /dev/null || true
|
||||||
exit 0
|
exit 0
|
||||||
) &
|
) &
|
||||||
INLINE_SPINNER_PID=$!
|
INLINE_SPINNER_PID=$!
|
||||||
disown 2>/dev/null || true
|
disown 2> /dev/null || true
|
||||||
else
|
else
|
||||||
echo -n " ${BLUE}|${NC} $message" >&2 || true
|
echo -n " ${BLUE}|${NC} $message" >&2 || true
|
||||||
fi
|
fi
|
||||||
@@ -326,25 +326,25 @@ stop_inline_spinner() {
|
|||||||
if [[ -n "$INLINE_SPINNER_PID" ]]; then
|
if [[ -n "$INLINE_SPINNER_PID" ]]; then
|
||||||
# Cooperative stop: create stop file to signal spinner to exit
|
# Cooperative stop: create stop file to signal spinner to exit
|
||||||
if [[ -n "$INLINE_SPINNER_STOP_FILE" ]]; then
|
if [[ -n "$INLINE_SPINNER_STOP_FILE" ]]; then
|
||||||
touch "$INLINE_SPINNER_STOP_FILE" 2>/dev/null || true
|
touch "$INLINE_SPINNER_STOP_FILE" 2> /dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Wait briefly for cooperative exit
|
# Wait briefly for cooperative exit
|
||||||
local wait_count=0
|
local wait_count=0
|
||||||
while kill -0 "$INLINE_SPINNER_PID" 2>/dev/null && [[ $wait_count -lt 5 ]]; do
|
while kill -0 "$INLINE_SPINNER_PID" 2> /dev/null && [[ $wait_count -lt 5 ]]; do
|
||||||
sleep 0.05 2>/dev/null || true
|
sleep 0.05 2> /dev/null || true
|
||||||
((wait_count++))
|
((wait_count++))
|
||||||
done
|
done
|
||||||
|
|
||||||
# Only use SIGKILL as last resort if process is stuck
|
# Only use SIGKILL as last resort if process is stuck
|
||||||
if kill -0 "$INLINE_SPINNER_PID" 2>/dev/null; then
|
if kill -0 "$INLINE_SPINNER_PID" 2> /dev/null; then
|
||||||
kill -KILL "$INLINE_SPINNER_PID" 2>/dev/null || true
|
kill -KILL "$INLINE_SPINNER_PID" 2> /dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wait "$INLINE_SPINNER_PID" 2>/dev/null || true
|
wait "$INLINE_SPINNER_PID" 2> /dev/null || true
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
rm -f "$INLINE_SPINNER_STOP_FILE" 2>/dev/null || true
|
rm -f "$INLINE_SPINNER_STOP_FILE" 2> /dev/null || true
|
||||||
INLINE_SPINNER_PID=""
|
INLINE_SPINNER_PID=""
|
||||||
INLINE_SPINNER_STOP_FILE=""
|
INLINE_SPINNER_STOP_FILE=""
|
||||||
|
|
||||||
@@ -361,8 +361,8 @@ with_spinner() {
|
|||||||
start_inline_spinner "$msg"
|
start_inline_spinner "$msg"
|
||||||
local exit_code=0
|
local exit_code=0
|
||||||
if [[ -n "${MOLE_TIMEOUT_BIN:-}" ]]; then
|
if [[ -n "${MOLE_TIMEOUT_BIN:-}" ]]; then
|
||||||
"$MOLE_TIMEOUT_BIN" "$timeout" "$@" >/dev/null 2>&1 || exit_code=$?
|
"$MOLE_TIMEOUT_BIN" "$timeout" "$@" > /dev/null 2>&1 || exit_code=$?
|
||||||
else "$@" >/dev/null 2>&1 || exit_code=$?; fi
|
else "$@" > /dev/null 2>&1 || exit_code=$?; fi
|
||||||
stop_inline_spinner "$msg"
|
stop_inline_spinner "$msg"
|
||||||
return $exit_code
|
return $exit_code
|
||||||
}
|
}
|
||||||
@@ -379,14 +379,14 @@ format_last_used_summary() {
|
|||||||
local value="$1"
|
local value="$1"
|
||||||
|
|
||||||
case "$value" in
|
case "$value" in
|
||||||
"" | "Unknown")
|
"" | "Unknown")
|
||||||
echo "Unknown"
|
echo "Unknown"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
"Never" | "Recent" | "Today" | "Yesterday" | "This year" | "Old")
|
"Never" | "Recent" | "Today" | "Yesterday" | "This year" | "Old")
|
||||||
echo "$value"
|
echo "$value"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ $value =~ ^([0-9]+)[[:space:]]+days?\ ago$ ]]; then
|
if [[ $value =~ ^([0-9]+)[[:space:]]+days?\ ago$ ]]; then
|
||||||
@@ -444,7 +444,7 @@ has_full_disk_access() {
|
|||||||
if [[ -e "$test_path" ]]; then
|
if [[ -e "$test_path" ]]; then
|
||||||
tested_count=$((tested_count + 1))
|
tested_count=$((tested_count + 1))
|
||||||
# Try to stat the ACTUAL protected path - this requires FDA
|
# Try to stat the ACTUAL protected path - this requires FDA
|
||||||
if stat "$test_path" >/dev/null 2>&1; then
|
if stat "$test_path" > /dev/null 2>&1; then
|
||||||
accessible_count=$((accessible_count + 1))
|
accessible_count=$((accessible_count + 1))
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user