1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 14:26:46 +00:00

feat: Add configurable project cleanup depth, refine interactive menu display, and sanitize uninstall app names.

This commit is contained in:
Tw93
2025-12-22 18:53:48 +08:00
parent bf04f752d2
commit 9a942a2770
3 changed files with 54 additions and 13 deletions

View File

@@ -149,6 +149,17 @@ scan_applications() {
local bundle_name
bundle_name=$(plutil -extract CFBundleName raw "$app_path/Contents/Info.plist" 2> /dev/null)
# Sanitize metadata values (prevent paths, pipes, and newlines)
if [[ "$md_display_name" == /* ]]; then md_display_name=""; fi
md_display_name="${md_display_name//|/-}"
md_display_name="${md_display_name//[$'\t\r\n']/}"
bundle_display_name="${bundle_display_name//|/-}"
bundle_display_name="${bundle_display_name//[$'\t\r\n']/}"
bundle_name="${bundle_name//|/-}"
bundle_name="${bundle_name//[$'\t\r\n']/}"
# Select best available name
if [[ -n "$md_display_name" && "$md_display_name" != "(null)" && "$md_display_name" != "$app_name" ]]; then
display_name="$md_display_name"
@@ -159,6 +170,14 @@ scan_applications() {
fi
fi
# Final safety check: if display_name looks like a path, revert to app_name
if [[ "$display_name" == /* ]]; then
display_name="$app_name"
fi
# Ensure no pipes or newlines in final display name
display_name="${display_name//|/-}"
display_name="${display_name//[$'\t\r\n']/}"
# Calculate app size (in parallel for performance)
local app_size="N/A"
local app_size_kb="0"

View File

@@ -26,6 +26,10 @@ readonly PURGE_TARGETS=(
# Minimum age in days before considering for cleanup
readonly MIN_AGE_DAYS=7
# Scan depth defaults (relative to search root)
readonly PURGE_MIN_DEPTH_DEFAULT=2
readonly PURGE_MAX_DEPTH_DEFAULT=8
# Search paths (only project directories)
readonly PURGE_SEARCH_PATHS=(
"$HOME/www"
@@ -71,6 +75,18 @@ is_safe_project_artifact() {
scan_purge_targets() {
local search_path="$1"
local output_file="$2"
local min_depth="${MOLE_PURGE_MIN_DEPTH:-$PURGE_MIN_DEPTH_DEFAULT}"
local max_depth="${MOLE_PURGE_MAX_DEPTH:-$PURGE_MAX_DEPTH_DEFAULT}"
if [[ ! "$min_depth" =~ ^[0-9]+$ ]]; then
min_depth="$PURGE_MIN_DEPTH_DEFAULT"
fi
if [[ ! "$max_depth" =~ ^[0-9]+$ ]]; then
max_depth="$PURGE_MAX_DEPTH_DEFAULT"
fi
if [[ "$max_depth" -lt "$min_depth" ]]; then
max_depth="$min_depth"
fi
if [[ ! -d "$search_path" ]]; then
return
@@ -83,8 +99,8 @@ scan_purge_targets() {
"--hidden"
"--no-ignore"
"--type" "d"
"--min-depth" "2"
"--max-depth" "5"
"--min-depth" "$min_depth"
"--max-depth" "$max_depth"
"--threads" "4"
"--exclude" ".git"
"--exclude" "Library"
@@ -152,7 +168,7 @@ scan_purge_targets() {
((i++))
done
command find "$search_path" -mindepth 2 -maxdepth 5 -type d \
command find "$search_path" -mindepth "$min_depth" -maxdepth "$max_depth" -type d \
\( "${find_expr[@]}" \) 2> /dev/null | while IFS= read -r item; do
if is_safe_project_artifact "$item" "$search_path"; then
@@ -226,6 +242,7 @@ get_dir_size_kb() {
select_purge_categories() {
local -a categories=("$@")
local total_items=${#categories[@]}
local clear_line=$'\r\033[2K'
if [[ $total_items -eq 0 ]]; then
return 1
@@ -265,7 +282,7 @@ select_purge_categories() {
}
draw_menu() {
printf "\033[H\033[2J"
printf "\033[H"
# Calculate total size of selected items for header
local selected_size=0
local selected_count=0
@@ -276,11 +293,12 @@ select_purge_categories() {
((selected_count++))
fi
done
local selected_gb=$(echo "scale=1; $selected_size/1024/1024" | bc)
local selected_gb
selected_gb=$(echo "scale=1; $selected_size/1024/1024" | bc)
printf '\n'
echo -e "${PURPLE_BOLD}Select Categories to Clean${NC} ${GRAY}- ${selected_gb}GB ($selected_count selected)${NC}"
echo ""
printf "%s\n" "$clear_line"
printf "%s${PURPLE_BOLD}Select Categories to Clean${NC} ${GRAY}- ${selected_gb}GB ($selected_count selected)${NC}\n" "$clear_line"
printf "%s\n" "$clear_line"
IFS=',' read -r -a recent_flags <<< "${PURGE_RECENT_CATEGORIES:-}"
for ((i = 0; i < total_items; i++)); do
@@ -291,14 +309,14 @@ select_purge_categories() {
[[ ${recent_flags[i]:-false} == "true" ]] && recent_marker=" ${GRAY}| Recent${NC}"
if [[ $i -eq $cursor_pos ]]; then
printf "\r\033[2K${CYAN}${ICON_ARROW} %s %s%s${NC}\n" "$checkbox" "${categories[i]}" "$recent_marker"
printf "%s${CYAN}${ICON_ARROW} %s %s%s${NC}\n" "$clear_line" "$checkbox" "${categories[i]}" "$recent_marker"
else
printf "\r\033[2K %s %s%s\n" "$checkbox" "${categories[i]}" "$recent_marker"
printf "%s %s %s%s\n" "$clear_line" "$checkbox" "${categories[i]}" "$recent_marker"
fi
done
echo ""
echo -e "${GRAY}↑↓ | Space Select | Enter Confirm | A All | I Invert | Q Quit${NC}"
printf "%s\n" "$clear_line"
printf "%s${GRAY}↑↓ | Space Select | Enter Confirm | A All | I Invert | Q Quit${NC}\n" "$clear_line"
}
trap restore_terminal EXIT
@@ -308,6 +326,10 @@ select_purge_categories() {
stty -echo -icanon intr ^C 2> /dev/null || true
hide_cursor
if [[ -t 1 ]]; then
clear_screen
fi
# Main loop
while true; do
draw_menu

2
mole
View File

@@ -22,7 +22,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/core/common.sh"
# Version info
VERSION="1.14.0"
VERSION="1.14.1"
MOLE_TAGLINE="Deep clean and optimize your Mac."
# Check TouchID configuration