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

feat(purge): smart project discovery and optimization

This commit is contained in:
Tw93
2025-12-29 19:38:14 +08:00
parent bb83362195
commit 6328bf158d
3 changed files with 143 additions and 6 deletions

View File

@@ -44,9 +44,121 @@ readonly PURGE_CONFIG_FILE="$HOME/.config/mole/purge_paths"
# Global array to hold actual search paths
PURGE_SEARCH_PATHS=()
# Load purge paths from config or defaults
# Project indicator files (if a directory contains these, it's likely a project)
readonly PROJECT_INDICATORS=(
"package.json"
"Cargo.toml"
"go.mod"
"pyproject.toml"
"requirements.txt"
"pom.xml"
"build.gradle"
"Gemfile"
"composer.json"
"pubspec.yaml"
"Makefile"
".git"
)
# Check if a directory contains projects (directly or in subdirectories)
is_project_container() {
local dir="$1"
local max_depth="${2:-2}"
# Skip hidden directories and system directories
local basename
basename=$(basename "$dir")
[[ "$basename" == .* ]] && return 1
[[ "$basename" == "Library" ]] && return 1
[[ "$basename" == "Applications" ]] && return 1
[[ "$basename" == "Movies" ]] && return 1
[[ "$basename" == "Music" ]] && return 1
[[ "$basename" == "Pictures" ]] && return 1
[[ "$basename" == "Public" ]] && return 1
# Build find expression with all indicators (single find call for efficiency)
local -a find_args=("$dir" "-maxdepth" "$max_depth" "(")
local first=true
for indicator in "${PROJECT_INDICATORS[@]}"; do
if [[ "$first" == "true" ]]; then
first=false
else
find_args+=("-o")
fi
find_args+=("-name" "$indicator")
done
find_args+=(")" "-print" "-quit")
# Single find call to check all indicators at once
if find "${find_args[@]}" 2>/dev/null | grep -q .; then
return 0
fi
return 1
}
# Discover project directories in $HOME
discover_project_dirs() {
local -a discovered=()
# First check default paths that exist
for path in "${DEFAULT_PURGE_SEARCH_PATHS[@]}"; do
if [[ -d "$path" ]]; then
discovered+=("$path")
fi
done
# Then scan $HOME for other project containers (depth 1)
local dir
for dir in "$HOME"/*/; do
[[ ! -d "$dir" ]] && continue
dir="${dir%/}" # Remove trailing slash
# Skip if already in defaults
local already_found=false
for existing in "${DEFAULT_PURGE_SEARCH_PATHS[@]}"; do
if [[ "$dir" == "$existing" ]]; then
already_found=true
break
fi
done
[[ "$already_found" == "true" ]] && continue
# Check if this directory contains projects
if is_project_container "$dir" 2; then
discovered+=("$dir")
fi
done
# Return unique paths
printf '%s\n' "${discovered[@]}" | sort -u
}
# Save discovered paths to config
save_discovered_paths() {
local -a paths=("$@")
ensure_user_dir "$(dirname "$PURGE_CONFIG_FILE")"
cat > "$PURGE_CONFIG_FILE" << 'EOF'
# Mole Purge Paths - Auto-discovered project directories
# Edit this file to customize, or run: mo purge --paths
# Add one path per line (supports ~ for home directory)
EOF
printf '\n' >> "$PURGE_CONFIG_FILE"
for path in "${paths[@]}"; do
# Convert $HOME to ~ for portability
path="${path/#$HOME/~}"
echo "$path" >> "$PURGE_CONFIG_FILE"
done
}
# Load purge paths from config or auto-discover
load_purge_config() {
PURGE_SEARCH_PATHS=()
# Try loading from config file
if [[ -f "$PURGE_CONFIG_FILE" ]]; then
while IFS= read -r line; do
# Remove leading/trailing whitespace
@@ -63,9 +175,30 @@ load_purge_config() {
done < "$PURGE_CONFIG_FILE"
fi
# Fallback to defaults if no paths loaded
# If no paths loaded, auto-discover and save
if [[ ${#PURGE_SEARCH_PATHS[@]} -eq 0 ]]; then
PURGE_SEARCH_PATHS=("${DEFAULT_PURGE_SEARCH_PATHS[@]}")
# Show discovery message if running interactively
if [[ -t 1 ]] && [[ -z "${_PURGE_DISCOVERY_SILENT:-}" ]]; then
echo -e "${GRAY}First run: discovering project directories...${NC}" >&2
fi
local -a discovered=()
while IFS= read -r path; do
[[ -n "$path" ]] && discovered+=("$path")
done < <(discover_project_dirs)
if [[ ${#discovered[@]} -gt 0 ]]; then
PURGE_SEARCH_PATHS=("${discovered[@]}")
# Save for next time
save_discovered_paths "${discovered[@]}"
if [[ -t 1 ]] && [[ -z "${_PURGE_DISCOVERY_SILENT:-}" ]]; then
echo -e "${GRAY}Found ${#discovered[@]} project directories, saved to config${NC}" >&2
fi
else
# Fallback to defaults if nothing found
PURGE_SEARCH_PATHS=("${DEFAULT_PURGE_SEARCH_PATHS[@]}")
fi
fi
}

View File

@@ -7,10 +7,13 @@ set -euo pipefail
# Get script directory and source dependencies
_MOLE_MANAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$_MOLE_MANAGE_DIR/../core/common.sh"
source "$_MOLE_MANAGE_DIR/../clean/project.sh"
# Only source project.sh if not already loaded (has readonly vars)
if [[ -z "${PURGE_TARGETS:-}" ]]; then
source "$_MOLE_MANAGE_DIR/../clean/project.sh"
fi
# Config file path
readonly PURGE_PATHS_CONFIG="$HOME/.config/mole/purge_paths"
# Config file path (use :- to avoid re-declaration if already set)
PURGE_PATHS_CONFIG="${PURGE_PATHS_CONFIG:-$HOME/.config/mole/purge_paths}"
# Ensure config file exists with helpful template
ensure_config_template() {

1
mole
View File

@@ -287,6 +287,7 @@ show_help() {
printf " %s%-28s%s %s\n" "$GREEN" "mo clean --whitelist" "$NC" "Manage protected caches"
printf " %s%-28s%s %s\n" "$GREEN" "mo uninstall --force-rescan" "$NC" "Rescan apps and refresh cache"
printf " %s%-28s%s %s\n" "$GREEN" "mo optimize --whitelist" "$NC" "Manage protected items"
printf " %s%-28s%s %s\n" "$GREEN" "mo purge --paths" "$NC" "Configure scan directories"
echo
printf "%s%s%s\n" "$BLUE" "OPTIONS" "$NC"
printf " %s%-28s%s %s\n" "$GREEN" "--debug" "$NC" "Show detailed operation logs"