mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 13:16:47 +00:00
🐛 Normalize output tags
This commit is contained in:
@@ -720,7 +720,7 @@ display_cleanup_suggestions() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo " ${YELLOW}Tip:${NC} Run 'mole clean' to perform cleanup operations"
|
echo " ${YELLOW}Tip:${NC} Run 'mole clean' to perform cleanup operations"
|
||||||
else
|
else
|
||||||
echo " ${GREEN}✓${NC} No obvious cleanup opportunities found"
|
echo " ${BLUE}✓${NC} No obvious cleanup opportunities found"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
@@ -1272,11 +1272,11 @@ scan_directory_contents_fast() {
|
|||||||
xargs -0 -n 1 -P "$num_jobs" sh -c '
|
xargs -0 -n 1 -P "$num_jobs" sh -c '
|
||||||
dir="$1"
|
dir="$1"
|
||||||
size=""
|
size=""
|
||||||
|
|
||||||
# Ultra-fast strategy: Try du with 1 second timeout only
|
# Ultra-fast strategy: Try du with 1 second timeout only
|
||||||
du -sk "$dir" 2>/dev/null > /tmp/mole_du_$$ &
|
du -sk "$dir" 2>/dev/null > /tmp/mole_du_$$ &
|
||||||
du_pid=$!
|
du_pid=$!
|
||||||
|
|
||||||
# Wait only 1 second (aggressive!)
|
# Wait only 1 second (aggressive!)
|
||||||
if ! sleep 1 || kill -0 $du_pid 2>/dev/null; then
|
if ! sleep 1 || kill -0 $du_pid 2>/dev/null; then
|
||||||
# Still running after 1s = large dir, kill it
|
# Still running after 1s = large dir, kill it
|
||||||
@@ -1289,7 +1289,7 @@ scan_directory_contents_fast() {
|
|||||||
size=$(cat /tmp/mole_du_$$ 2>/dev/null | cut -f1)
|
size=$(cat /tmp/mole_du_$$ 2>/dev/null | cut -f1)
|
||||||
rm -f /tmp/mole_du_$$ 2>/dev/null
|
rm -f /tmp/mole_du_$$ 2>/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If timeout or empty, use instant estimation
|
# If timeout or empty, use instant estimation
|
||||||
if [[ -z "$size" ]] || [[ "$size" -eq 0 ]]; then
|
if [[ -z "$size" ]] || [[ "$size" -eq 0 ]]; then
|
||||||
# Ultra-fast: count only immediate files (no recursion)
|
# Ultra-fast: count only immediate files (no recursion)
|
||||||
@@ -1297,7 +1297,7 @@ scan_directory_contents_fast() {
|
|||||||
size=$(find "$dir" -type f -maxdepth 1 -print0 2>/dev/null | \
|
size=$(find "$dir" -type f -maxdepth 1 -print0 2>/dev/null | \
|
||||||
xargs -0 stat -f%z 2>/dev/null | \
|
xargs -0 stat -f%z 2>/dev/null | \
|
||||||
awk "BEGIN{sum=0} {sum+=\$1} END{print int(sum/1024)}")
|
awk "BEGIN{sum=0} {sum+=\$1} END{print int(sum/1024)}")
|
||||||
|
|
||||||
# If still 0, mark as unknown but ensure it shows up
|
# If still 0, mark as unknown but ensure it shows up
|
||||||
[[ -z "$size" ]] || [[ "$size" -eq 0 ]] && size=1
|
[[ -z "$size" ]] || [[ "$size" -eq 0 ]] && size=1
|
||||||
fi
|
fi
|
||||||
@@ -1318,7 +1318,7 @@ scan_directory_contents_fast() {
|
|||||||
((i++))
|
((i++))
|
||||||
sleep 0.1 # Faster animation (100ms per frame)
|
sleep 0.1 # Faster animation (100ms per frame)
|
||||||
((tick++))
|
((tick++))
|
||||||
|
|
||||||
# Update elapsed seconds every 10 ticks (1 second)
|
# Update elapsed seconds every 10 ticks (1 second)
|
||||||
if [[ $((tick % 10)) -eq 0 ]]; then
|
if [[ $((tick % 10)) -eq 0 ]]; then
|
||||||
((elapsed++))
|
((elapsed++))
|
||||||
@@ -1343,7 +1343,7 @@ scan_directory_contents_fast() {
|
|||||||
# Wait for completion (non-blocking if already killed)
|
# Wait for completion (non-blocking if already killed)
|
||||||
wait "$file_pid" 2>/dev/null || true
|
wait "$file_pid" 2>/dev/null || true
|
||||||
wait "$dir_pid" 2>/dev/null || true
|
wait "$dir_pid" 2>/dev/null || true
|
||||||
|
|
||||||
# Small delay only if scan was very fast (let user see the spinner briefly)
|
# Small delay only if scan was very fast (let user see the spinner briefly)
|
||||||
if [[ "$show_progress" == "true" ]] && [[ ${elapsed:-0} -lt 1 ]]; then
|
if [[ "$show_progress" == "true" ]] && [[ ${elapsed:-0} -lt 1 ]]; then
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
@@ -1592,8 +1592,6 @@ interactive_drill_down() {
|
|||||||
# Ensure cursor is always hidden during navigation
|
# Ensure cursor is always hidden during navigation
|
||||||
printf "\033[?25l" >&2
|
printf "\033[?25l" >&2
|
||||||
|
|
||||||
# Drain any burst input (e.g. trackpad scroll converted to many arrow keys)
|
|
||||||
type drain_pending_input >/dev/null 2>&1 && drain_pending_input
|
|
||||||
# Only scan if needed (directory changed or refresh requested)
|
# Only scan if needed (directory changed or refresh requested)
|
||||||
if [[ "$need_scan" == "true" ]]; then
|
if [[ "$need_scan" == "true" ]]; then
|
||||||
# Generate cache key (use md5 hash of path)
|
# Generate cache key (use md5 hash of path)
|
||||||
@@ -1632,7 +1630,7 @@ interactive_drill_down() {
|
|||||||
has_calculating=false
|
has_calculating=false
|
||||||
need_scan=false
|
need_scan=false
|
||||||
wait_for_calc=false
|
wait_for_calc=false
|
||||||
|
|
||||||
# Reset scroll when entering new directory
|
# Reset scroll when entering new directory
|
||||||
scroll_offset=0
|
scroll_offset=0
|
||||||
|
|
||||||
@@ -1701,7 +1699,7 @@ interactive_drill_down() {
|
|||||||
local page_start=$scroll_offset
|
local page_start=$scroll_offset
|
||||||
local page_end=$((scroll_offset + max_show))
|
local page_end=$((scroll_offset + max_show))
|
||||||
[[ $page_end -gt $total_items ]] && page_end=$total_items
|
[[ $page_end -gt $total_items ]] && page_end=$total_items
|
||||||
|
|
||||||
local display_idx=0
|
local display_idx=0
|
||||||
local idx=0
|
local idx=0
|
||||||
for item_info in "${items[@]}"; do
|
for item_info in "${items[@]}"; do
|
||||||
@@ -1710,7 +1708,7 @@ interactive_drill_down() {
|
|||||||
((idx++))
|
((idx++))
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Stop if we've shown enough items for this page
|
# Stop if we've shown enough items for this page
|
||||||
if [[ $idx -ge $page_end ]]; then
|
if [[ $idx -ge $page_end ]]; then
|
||||||
break
|
break
|
||||||
@@ -1782,10 +1780,7 @@ interactive_drill_down() {
|
|||||||
# Output everything at once (single write = no flicker)
|
# Output everything at once (single write = no flicker)
|
||||||
printf "%b" "$output" >&2
|
printf "%b" "$output" >&2
|
||||||
|
|
||||||
# Drain any pending input to prevent escape sequence leakage
|
# Read key directly without draining (to preserve all user input)
|
||||||
drain_pending_input 2>/dev/null || true
|
|
||||||
|
|
||||||
# Read key (suppress any escape sequences that might leak)
|
|
||||||
local key
|
local key
|
||||||
key=$(read_key 2>/dev/null || echo "OTHER")
|
key=$(read_key 2>/dev/null || echo "OTHER")
|
||||||
|
|
||||||
@@ -1832,41 +1827,75 @@ interactive_drill_down() {
|
|||||||
need_scan=true
|
need_scan=true
|
||||||
else
|
else
|
||||||
# It's a file - open it for viewing
|
# It's a file - open it for viewing
|
||||||
# Exit alternate screen temporarily
|
|
||||||
printf "\033[?25h" # Show cursor
|
|
||||||
tput rmcup 2>/dev/null || true
|
|
||||||
|
|
||||||
# Try to open with system default viewer
|
|
||||||
local file_ext="${selected_path##*.}"
|
local file_ext="${selected_path##*.}"
|
||||||
|
local filename=$(basename "$selected_path")
|
||||||
local open_success=false
|
local open_success=false
|
||||||
|
|
||||||
# For text-like files, use less
|
# For text-like files, use less or fallback to open
|
||||||
case "$file_ext" in
|
case "$file_ext" in
|
||||||
txt|log|md|json|xml|yaml|yml|conf|cfg|ini|sh|bash|zsh|py|js|ts|go|rs|c|cpp|h|java|rb|php|html|css|sql)
|
txt|log|md|json|xml|yaml|yml|conf|cfg|ini|sh|bash|zsh|py|js|ts|go|rs|c|cpp|h|java|rb|php|html|css|sql)
|
||||||
|
# Clear screen and show loading message
|
||||||
|
printf "\033[H\033[J"
|
||||||
|
echo ""
|
||||||
|
echo " ${BLUE}📄 Opening: $filename${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Try less first (best for text viewing)
|
||||||
if command -v less &>/dev/null; then
|
if command -v less &>/dev/null; then
|
||||||
|
# Exit alternate screen only for less
|
||||||
|
printf "\033[?25h" # Show cursor
|
||||||
|
tput rmcup 2>/dev/null || true
|
||||||
|
|
||||||
less -F "$selected_path" 2>/dev/null && open_success=true
|
less -F "$selected_path" 2>/dev/null && open_success=true
|
||||||
|
|
||||||
|
# Return to alternate screen
|
||||||
|
tput smcup 2>/dev/null || true
|
||||||
|
printf "\033[?25l" # Hide cursor
|
||||||
|
else
|
||||||
|
# Fallback to system open if less is not available
|
||||||
|
echo " ${GRAY}Launching default application...${NC}"
|
||||||
|
if command -v open &>/dev/null; then
|
||||||
|
open "$selected_path" 2>/dev/null && open_success=true
|
||||||
|
if [[ "$open_success" == "true" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo " ${BLUE}✓${NC} File opened in external app"
|
||||||
|
sleep 0.8
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# For other files, try system open
|
# For other files, use system open (keep in alternate screen)
|
||||||
|
# Show message without flashing
|
||||||
|
printf "\033[H\033[J"
|
||||||
|
echo ""
|
||||||
|
echo " ${BLUE}📦 Opening: $filename${NC}"
|
||||||
|
echo ""
|
||||||
|
echo " ${GRAY}Launching default application...${NC}"
|
||||||
|
|
||||||
if command -v open &>/dev/null; then
|
if command -v open &>/dev/null; then
|
||||||
open "$selected_path" 2>/dev/null && open_success=true
|
open "$selected_path" 2>/dev/null && open_success=true
|
||||||
sleep 0.5 # Give time for app to launch
|
|
||||||
|
# Show brief success message
|
||||||
|
if [[ "$open_success" == "true" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo " ${BLUE}✓${NC} File opened in external app"
|
||||||
|
sleep 0.8
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# If nothing worked, show a message
|
# If nothing worked, show error message
|
||||||
if [[ "$open_success" != "true" ]]; then
|
if [[ "$open_success" != "true" ]]; then
|
||||||
|
printf "\033[H\033[J"
|
||||||
echo ""
|
echo ""
|
||||||
echo " ${YELLOW}File: $selected_path${NC}"
|
echo " ${YELLOW}⚠️ Could not open file${NC}"
|
||||||
|
echo ""
|
||||||
|
echo " ${GRAY}File: $selected_path${NC}"
|
||||||
echo " ${GRAY}Press any key to return...${NC}"
|
echo " ${GRAY}Press any key to return...${NC}"
|
||||||
read -n 1 -s 2>/dev/null
|
read -n 1 -s 2>/dev/null
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Return to alternate screen
|
|
||||||
tput smcup 2>/dev/null || true
|
|
||||||
printf "\033[?25l" # Hide cursor
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
@@ -1973,7 +2002,7 @@ interactive_drill_down() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$delete_success" == "true" ]]; then
|
if [[ "$delete_success" == "true" ]]; then
|
||||||
echo " ${GREEN}✓ Deleted successfully${NC}"
|
echo " ${BLUE}✓ Deleted successfully${NC}"
|
||||||
echo " ${GRAY}Freed: $human_size${NC}"
|
echo " ${GRAY}Freed: $human_size${NC}"
|
||||||
sleep 0.8
|
sleep 0.8
|
||||||
|
|
||||||
|
|||||||
56
bin/clean.sh
56
bin/clean.sh
@@ -63,21 +63,21 @@ start_spinner() {
|
|||||||
local message="$1"
|
local message="$1"
|
||||||
|
|
||||||
if [[ ! -t 1 ]]; then
|
if [[ ! -t 1 ]]; then
|
||||||
echo -n " ${BLUE}🔍${NC} $message"
|
echo -n " ${BLUE}◎${NC} $message"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n " ${BLUE}🔍${NC} $message"
|
echo -n " ${BLUE}◎${NC} $message"
|
||||||
(
|
(
|
||||||
local delay=0.5
|
local delay=0.5
|
||||||
while true; do
|
while true; do
|
||||||
printf "\r ${BLUE}🔍${NC} $message. "
|
printf "\r ${BLUE}◎${NC} $message. "
|
||||||
sleep $delay
|
sleep $delay
|
||||||
printf "\r ${BLUE}🔍${NC} $message.. "
|
printf "\r ${BLUE}◎${NC} $message.. "
|
||||||
sleep $delay
|
sleep $delay
|
||||||
printf "\r ${BLUE}🔍${NC} $message..."
|
printf "\r ${BLUE}◎${NC} $message..."
|
||||||
sleep $delay
|
sleep $delay
|
||||||
printf "\r ${BLUE}🔍${NC} $message "
|
printf "\r ${BLUE}◎${NC} $message "
|
||||||
sleep $delay
|
sleep $delay
|
||||||
done
|
done
|
||||||
) &
|
) &
|
||||||
@@ -96,9 +96,9 @@ stop_spinner() {
|
|||||||
kill "$SPINNER_PID" 2>/dev/null
|
kill "$SPINNER_PID" 2>/dev/null
|
||||||
wait "$SPINNER_PID" 2>/dev/null
|
wait "$SPINNER_PID" 2>/dev/null
|
||||||
SPINNER_PID=""
|
SPINNER_PID=""
|
||||||
printf "\r ${GREEN}✓${NC} %s\n" "$result_message"
|
printf "\r ${BLUE}✓${NC} %s\n" "$result_message"
|
||||||
else
|
else
|
||||||
echo " ${GREEN}✓${NC} $result_message"
|
echo " ${BLUE}✓${NC} $result_message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ start_section() {
|
|||||||
|
|
||||||
end_section() {
|
end_section() {
|
||||||
if [[ $TRACK_SECTION -eq 1 && $SECTION_ACTIVITY -eq 0 ]]; then
|
if [[ $TRACK_SECTION -eq 1 && $SECTION_ACTIVITY -eq 0 ]]; then
|
||||||
echo -e " ${BLUE}✨${NC} Nothing to tidy"
|
echo -e " ${BLUE}○${NC} Nothing to tidy"
|
||||||
fi
|
fi
|
||||||
TRACK_SECTION=0
|
TRACK_SECTION=0
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ safe_clean() {
|
|||||||
|
|
||||||
# Show progress indicator for potentially slow operations
|
# Show progress indicator for potentially slow operations
|
||||||
if [[ ${#existing_paths[@]} -gt 3 ]]; then
|
if [[ ${#existing_paths[@]} -gt 3 ]]; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Checking $description...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Checking $description...\r"
|
||||||
local temp_dir=$(mktemp -d)
|
local temp_dir=$(mktemp -d)
|
||||||
|
|
||||||
# Parallel processing (bash 3.2 compatible)
|
# Parallel processing (bash 3.2 compatible)
|
||||||
@@ -197,7 +197,7 @@ safe_clean() {
|
|||||||
rm -rf "$temp_dir"
|
rm -rf "$temp_dir"
|
||||||
else
|
else
|
||||||
# Show progress for small batches too (simpler jobs)
|
# Show progress for small batches too (simpler jobs)
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Checking $description...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Checking $description...\r"
|
||||||
|
|
||||||
for path in "${existing_paths[@]}"; do
|
for path in "${existing_paths[@]}"; do
|
||||||
local size_bytes=$(du -sk "$path" 2>/dev/null | awk '{print $1}' || echo "0")
|
local size_bytes=$(du -sk "$path" 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
@@ -235,7 +235,7 @@ safe_clean() {
|
|||||||
if [[ "$DRY_RUN" == "true" ]]; then
|
if [[ "$DRY_RUN" == "true" ]]; then
|
||||||
echo -e " ${YELLOW}→${NC} $label ${YELLOW}($size_human, dry)${NC}"
|
echo -e " ${YELLOW}→${NC} $label ${YELLOW}($size_human, dry)${NC}"
|
||||||
else
|
else
|
||||||
echo -e " ${GREEN}✓${NC} $label ${GREEN}($size_human)${NC}"
|
echo -e " ${BLUE}✓${NC} $label ${GREEN}($size_human)${NC}"
|
||||||
fi
|
fi
|
||||||
((files_cleaned+=total_count))
|
((files_cleaned+=total_count))
|
||||||
((total_size_cleaned+=total_size_bytes))
|
((total_size_cleaned+=total_size_bytes))
|
||||||
@@ -442,10 +442,10 @@ perform_cleanup() {
|
|||||||
start_section "Developer tools"
|
start_section "Developer tools"
|
||||||
# Node.js ecosystem
|
# Node.js ecosystem
|
||||||
if command -v npm >/dev/null 2>&1; then
|
if command -v npm >/dev/null 2>&1; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Cleaning npm cache...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Cleaning npm cache...\r"
|
||||||
npm cache clean --force >/dev/null 2>&1 || true
|
npm cache clean --force >/dev/null 2>&1 || true
|
||||||
[[ -t 1 ]] && echo -ne "\r\033[K"
|
[[ -t 1 ]] && echo -ne "\r\033[K"
|
||||||
echo -e " ${GREEN}✓${NC} npm cache cleaned"
|
echo -e " ${BLUE}✓${NC} npm cache cleaned"
|
||||||
note_activity
|
note_activity
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -455,10 +455,10 @@ perform_cleanup() {
|
|||||||
|
|
||||||
# Python ecosystem
|
# Python ecosystem
|
||||||
if command -v pip3 >/dev/null 2>&1; then
|
if command -v pip3 >/dev/null 2>&1; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Cleaning pip cache...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Cleaning pip cache...\r"
|
||||||
pip3 cache purge >/dev/null 2>&1 || true
|
pip3 cache purge >/dev/null 2>&1 || true
|
||||||
[[ -t 1 ]] && echo -ne "\r\033[K"
|
[[ -t 1 ]] && echo -ne "\r\033[K"
|
||||||
echo -e " ${GREEN}✓${NC} pip cache cleaned"
|
echo -e " ${BLUE}✓${NC} pip cache cleaned"
|
||||||
note_activity
|
note_activity
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -468,11 +468,11 @@ perform_cleanup() {
|
|||||||
|
|
||||||
# Go ecosystem
|
# Go ecosystem
|
||||||
if command -v go >/dev/null 2>&1; then
|
if command -v go >/dev/null 2>&1; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Cleaning Go cache...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Cleaning Go cache...\r"
|
||||||
go clean -modcache >/dev/null 2>&1 || true
|
go clean -modcache >/dev/null 2>&1 || true
|
||||||
go clean -cache >/dev/null 2>&1 || true
|
go clean -cache >/dev/null 2>&1 || true
|
||||||
[[ -t 1 ]] && echo -ne "\r\033[K"
|
[[ -t 1 ]] && echo -ne "\r\033[K"
|
||||||
echo -e " ${GREEN}✓${NC} Go cache cleaned"
|
echo -e " ${BLUE}✓${NC} Go cache cleaned"
|
||||||
note_activity
|
note_activity
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -484,20 +484,20 @@ perform_cleanup() {
|
|||||||
|
|
||||||
# Docker (only clean build cache, preserve images and volumes)
|
# Docker (only clean build cache, preserve images and volumes)
|
||||||
if command -v docker >/dev/null 2>&1; then
|
if command -v docker >/dev/null 2>&1; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Cleaning Docker build cache...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Cleaning Docker build cache...\r"
|
||||||
docker builder prune -af >/dev/null 2>&1 || true
|
docker builder prune -af >/dev/null 2>&1 || true
|
||||||
[[ -t 1 ]] && echo -ne "\r\033[K"
|
[[ -t 1 ]] && echo -ne "\r\033[K"
|
||||||
echo -e " ${GREEN}✓${NC} Docker build cache cleaned"
|
echo -e " ${BLUE}✓${NC} Docker build cache cleaned"
|
||||||
note_activity
|
note_activity
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Container tools
|
# Container tools
|
||||||
safe_clean ~/.kube/cache/* "Kubernetes cache"
|
safe_clean ~/.kube/cache/* "Kubernetes cache"
|
||||||
if command -v podman >/dev/null 2>&1; then
|
if command -v podman >/dev/null 2>&1; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Cleaning Podman build cache...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Cleaning Podman build cache...\r"
|
||||||
podman system prune -f >/dev/null 2>&1 || true
|
podman system prune -f >/dev/null 2>&1 || true
|
||||||
[[ -t 1 ]] && echo -ne "\r\033[K"
|
[[ -t 1 ]] && echo -ne "\r\033[K"
|
||||||
echo -e " ${GREEN}✓${NC} Podman build cache cleaned"
|
echo -e " ${BLUE}✓${NC} Podman build cache cleaned"
|
||||||
note_activity
|
note_activity
|
||||||
fi
|
fi
|
||||||
safe_clean ~/.local/share/containers/storage/tmp/* "Container storage temp"
|
safe_clean ~/.local/share/containers/storage/tmp/* "Container storage temp"
|
||||||
@@ -512,10 +512,10 @@ perform_cleanup() {
|
|||||||
safe_clean /opt/homebrew/var/homebrew/locks/* "Homebrew lock files (M series)"
|
safe_clean /opt/homebrew/var/homebrew/locks/* "Homebrew lock files (M series)"
|
||||||
safe_clean /usr/local/var/homebrew/locks/* "Homebrew lock files (Intel)"
|
safe_clean /usr/local/var/homebrew/locks/* "Homebrew lock files (Intel)"
|
||||||
if command -v brew >/dev/null 2>&1; then
|
if command -v brew >/dev/null 2>&1; then
|
||||||
[[ -t 1 ]] && echo -ne " ${BLUE}●${NC} Cleaning Homebrew...\r"
|
[[ -t 1 ]] && echo -ne " ${BLUE}◎${NC} Cleaning Homebrew...\r"
|
||||||
brew cleanup >/dev/null 2>&1 || true
|
brew cleanup >/dev/null 2>&1 || true
|
||||||
[[ -t 1 ]] && echo -ne "\r\033[K"
|
[[ -t 1 ]] && echo -ne "\r\033[K"
|
||||||
echo -e " ${GREEN}✓${NC} Homebrew cache cleaned"
|
echo -e " ${BLUE}✓${NC} Homebrew cache cleaned"
|
||||||
note_activity
|
note_activity
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -774,7 +774,7 @@ perform_cleanup() {
|
|||||||
start_section "Orphaned app caches"
|
start_section "Orphaned app caches"
|
||||||
|
|
||||||
# Build a list of installed application bundle identifiers
|
# Build a list of installed application bundle identifiers
|
||||||
echo -n " ${BLUE}🔍${NC} Scanning installed applications..."
|
echo -n " ${BLUE}◎${NC} Scanning installed applications..."
|
||||||
local installed_bundles=$(mktemp)
|
local installed_bundles=$(mktemp)
|
||||||
|
|
||||||
# Scan both system and user application directories
|
# Scan both system and user application directories
|
||||||
@@ -785,12 +785,12 @@ perform_cleanup() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
local app_count=$(wc -l < "$installed_bundles" | tr -d ' ')
|
local app_count=$(wc -l < "$installed_bundles" | tr -d ' ')
|
||||||
echo " ${GREEN}✓${NC} Found $app_count apps"
|
echo " ${BLUE}✓${NC} Found $app_count apps"
|
||||||
|
|
||||||
local cache_count=0
|
local cache_count=0
|
||||||
|
|
||||||
# Check for orphaned caches (safe to remove - caches are regenerable)
|
# Check for orphaned caches (safe to remove - caches are regenerable)
|
||||||
echo -n " ${BLUE}🔍${NC} Scanning orphaned cache directories..."
|
echo -n " ${BLUE}◎${NC} Scanning orphaned cache directories..."
|
||||||
if ls ~/Library/Caches/com.* >/dev/null 2>&1; then
|
if ls ~/Library/Caches/com.* >/dev/null 2>&1; then
|
||||||
for cache_dir in ~/Library/Caches/com.*; do
|
for cache_dir in ~/Library/Caches/com.*; do
|
||||||
[[ -d "$cache_dir" ]] || continue
|
[[ -d "$cache_dir" ]] || continue
|
||||||
@@ -805,7 +805,7 @@ perform_cleanup() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
echo " ${GREEN}✓${NC} Complete ($cache_count removed)"
|
echo " ${BLUE}✓${NC} Complete ($cache_count removed)"
|
||||||
|
|
||||||
# Clean up temp file
|
# Clean up temp file
|
||||||
rm -f "$installed_bundles"
|
rm -f "$installed_bundles"
|
||||||
|
|||||||
@@ -144,11 +144,11 @@ scan_applications() {
|
|||||||
|
|
||||||
# Smart display name selection - prefer descriptive names over generic ones
|
# Smart display name selection - prefer descriptive names over generic ones
|
||||||
local candidates=()
|
local candidates=()
|
||||||
|
|
||||||
# Get all potential names
|
# Get all potential names
|
||||||
local bundle_display_name=$(plutil -extract CFBundleDisplayName raw "$app_path/Contents/Info.plist" 2>/dev/null)
|
local bundle_display_name=$(plutil -extract CFBundleDisplayName raw "$app_path/Contents/Info.plist" 2>/dev/null)
|
||||||
local bundle_name=$(plutil -extract CFBundleName raw "$app_path/Contents/Info.plist" 2>/dev/null)
|
local bundle_name=$(plutil -extract CFBundleName raw "$app_path/Contents/Info.plist" 2>/dev/null)
|
||||||
|
|
||||||
# Check if executable name is generic/technical (should be avoided)
|
# Check if executable name is generic/technical (should be avoided)
|
||||||
local is_generic_executable=false
|
local is_generic_executable=false
|
||||||
if [[ -n "$bundle_executable" ]]; then
|
if [[ -n "$bundle_executable" ]]; then
|
||||||
@@ -158,35 +158,35 @@ scan_applications() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Priority order for name selection:
|
# Priority order for name selection:
|
||||||
# 1. App folder name (if ASCII and descriptive) - often the most complete name
|
# 1. App folder name (if ASCII and descriptive) - often the most complete name
|
||||||
if [[ "$app_name" =~ ^[A-Za-z0-9\ ._-]+$ && ${#app_name} -gt 3 ]]; then
|
if [[ "$app_name" =~ ^[A-Za-z0-9\ ._-]+$ && ${#app_name} -gt 3 ]]; then
|
||||||
candidates+=("$app_name")
|
candidates+=("$app_name")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 2. CFBundleDisplayName (if meaningful and ASCII)
|
# 2. CFBundleDisplayName (if meaningful and ASCII)
|
||||||
if [[ -n "$bundle_display_name" && "$bundle_display_name" =~ ^[A-Za-z0-9\ ._-]+$ ]]; then
|
if [[ -n "$bundle_display_name" && "$bundle_display_name" =~ ^[A-Za-z0-9\ ._-]+$ ]]; then
|
||||||
candidates+=("$bundle_display_name")
|
candidates+=("$bundle_display_name")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 3. CFBundleName (if meaningful and ASCII)
|
# 3. CFBundleName (if meaningful and ASCII)
|
||||||
if [[ -n "$bundle_name" && "$bundle_name" =~ ^[A-Za-z0-9\ ._-]+$ && "$bundle_name" != "$bundle_display_name" ]]; then
|
if [[ -n "$bundle_name" && "$bundle_name" =~ ^[A-Za-z0-9\ ._-]+$ && "$bundle_name" != "$bundle_display_name" ]]; then
|
||||||
candidates+=("$bundle_name")
|
candidates+=("$bundle_name")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. CFBundleExecutable (only if not generic and ASCII)
|
# 4. CFBundleExecutable (only if not generic and ASCII)
|
||||||
if [[ -n "$bundle_executable" && "$bundle_executable" =~ ^[A-Za-z0-9._-]+$ && "$is_generic_executable" == false ]]; then
|
if [[ -n "$bundle_executable" && "$bundle_executable" =~ ^[A-Za-z0-9._-]+$ && "$is_generic_executable" == false ]]; then
|
||||||
candidates+=("$bundle_executable")
|
candidates+=("$bundle_executable")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 5. Fallback to non-ASCII names if no ASCII found
|
# 5. Fallback to non-ASCII names if no ASCII found
|
||||||
if [[ ${#candidates[@]} -eq 0 ]]; then
|
if [[ ${#candidates[@]} -eq 0 ]]; then
|
||||||
[[ -n "$bundle_display_name" ]] && candidates+=("$bundle_display_name")
|
[[ -n "$bundle_display_name" ]] && candidates+=("$bundle_display_name")
|
||||||
[[ -n "$bundle_name" && "$bundle_name" != "$bundle_display_name" ]] && candidates+=("$bundle_name")
|
[[ -n "$bundle_name" && "$bundle_name" != "$bundle_display_name" ]] && candidates+=("$bundle_name")
|
||||||
candidates+=("$app_name")
|
candidates+=("$app_name")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Select the first (best) candidate
|
# Select the first (best) candidate
|
||||||
display_name="${candidates[0]:-$app_name}"
|
display_name="${candidates[0]:-$app_name}"
|
||||||
|
|
||||||
@@ -404,11 +404,11 @@ uninstall_applications() {
|
|||||||
|
|
||||||
# Show what will be removed
|
# Show what will be removed
|
||||||
echo -e " ${YELLOW}Files to be removed:${NC}"
|
echo -e " ${YELLOW}Files to be removed:${NC}"
|
||||||
echo -e " ${GREEN}✓${NC} Application: $(echo "$app_path" | sed "s|$HOME|~|")"
|
echo -e " ${BLUE}✓${NC} Application: $(echo "$app_path" | sed "s|$HOME|~|")"
|
||||||
|
|
||||||
# Show user-level files
|
# Show user-level files
|
||||||
while IFS= read -r file; do
|
while IFS= read -r file; do
|
||||||
[[ -n "$file" && -e "$file" ]] && echo -e " ${GREEN}✓${NC} $(echo "$file" | sed "s|$HOME|~|")"
|
[[ -n "$file" && -e "$file" ]] && echo -e " ${BLUE}✓${NC} $(echo "$file" | sed "s|$HOME|~|")"
|
||||||
done <<< "$related_files"
|
done <<< "$related_files"
|
||||||
|
|
||||||
# Show system-level files
|
# Show system-level files
|
||||||
@@ -435,7 +435,7 @@ uninstall_applications() {
|
|||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
# Remove the application
|
# Remove the application
|
||||||
if rm -rf "$app_path" 2>/dev/null; then
|
if rm -rf "$app_path" 2>/dev/null; then
|
||||||
echo -e " ${GREEN}✓${NC} Removed application"
|
echo -e " ${BLUE}✓${NC} Removed application"
|
||||||
else
|
else
|
||||||
log_error "Failed to remove $app_path"
|
log_error "Failed to remove $app_path"
|
||||||
continue
|
continue
|
||||||
@@ -445,7 +445,7 @@ uninstall_applications() {
|
|||||||
while IFS= read -r file; do
|
while IFS= read -r file; do
|
||||||
if [[ -n "$file" && -e "$file" ]]; then
|
if [[ -n "$file" && -e "$file" ]]; then
|
||||||
if rm -rf "$file" 2>/dev/null; then
|
if rm -rf "$file" 2>/dev/null; then
|
||||||
echo -e " ${GREEN}✓${NC} Removed $(echo "$file" | sed "s|$HOME|~|" | xargs basename)"
|
echo -e " ${BLUE}✓${NC} Removed $(echo "$file" | sed "s|$HOME|~|" | xargs basename)"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done <<< "$related_files"
|
done <<< "$related_files"
|
||||||
@@ -456,7 +456,7 @@ uninstall_applications() {
|
|||||||
while IFS= read -r file; do
|
while IFS= read -r file; do
|
||||||
if [[ -n "$file" && -e "$file" ]]; then
|
if [[ -n "$file" && -e "$file" ]]; then
|
||||||
if sudo rm -rf "$file" 2>/dev/null; then
|
if sudo rm -rf "$file" 2>/dev/null; then
|
||||||
echo -e " ${GREEN}✓${NC} Removed [System] $(basename "$file")"
|
echo -e " ${BLUE}✓${NC} Removed [System] $(basename "$file")"
|
||||||
else
|
else
|
||||||
log_warning "Failed to remove system file: $file"
|
log_warning "Failed to remove system file: $file"
|
||||||
fi
|
fi
|
||||||
@@ -508,7 +508,7 @@ trap cleanup EXIT INT TERM
|
|||||||
main() {
|
main() {
|
||||||
# Hide cursor during operation
|
# Hide cursor during operation
|
||||||
hide_cursor
|
hide_cursor
|
||||||
|
|
||||||
# Scan applications
|
# Scan applications
|
||||||
local apps_file=$(scan_applications)
|
local apps_file=$(scan_applications)
|
||||||
|
|
||||||
|
|||||||
14
install.sh
14
install.sh
@@ -85,7 +85,7 @@ resolve_source_dir() {
|
|||||||
# Expand tmp now so trap doesn't depend on local scope
|
# Expand tmp now so trap doesn't depend on local scope
|
||||||
trap "rm -rf '$tmp'" EXIT
|
trap "rm -rf '$tmp'" EXIT
|
||||||
|
|
||||||
echo "Fetching Mole source..."
|
echo -e "${BLUE}◎${NC} Fetching Mole source..."
|
||||||
if command -v curl >/dev/null 2>&1; then
|
if command -v curl >/dev/null 2>&1; then
|
||||||
# Download main branch tarball
|
# Download main branch tarball
|
||||||
if curl -fsSL -o "$tmp/mole.tar.gz" "https://github.com/tw93/mole/archive/refs/heads/main.tar.gz"; then
|
if curl -fsSL -o "$tmp/mole.tar.gz" "https://github.com/tw93/mole/archive/refs/heads/main.tar.gz"; then
|
||||||
@@ -448,17 +448,17 @@ perform_update() {
|
|||||||
update_via_homebrew "$VERSION"
|
update_via_homebrew "$VERSION"
|
||||||
else
|
else
|
||||||
# Fallback: inline implementation
|
# Fallback: inline implementation
|
||||||
echo -e "${BLUE}→${NC} Updating Homebrew..."
|
echo -e "${BLUE}◎${NC} Updating Homebrew..."
|
||||||
brew update 2>&1 | grep -Ev "^(==>|Already up-to-date)" || true
|
brew update 2>&1 | grep -Ev "^(==>|Already up-to-date)" || true
|
||||||
|
|
||||||
echo -e "${BLUE}→${NC} Upgrading Mole..."
|
echo -e "${BLUE}◎${NC} Upgrading Mole..."
|
||||||
local upgrade_output
|
local upgrade_output
|
||||||
upgrade_output=$(brew upgrade mole 2>&1) || true
|
upgrade_output=$(brew upgrade mole 2>&1) || true
|
||||||
|
|
||||||
if echo "$upgrade_output" | grep -q "already installed"; then
|
if echo "$upgrade_output" | grep -q "already installed"; then
|
||||||
local current_version
|
local current_version
|
||||||
current_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
current_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
||||||
echo -e "${GREEN}✓${NC} Already on latest version (${current_version:-$VERSION})"
|
echo -e "${BLUE}✓${NC} Already on latest version (${current_version:-$VERSION})"
|
||||||
elif echo "$upgrade_output" | grep -q "Error:"; then
|
elif echo "$upgrade_output" | grep -q "Error:"; then
|
||||||
log_error "Homebrew upgrade failed"
|
log_error "Homebrew upgrade failed"
|
||||||
echo "$upgrade_output" | grep "Error:" >&2
|
echo "$upgrade_output" | grep "Error:" >&2
|
||||||
@@ -467,7 +467,7 @@ perform_update() {
|
|||||||
echo "$upgrade_output" | grep -Ev "^(==>|Updating Homebrew|Warning:)" || true
|
echo "$upgrade_output" | grep -Ev "^(==>|Updating Homebrew|Warning:)" || true
|
||||||
local new_version
|
local new_version
|
||||||
new_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
new_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
||||||
echo -e "${GREEN}✓${NC} Updated to latest version (${new_version:-$VERSION})"
|
echo -e "${BLUE}✓${NC} Updated to latest version (${new_version:-$VERSION})"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f "$HOME/.cache/mole/version_check" "$HOME/.cache/mole/update_message"
|
rm -f "$HOME/.cache/mole/version_check" "$HOME/.cache/mole/update_message"
|
||||||
@@ -494,7 +494,7 @@ perform_update() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$installed_version" == "$target_version" ]]; then
|
if [[ "$installed_version" == "$target_version" ]]; then
|
||||||
echo -e "${GREEN}✓${NC} Already on latest version ($installed_version)"
|
echo -e "${BLUE}✓${NC} Already on latest version ($installed_version)"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -514,7 +514,7 @@ perform_update() {
|
|||||||
updated_version="$target_version"
|
updated_version="$target_version"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "${GREEN}✓${NC} Updated to latest version ($updated_version)"
|
echo -e "${BLUE}✓${NC} Updated to latest version ($updated_version)"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Run requested action
|
# Run requested action
|
||||||
|
|||||||
@@ -185,14 +185,14 @@ batch_uninstall_applications() {
|
|||||||
if [[ "$needs_sudo" == "true" ]]; then
|
if [[ "$needs_sudo" == "true" ]]; then
|
||||||
if sudo rm -rf "$app_path" 2>/dev/null; then
|
if sudo rm -rf "$app_path" 2>/dev/null; then
|
||||||
removal_success=true
|
removal_success=true
|
||||||
echo -e " ${GREEN}✓${NC} Removed application"
|
echo -e " ${BLUE}✓${NC} Removed application"
|
||||||
else
|
else
|
||||||
error_msg="Failed to remove with sudo (check permissions or SIP protection)"
|
error_msg="Failed to remove with sudo (check permissions or SIP protection)"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if rm -rf "$app_path" 2>/dev/null; then
|
if rm -rf "$app_path" 2>/dev/null; then
|
||||||
removal_success=true
|
removal_success=true
|
||||||
echo -e " ${GREEN}✓${NC} Removed application"
|
echo -e " ${BLUE}✓${NC} Removed application"
|
||||||
else
|
else
|
||||||
error_msg="Failed to remove (check if app is running or protected)"
|
error_msg="Failed to remove (check if app is running or protected)"
|
||||||
fi
|
fi
|
||||||
@@ -211,7 +211,7 @@ batch_uninstall_applications() {
|
|||||||
done <<< "$related_files"
|
done <<< "$related_files"
|
||||||
|
|
||||||
if [[ $files_removed -gt 0 ]]; then
|
if [[ $files_removed -gt 0 ]]; then
|
||||||
echo -e " ${GREEN}✓${NC} Cleaned $files_removed related files"
|
echo -e " ${BLUE}✓${NC} Cleaned $files_removed related files"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
((total_size_freed += total_kb))
|
((total_size_freed += total_kb))
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ log_info() {
|
|||||||
|
|
||||||
log_success() {
|
log_success() {
|
||||||
rotate_log
|
rotate_log
|
||||||
echo -e " ${GREEN}✓${NC} $1"
|
echo -e " ${BLUE}✓${NC} $1"
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $1" >> "$LOG_FILE" 2>/dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $1" >> "$LOG_FILE" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ log_warning() {
|
|||||||
|
|
||||||
log_error() {
|
log_error() {
|
||||||
rotate_log
|
rotate_log
|
||||||
echo -e "${RED}❌ $1${NC}" >&2
|
echo -e "${RED}$1${NC}" >&2
|
||||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE" 2>/dev/null || true
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,11 +264,11 @@ request_sudo() {
|
|||||||
update_via_homebrew() {
|
update_via_homebrew() {
|
||||||
local version="${1:-unknown}"
|
local version="${1:-unknown}"
|
||||||
|
|
||||||
echo -e "${BLUE}→${NC} Updating Homebrew..."
|
echo -e "${BLUE}◎${NC} Updating Homebrew..."
|
||||||
# Filter out common noise but show important info
|
# Filter out common noise but show important info
|
||||||
brew update 2>&1 | grep -Ev "^(==>|Already up-to-date)" || true
|
brew update 2>&1 | grep -Ev "^(==>|Already up-to-date)" || true
|
||||||
|
|
||||||
echo -e "${BLUE}→${NC} Upgrading Mole..."
|
echo -e "${BLUE}◎${NC} Upgrading Mole..."
|
||||||
local upgrade_output
|
local upgrade_output
|
||||||
upgrade_output=$(brew upgrade mole 2>&1) || true
|
upgrade_output=$(brew upgrade mole 2>&1) || true
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ update_via_homebrew() {
|
|||||||
# Get current version
|
# Get current version
|
||||||
local current_version
|
local current_version
|
||||||
current_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
current_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
||||||
echo -e "${GREEN}✓${NC} Already on latest version (${current_version:-$version})"
|
echo -e "${BLUE}✓${NC} Already on latest version (${current_version:-$version})"
|
||||||
elif echo "$upgrade_output" | grep -q "Error:"; then
|
elif echo "$upgrade_output" | grep -q "Error:"; then
|
||||||
log_error "Homebrew upgrade failed"
|
log_error "Homebrew upgrade failed"
|
||||||
echo "$upgrade_output" | grep "Error:" >&2
|
echo "$upgrade_output" | grep "Error:" >&2
|
||||||
@@ -287,7 +287,7 @@ update_via_homebrew() {
|
|||||||
# Get new version
|
# Get new version
|
||||||
local new_version
|
local new_version
|
||||||
new_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
new_version=$(brew list --versions mole 2>/dev/null | awk '{print $2}')
|
||||||
echo -e "${GREEN}✓${NC} Updated to latest version (${new_version:-$version})"
|
echo -e "${BLUE}✓${NC} Updated to latest version (${new_version:-$version})"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clear version check cache
|
# Clear version check cache
|
||||||
@@ -368,7 +368,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.tunabellysoftware.*" # Disk Utility apps
|
"com.tunabellysoftware.*" # Disk Utility apps
|
||||||
"com.grandperspectiv.*" # GrandPerspective
|
"com.grandperspectiv.*" # GrandPerspective
|
||||||
"com.binaryfruit.*" # FusionCast
|
"com.binaryfruit.*" # FusionCast
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Password Managers & Security
|
# Password Managers & Security
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -381,7 +381,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"org.keepassx.*" # KeePassX
|
"org.keepassx.*" # KeePassX
|
||||||
"com.authy.*" # Authy
|
"com.authy.*" # Authy
|
||||||
"com.yubico.*" # YubiKey Manager
|
"com.yubico.*" # YubiKey Manager
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Development Tools - IDEs & Editors
|
# Development Tools - IDEs & Editors
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -398,7 +398,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.panic.Nova" # Nova
|
"com.panic.Nova" # Nova
|
||||||
"abnerworks.Typora" # Typora (Markdown editor)
|
"abnerworks.Typora" # Typora (Markdown editor)
|
||||||
"com.uranusjr.macdown" # MacDown
|
"com.uranusjr.macdown" # MacDown
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Development Tools - Database Clients
|
# Development Tools - Database Clients
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -413,7 +413,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.eggerapps.Sequel-Pro" # Sequel Pro legacy
|
"com.eggerapps.Sequel-Pro" # Sequel Pro legacy
|
||||||
"com.valentina-db.Valentina-Studio" # Valentina Studio
|
"com.valentina-db.Valentina-Studio" # Valentina Studio
|
||||||
"com.dbvis.DbVisualizer" # DbVisualizer
|
"com.dbvis.DbVisualizer" # DbVisualizer
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Development Tools - API & Network
|
# Development Tools - API & Network
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -426,7 +426,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.charlesproxy.charles" # Charles
|
"com.charlesproxy.charles" # Charles
|
||||||
"com.telerik.Fiddler" # Fiddler
|
"com.telerik.Fiddler" # Fiddler
|
||||||
"com.usebruno.app" # Bruno (API client)
|
"com.usebruno.app" # Bruno (API client)
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Development Tools - Git & Version Control
|
# Development Tools - Git & Version Control
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -438,7 +438,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.github.Gitify" # Gitify
|
"com.github.Gitify" # Gitify
|
||||||
"com.fork.Fork" # Fork
|
"com.fork.Fork" # Fork
|
||||||
"com.axosoft.gitkraken" # GitKraken
|
"com.axosoft.gitkraken" # GitKraken
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Development Tools - Terminal & Shell
|
# Development Tools - Terminal & Shell
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -451,7 +451,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.fig.Fig" # Fig (terminal assistant)
|
"com.fig.Fig" # Fig (terminal assistant)
|
||||||
"dev.warp.Warp-Stable" # Warp
|
"dev.warp.Warp-Stable" # Warp
|
||||||
"com.termius-dmg" # Termius (SSH client)
|
"com.termius-dmg" # Termius (SSH client)
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Development Tools - Docker & Virtualization
|
# Development Tools - Docker & Virtualization
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -462,7 +462,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"org.virtualbox.app.VirtualBox" # VirtualBox
|
"org.virtualbox.app.VirtualBox" # VirtualBox
|
||||||
"com.vagrant.*" # Vagrant
|
"com.vagrant.*" # Vagrant
|
||||||
"com.orbstack.OrbStack" # OrbStack
|
"com.orbstack.OrbStack" # OrbStack
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# System Monitoring & Performance
|
# System Monitoring & Performance
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -473,7 +473,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.mediaatelier.MenuMeters" # MenuMeters
|
"com.mediaatelier.MenuMeters" # MenuMeters
|
||||||
"com.activity-indicator.app" # Activity Indicator
|
"com.activity-indicator.app" # Activity Indicator
|
||||||
"net.cindori.sensei" # Sensei
|
"net.cindori.sensei" # Sensei
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Window Management & Productivity
|
# Window Management & Productivity
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -493,7 +493,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.surteesstudios.Bartender" # Bartender
|
"com.surteesstudios.Bartender" # Bartender
|
||||||
"com.gaosun.eul" # eul (system monitor)
|
"com.gaosun.eul" # eul (system monitor)
|
||||||
"com.pointum.hazeover" # HazeOver
|
"com.pointum.hazeover" # HazeOver
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Launcher & Automation
|
# Launcher & Automation
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -506,7 +506,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.pilotmoon.scroll-reverser" # Scroll Reverser
|
"com.pilotmoon.scroll-reverser" # Scroll Reverser
|
||||||
"org.pqrs.Karabiner-Elements" # Karabiner-Elements
|
"org.pqrs.Karabiner-Elements" # Karabiner-Elements
|
||||||
"com.apple.Automator" # Automator (system, but keep user workflows)
|
"com.apple.Automator" # Automator (system, but keep user workflows)
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Note-Taking & Documentation
|
# Note-Taking & Documentation
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -527,7 +527,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.roamresearch.*" # Roam Research
|
"com.roamresearch.*" # Roam Research
|
||||||
"com.reflect.ReflectApp" # Reflect
|
"com.reflect.ReflectApp" # Reflect
|
||||||
"com.inkdrop.*" # Inkdrop
|
"com.inkdrop.*" # Inkdrop
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Design & Creative Tools
|
# Design & Creative Tools
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -547,7 +547,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.maxon.cinema4d" # Cinema 4D
|
"com.maxon.cinema4d" # Cinema 4D
|
||||||
"com.autodesk.*" # Autodesk products
|
"com.autodesk.*" # Autodesk products
|
||||||
"com.sketchup.*" # SketchUp
|
"com.sketchup.*" # SketchUp
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Communication & Collaboration
|
# Communication & Collaboration
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -571,7 +571,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.airmail.*" # Airmail
|
"com.airmail.*" # Airmail
|
||||||
"com.postbox-inc.postbox" # Postbox
|
"com.postbox-inc.postbox" # Postbox
|
||||||
"com.tinyspeck.slackmacgap" # Slack legacy
|
"com.tinyspeck.slackmacgap" # Slack legacy
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Task Management & Productivity
|
# Task Management & Productivity
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -588,7 +588,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.airtable.airtable" # Airtable
|
"com.airtable.airtable" # Airtable
|
||||||
"com.notion.id" # Notion (also note-taking)
|
"com.notion.id" # Notion (also note-taking)
|
||||||
"com.linear.linear" # Linear
|
"com.linear.linear" # Linear
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# File Transfer & Sync
|
# File Transfer & Sync
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -599,7 +599,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"io.filezilla.FileZilla" # FileZilla
|
"io.filezilla.FileZilla" # FileZilla
|
||||||
"com.apple.Xcode.CloudDocuments" # Xcode Cloud Documents
|
"com.apple.Xcode.CloudDocuments" # Xcode Cloud Documents
|
||||||
"com.synology.*" # Synology apps
|
"com.synology.*" # Synology apps
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Screenshot & Recording
|
# Screenshot & Recording
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -615,7 +615,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.getkap.*" # Kap legacy
|
"com.getkap.*" # Kap legacy
|
||||||
"com.linebreak.CloudApp" # CloudApp
|
"com.linebreak.CloudApp" # CloudApp
|
||||||
"com.droplr.droplr-mac" # Droplr
|
"com.droplr.droplr-mac" # Droplr
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Media & Entertainment
|
# Media & Entertainment
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -632,7 +632,7 @@ readonly DATA_PROTECTED_BUNDLES=(
|
|||||||
"com.noodlesoft.Hazel" # Hazel (automation)
|
"com.noodlesoft.Hazel" # Hazel (automation)
|
||||||
"tv.plex.player.desktop" # Plex
|
"tv.plex.player.desktop" # Plex
|
||||||
"com.netease.163music" # NetEase Music
|
"com.netease.163music" # NetEase Music
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# License Management & App Stores
|
# License Management & App Stores
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ collect_files_to_be_cleaned() {
|
|||||||
local clean_sh="$SCRIPT_DIR/../bin/clean.sh"
|
local clean_sh="$SCRIPT_DIR/../bin/clean.sh"
|
||||||
local -a items=()
|
local -a items=()
|
||||||
|
|
||||||
echo -e "${BLUE}🔍${NC} Scanning cache files..."
|
echo -e "${BLUE}◎${NC} Scanning cache files..."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Run clean.sh in dry-run mode
|
# Run clean.sh in dry-run mode
|
||||||
@@ -298,7 +298,7 @@ manage_whitelist() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${#all_items[@]} -eq 0 ]]; then
|
if [[ ${#all_items[@]} -eq 0 ]]; then
|
||||||
echo -e "${GREEN}✨${NC} No cache files found - system is clean!"
|
echo -e "${BLUE}✓${NC} No cache files found - system is clean!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Press any key to exit..."
|
echo "Press any key to exit..."
|
||||||
read -n 1 -s
|
read -n 1 -s
|
||||||
@@ -308,7 +308,7 @@ manage_whitelist() {
|
|||||||
# Update global array with all items
|
# Update global array with all items
|
||||||
AVAILABLE_CACHE_ITEMS=("${all_items[@]}")
|
AVAILABLE_CACHE_ITEMS=("${all_items[@]}")
|
||||||
|
|
||||||
echo -e "${GREEN}✓${NC} Found ${#AVAILABLE_CACHE_ITEMS[@]} items"
|
echo -e "${BLUE}✓${NC} Found ${#AVAILABLE_CACHE_ITEMS[@]} items"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
local -a menu_options=()
|
local -a menu_options=()
|
||||||
@@ -432,7 +432,7 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}✓${NC} Protected $total_count items${summary}"
|
echo -e "${BLUE}✓${NC} Protected $total_count items${summary}"
|
||||||
echo -e "${GRAY}Config: ${WHITELIST_CONFIG}${NC}"
|
echo -e "${GRAY}Config: ${WHITELIST_CONFIG}${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
mole
22
mole
@@ -22,7 +22,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
source "$SCRIPT_DIR/lib/common.sh"
|
source "$SCRIPT_DIR/lib/common.sh"
|
||||||
|
|
||||||
# Version info
|
# Version info
|
||||||
VERSION="1.6.0"
|
VERSION="1.6.1"
|
||||||
MOLE_TAGLINE="can dig deep to clean your Mac."
|
MOLE_TAGLINE="can dig deep to clean your Mac."
|
||||||
|
|
||||||
# Check for updates (non-blocking, cached)
|
# Check for updates (non-blocking, cached)
|
||||||
@@ -148,7 +148,7 @@ update_mole() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Download and run installer with progress
|
# Download and run installer with progress
|
||||||
echo -e "${BLUE}→${NC} Downloading latest version..."
|
echo -e "${BLUE}◎${NC} Downloading latest version..."
|
||||||
|
|
||||||
local installer_url="https://raw.githubusercontent.com/tw93/mole/main/install.sh"
|
local installer_url="https://raw.githubusercontent.com/tw93/mole/main/install.sh"
|
||||||
local tmp_installer
|
local tmp_installer
|
||||||
@@ -181,7 +181,7 @@ update_mole() {
|
|||||||
local install_dir
|
local install_dir
|
||||||
install_dir="$(cd "$(dirname "$mole_path")" && pwd)"
|
install_dir="$(cd "$(dirname "$mole_path")" && pwd)"
|
||||||
|
|
||||||
echo -e "${BLUE}→${NC} Installing update..."
|
echo -e "${BLUE}◎${NC} Installing update..."
|
||||||
|
|
||||||
# Run installer with visible output (but capture for error handling)
|
# Run installer with visible output (but capture for error handling)
|
||||||
local install_output
|
local install_output
|
||||||
@@ -189,14 +189,14 @@ update_mole() {
|
|||||||
echo "$install_output" | grep -Ev "^$" || true
|
echo "$install_output" | grep -Ev "^$" || true
|
||||||
local new_version
|
local new_version
|
||||||
new_version=$("$mole_path" --version 2>/dev/null | awk 'NF {print $NF}' || echo "")
|
new_version=$("$mole_path" --version 2>/dev/null | awk 'NF {print $NF}' || echo "")
|
||||||
echo -e "${GREEN}✓${NC} Updated to latest version (${new_version:-unknown})"
|
echo -e "${BLUE}✓${NC} Updated to latest version (${new_version:-unknown})"
|
||||||
else
|
else
|
||||||
# Retry without --update flag
|
# Retry without --update flag
|
||||||
if install_output=$("$tmp_installer" --prefix "$install_dir" --config "$HOME/.config/mole" 2>&1); then
|
if install_output=$("$tmp_installer" --prefix "$install_dir" --config "$HOME/.config/mole" 2>&1); then
|
||||||
echo "$install_output" | grep -Ev "^$" || true
|
echo "$install_output" | grep -Ev "^$" || true
|
||||||
local new_version
|
local new_version
|
||||||
new_version=$("$mole_path" --version 2>/dev/null | awk 'NF {print $NF}' || echo "")
|
new_version=$("$mole_path" --version 2>/dev/null | awk 'NF {print $NF}' || echo "")
|
||||||
echo -e "${GREEN}✓${NC} Updated to latest version (${new_version:-unknown})"
|
echo -e "${BLUE}✓${NC} Updated to latest version (${new_version:-unknown})"
|
||||||
else
|
else
|
||||||
rm -f "$tmp_installer"
|
rm -f "$tmp_installer"
|
||||||
log_error "Update failed"
|
log_error "Update failed"
|
||||||
@@ -259,28 +259,28 @@ remove_mole() {
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if [[ "$is_homebrew" == "true" ]]; then
|
if [[ "$is_homebrew" == "true" ]]; then
|
||||||
echo -e " ${GREEN}✓${NC} Mole (via Homebrew)"
|
echo -e " ${BLUE}✓${NC} Mole (via Homebrew)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${#manual_installs[@]} -gt 0 ]]; then
|
if [[ ${#manual_installs[@]} -gt 0 ]]; then
|
||||||
for install in "${manual_installs[@]}"; do
|
for install in "${manual_installs[@]}"; do
|
||||||
echo -e " ${GREEN}✓${NC} $install"
|
echo -e " ${BLUE}✓${NC} $install"
|
||||||
local install_dir="$(dirname "$install")"
|
local install_dir="$(dirname "$install")"
|
||||||
local install_root="$(dirname "$install_dir")"
|
local install_root="$(dirname "$install_dir")"
|
||||||
if [[ -d "$install_root/lib" ]]; then
|
if [[ -d "$install_root/lib" ]]; then
|
||||||
echo -e " ${GREEN}✓${NC} $install_root/lib/"
|
echo -e " ${BLUE}✓${NC} $install_root/lib/"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${#alias_installs[@]} -gt 0 ]]; then
|
if [[ ${#alias_installs[@]} -gt 0 ]]; then
|
||||||
for alias in "${alias_installs[@]}"; do
|
for alias in "${alias_installs[@]}"; do
|
||||||
echo -e " ${GREEN}✓${NC} $alias"
|
echo -e " ${BLUE}✓${NC} $alias"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e " ${GREEN}✓${NC} ~/.config/mole/ (configuration)"
|
echo -e " ${BLUE}✓${NC} ~/.config/mole/ (configuration)"
|
||||||
echo -e " ${GREEN}✓${NC} ~/.cache/mole/ (cache)"
|
echo -e " ${BLUE}✓${NC} ~/.cache/mole/ (cache)"
|
||||||
|
|
||||||
if [[ "$is_homebrew" == "false" && ${#manual_installs[@]} -eq 0 && ${#alias_installs[@]} -eq 0 ]]; then
|
if [[ "$is_homebrew" == "false" && ${#manual_installs[@]} -eq 0 && ${#alias_installs[@]} -eq 0 ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Reference in New Issue
Block a user