mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 11:31:46 +00:00
refactor: standardize epoch time retrieval with get_epoch_seconds and ensure locale-independent string transformations.
This commit is contained in:
@@ -369,7 +369,8 @@ safe_clean() {
|
||||
fi
|
||||
|
||||
local idx=0
|
||||
local last_progress_update=$(date +%s)
|
||||
local last_progress_update
|
||||
last_progress_update=$(get_epoch_seconds)
|
||||
for path in "${existing_paths[@]}"; do
|
||||
local size
|
||||
size=$(get_cleanup_path_size_kb "$path")
|
||||
@@ -384,14 +385,15 @@ safe_clean() {
|
||||
((idx++))
|
||||
if [[ $((idx % 20)) -eq 0 && "$show_spinner" == "true" && -t 1 ]]; then
|
||||
update_progress_if_needed "$idx" "${#existing_paths[@]}" last_progress_update 1 || true
|
||||
last_progress_update=$(date +%s)
|
||||
last_progress_update=$(get_epoch_seconds)
|
||||
fi
|
||||
done
|
||||
else
|
||||
local -a pids=()
|
||||
local idx=0
|
||||
local completed=0
|
||||
local last_progress_update=$(date +%s)
|
||||
local last_progress_update
|
||||
last_progress_update=$(get_epoch_seconds)
|
||||
local total_paths=${#existing_paths[@]}
|
||||
|
||||
if [[ ${#existing_paths[@]} -gt 0 ]]; then
|
||||
|
||||
@@ -38,8 +38,8 @@ scan_applications() {
|
||||
ensure_user_dir "$cache_dir"
|
||||
|
||||
if [[ $force_rescan == false && -f "$cache_file" ]]; then
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(date +%s) ]] && cache_age=86401 # Handle mtime read failure
|
||||
local cache_age=$(($(get_epoch_seconds) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(get_epoch_seconds) ]] && cache_age=86401 # Handle mtime read failure
|
||||
if [[ $cache_age -lt $cache_ttl ]]; then
|
||||
if [[ -t 2 ]]; then
|
||||
echo -e "${GREEN}Loading from cache...${NC}" >&2
|
||||
@@ -60,7 +60,7 @@ scan_applications() {
|
||||
temp_file=$(create_temp_file)
|
||||
|
||||
local current_epoch
|
||||
current_epoch=$(date "+%s")
|
||||
current_epoch=$(get_epoch_seconds)
|
||||
|
||||
# Pass 1: collect app paths and bundle IDs (no mdls).
|
||||
local -a app_data_tuples=()
|
||||
@@ -377,8 +377,8 @@ main() {
|
||||
local needs_scanning=true
|
||||
local cache_file="$HOME/.cache/mole/app_scan_cache"
|
||||
if [[ $force_rescan == false && -f "$cache_file" ]]; then
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(date +%s) ]] && cache_age=86401
|
||||
local cache_age=$(($(get_epoch_seconds) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(get_epoch_seconds) ]] && cache_age=86401
|
||||
[[ $cache_age -lt 86400 ]] && needs_scanning=false
|
||||
fi
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ scan_applications() {
|
||||
|
||||
# Check if cache exists and is fresh
|
||||
if [[ $force_rescan == false && -f "$cache_file" ]]; then
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(date +%s) ]] && cache_age=86401 # Handle missing file
|
||||
local cache_age=$(($(get_epoch_seconds) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(get_epoch_seconds) ]] && cache_age=86401 # Handle missing file
|
||||
if [[ $cache_age -lt $cache_ttl ]]; then
|
||||
# Cache hit - return immediately
|
||||
# Show brief flash of cache usage if in interactive mode
|
||||
@@ -107,7 +107,7 @@ scan_applications() {
|
||||
|
||||
# Pre-cache current epoch to avoid repeated calls
|
||||
local current_epoch
|
||||
current_epoch=$(date "+%s")
|
||||
current_epoch=$(get_epoch_seconds)
|
||||
|
||||
# First pass: quickly collect all valid app paths and bundle IDs (NO mdls calls)
|
||||
local -a app_data_tuples=()
|
||||
@@ -454,8 +454,8 @@ main() {
|
||||
local needs_scanning=true
|
||||
local cache_file="$HOME/.cache/mole/app_scan_cache"
|
||||
if [[ $force_rescan == false && -f "$cache_file" ]]; then
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(date +%s) ]] && cache_age=86401 # Handle missing file
|
||||
local cache_age=$(($(get_epoch_seconds) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -eq $(get_epoch_seconds) ]] && cache_age=86401 # Handle missing file
|
||||
[[ $cache_age -lt 86400 ]] && needs_scanning=false
|
||||
fi
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ is_cache_valid() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
local cache_age=$(($(date +%s) - $(get_file_mtime "$cache_file")))
|
||||
local cache_age=$(($(get_epoch_seconds) - $(get_file_mtime "$cache_file")))
|
||||
[[ $cache_age -lt $ttl ]]
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,8 @@ get_uptime_days() {
|
||||
boot_time=$(echo "$boot_output" | awk -F 'sec = |, usec' '{print $2}' 2> /dev/null || echo "")
|
||||
|
||||
if [[ -n "$boot_time" && "$boot_time" =~ ^[0-9]+$ ]]; then
|
||||
local now=$(date +%s 2> /dev/null || echo "0")
|
||||
local now
|
||||
now=$(get_epoch_seconds)
|
||||
local uptime_sec=$((now - boot_time))
|
||||
uptime_days=$(LC_ALL=C awk "BEGIN {printf \"%.1f\", $uptime_sec / 86400}" 2> /dev/null || echo "0")
|
||||
else
|
||||
|
||||
@@ -66,7 +66,8 @@ scan_installed_apps() {
|
||||
local cache_age_seconds=300 # 5 minutes
|
||||
if [[ -f "$cache_file" ]]; then
|
||||
local cache_mtime=$(get_file_mtime "$cache_file")
|
||||
local current_time=$(date +%s)
|
||||
local current_time
|
||||
current_time=$(get_epoch_seconds)
|
||||
local age=$((current_time - cache_mtime))
|
||||
if [[ $age -lt $cache_age_seconds ]]; then
|
||||
debug_log "Using cached app list (age: ${age}s)"
|
||||
@@ -158,7 +159,8 @@ is_bundle_orphaned() {
|
||||
esac
|
||||
if [[ -e "$directory_path" ]]; then
|
||||
local last_modified_epoch=$(get_file_mtime "$directory_path")
|
||||
local current_epoch=$(date +%s)
|
||||
local current_epoch
|
||||
current_epoch=$(get_epoch_seconds)
|
||||
local days_since_modified=$(((current_epoch - last_modified_epoch) / 86400))
|
||||
if [[ $days_since_modified -lt ${ORPHAN_AGE_THRESHOLD:-60} ]]; then
|
||||
return 1
|
||||
|
||||
@@ -16,7 +16,7 @@ clean_homebrew() {
|
||||
local last_cleanup
|
||||
last_cleanup=$(cat "$brew_cache_file" 2> /dev/null || echo "0")
|
||||
local current_time
|
||||
current_time=$(date +%s)
|
||||
current_time=$(get_epoch_seconds)
|
||||
local time_diff=$((current_time - last_cleanup))
|
||||
local days_diff=$((time_diff / 86400))
|
||||
if [[ $days_diff -lt $cache_valid_days ]]; then
|
||||
@@ -112,6 +112,6 @@ clean_homebrew() {
|
||||
# Update cache timestamp when any work succeeded or was intentionally skipped.
|
||||
if [[ "$skip_cleanup" == "true" ]] || [[ "$brew_success" == "true" ]] || [[ "$autoremove_success" == "true" ]]; then
|
||||
ensure_user_file "$brew_cache_file"
|
||||
date +%s > "$brew_cache_file"
|
||||
get_epoch_seconds > "$brew_cache_file"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ is_safe_project_artifact() {
|
||||
fi
|
||||
# Must not be a direct child of the search root.
|
||||
local relative_path="${path#"$search_path"/}"
|
||||
local depth=$(echo "$relative_path" | tr -cd '/' | wc -c)
|
||||
local depth=$(echo "$relative_path" | LC_ALL=C tr -cd '/' | wc -c)
|
||||
if [[ $depth -lt 1 ]]; then
|
||||
return 1
|
||||
fi
|
||||
@@ -398,7 +398,8 @@ is_recently_modified() {
|
||||
fi
|
||||
local mod_time
|
||||
mod_time=$(get_file_mtime "$path")
|
||||
local current_time=$(date +%s)
|
||||
local current_time
|
||||
current_time=$(get_epoch_seconds)
|
||||
local age_seconds=$((current_time - mod_time))
|
||||
local age_in_days=$((age_seconds / 86400))
|
||||
if [[ $age_in_days -lt $age_days ]]; then
|
||||
|
||||
@@ -40,7 +40,7 @@ clean_deep_system() {
|
||||
fi
|
||||
if [[ -d "/macOS Install Data" ]]; then
|
||||
local mtime=$(get_file_mtime "/macOS Install Data")
|
||||
local age_days=$((($(date +%s) - mtime) / 86400))
|
||||
local age_days=$((($(get_epoch_seconds) - mtime) / 86400))
|
||||
debug_log "Found macOS Install Data (age: ${age_days} days)"
|
||||
if [[ $age_days -ge 30 ]]; then
|
||||
local size_kb=$(get_path_size_kb "/macOS Install Data")
|
||||
@@ -58,17 +58,23 @@ clean_deep_system() {
|
||||
start_section_spinner "Scanning system caches..."
|
||||
local code_sign_cleaned=0
|
||||
local found_count=0
|
||||
local last_update_time=$(date +%s)
|
||||
local last_update_time
|
||||
last_update_time=$(get_epoch_seconds)
|
||||
local update_interval=2
|
||||
while IFS= read -r -d '' cache_dir; do
|
||||
if safe_remove "$cache_dir" true; then
|
||||
((code_sign_cleaned++))
|
||||
fi
|
||||
((found_count++))
|
||||
local current_time=$(date +%s)
|
||||
if [[ $((current_time - last_update_time)) -ge $update_interval ]]; then
|
||||
start_section_spinner "Scanning system caches... ($found_count found)"
|
||||
last_update_time=$current_time
|
||||
|
||||
# Optimize: only check time every 50 files
|
||||
if ((found_count % 50 == 0)); then
|
||||
local current_time
|
||||
current_time=$(get_epoch_seconds)
|
||||
if [[ $((current_time - last_update_time)) -ge $update_interval ]]; then
|
||||
start_section_spinner "Scanning system caches... ($found_count found)"
|
||||
last_update_time=$current_time
|
||||
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)
|
||||
stop_section_spinner
|
||||
@@ -155,7 +161,8 @@ clean_time_machine_failed_backups() {
|
||||
[[ -d "$inprogress_file" ]] || continue
|
||||
# Only delete old incomplete backups (safety window).
|
||||
local file_mtime=$(get_file_mtime "$inprogress_file")
|
||||
local current_time=$(date +%s)
|
||||
local current_time
|
||||
current_time=$(get_epoch_seconds)
|
||||
local hours_old=$(((current_time - file_mtime) / 3600))
|
||||
if [[ $hours_old -lt $MOLE_TM_BACKUP_SAFE_HOURS ]]; then
|
||||
continue
|
||||
@@ -200,7 +207,8 @@ clean_time_machine_failed_backups() {
|
||||
while IFS= read -r inprogress_file; do
|
||||
[[ -d "$inprogress_file" ]] || continue
|
||||
local file_mtime=$(get_file_mtime "$inprogress_file")
|
||||
local current_time=$(date +%s)
|
||||
local current_time
|
||||
current_time=$(get_epoch_seconds)
|
||||
local hours_old=$(((current_time - file_mtime) / 3600))
|
||||
if [[ $hours_old -lt $MOLE_TM_BACKUP_SAFE_HOURS ]]; then
|
||||
continue
|
||||
|
||||
@@ -485,7 +485,7 @@ process_container_cache() {
|
||||
if is_critical_system_component "$bundle_id"; then
|
||||
return 0
|
||||
fi
|
||||
if should_protect_data "$bundle_id" || should_protect_data "$(echo "$bundle_id" | tr '[:upper:]' '[:lower:]')"; then
|
||||
if should_protect_data "$bundle_id" || should_protect_data "$(echo "$bundle_id" | LC_ALL=C tr '[:upper:]' '[:lower:]')"; then
|
||||
return 0
|
||||
fi
|
||||
local cache_dir="$container_dir/Data/Library/Caches"
|
||||
@@ -583,7 +583,7 @@ clean_application_support_logs() {
|
||||
for app_dir in ~/Library/Application\ Support/*; do
|
||||
[[ -d "$app_dir" ]] || continue
|
||||
local app_name=$(basename "$app_dir")
|
||||
local app_name_lower=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
|
||||
local app_name_lower=$(echo "$app_name" | LC_ALL=C tr '[:upper:]' '[:lower:]')
|
||||
local is_protected=false
|
||||
if should_protect_data "$app_name"; then
|
||||
is_protected=true
|
||||
|
||||
@@ -425,7 +425,7 @@ is_critical_system_component() {
|
||||
[[ -z "$token" ]] && return 1
|
||||
|
||||
local lower
|
||||
lower=$(echo "$token" | tr '[:upper:]' '[:lower:]')
|
||||
lower=$(echo "$token" | LC_ALL=C tr '[:upper:]' '[:lower:]')
|
||||
|
||||
case "$lower" in
|
||||
*backgroundtaskmanagement* | *loginitems* | *systempreferences* | *systemsettings* | *settings* | *preferences* | *controlcenter* | *biometrickit* | *sfl* | *tcc*)
|
||||
@@ -489,7 +489,7 @@ should_protect_path() {
|
||||
[[ -z "$path" ]] && return 1
|
||||
|
||||
local path_lower
|
||||
path_lower=$(echo "$path" | tr '[:upper:]' '[:lower:]')
|
||||
path_lower=$(echo "$path" | LC_ALL=C tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# 1. Keyword-based matching for system components
|
||||
# Protect System Settings, Preferences, Control Center, and related XPC services
|
||||
|
||||
@@ -108,8 +108,30 @@ get_file_mtime() {
|
||||
return
|
||||
}
|
||||
local result
|
||||
result=$($STAT_BSD -f%m "$file" 2> /dev/null)
|
||||
echo "${result:-0}"
|
||||
result=$($STAT_BSD -f%m "$file" 2> /dev/null || echo "")
|
||||
if [[ "$result" =~ ^[0-9]+$ ]]; then
|
||||
echo "$result"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
# Determine date command once
|
||||
if [[ -x /bin/date ]]; then
|
||||
_DATE_CMD="/bin/date"
|
||||
else
|
||||
_DATE_CMD="date"
|
||||
fi
|
||||
|
||||
# Get current time in epoch seconds (defensive against locale/aliases)
|
||||
get_epoch_seconds() {
|
||||
local result
|
||||
result=$($_DATE_CMD +%s 2> /dev/null || echo "")
|
||||
if [[ "$result" =~ ^[0-9]+$ ]]; then
|
||||
echo "$result"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get file owner username
|
||||
@@ -635,11 +657,13 @@ update_progress_if_needed() {
|
||||
local interval="${4:-2}" # Default: update every 2 seconds
|
||||
|
||||
# Get current time
|
||||
local current_time=$(date +%s)
|
||||
local current_time
|
||||
current_time=$(get_epoch_seconds)
|
||||
|
||||
# Get last update time from variable
|
||||
local last_time
|
||||
eval "last_time=\${$last_update_var:-0}"
|
||||
[[ "$last_time" =~ ^[0-9]+$ ]] || last_time=0
|
||||
|
||||
# Check if enough time has elapsed
|
||||
if [[ $((current_time - last_time)) -ge $interval ]]; then
|
||||
|
||||
@@ -590,9 +590,9 @@ opt_spotlight_index_optimize() {
|
||||
local slow_count=0
|
||||
local test_start test_end test_duration
|
||||
for _ in 1 2; do
|
||||
test_start=$(date +%s)
|
||||
test_start=$(get_epoch_seconds)
|
||||
mdfind "kMDItemFSName == 'Applications'" > /dev/null 2>&1 || true
|
||||
test_end=$(date +%s)
|
||||
test_end=$(get_epoch_seconds)
|
||||
test_duration=$((test_end - test_start))
|
||||
if [[ $test_duration -gt 3 ]]; then
|
||||
((slow_count++))
|
||||
|
||||
4
mole
4
mole
@@ -179,7 +179,7 @@ show_version() {
|
||||
local sip_status
|
||||
if command -v csrutil > /dev/null; then
|
||||
sip_status=$(csrutil status 2> /dev/null | grep -o "enabled\|disabled" || echo "Unknown")
|
||||
sip_status="$(tr '[:lower:]' '[:upper:]' <<< "${sip_status:0:1}")${sip_status:1}"
|
||||
sip_status="$(LC_ALL=C tr '[:lower:]' '[:upper:]' <<< "${sip_status:0:1}")${sip_status:1}"
|
||||
else
|
||||
sip_status="Unknown"
|
||||
fi
|
||||
@@ -613,7 +613,7 @@ interactive_main_menu() {
|
||||
local flag_file
|
||||
local cache_dir="$HOME/.cache/mole"
|
||||
ensure_user_dir "$cache_dir"
|
||||
flag_file="$cache_dir/intro_$(echo "$tty_name" | tr -c '[:alnum:]_' '_')"
|
||||
flag_file="$cache_dir/intro_$(echo "$tty_name" | LC_ALL=C tr -c '[:alnum:]_' '_')"
|
||||
if [[ ! -f "$flag_file" ]]; then
|
||||
animate_mole_intro
|
||||
ensure_user_file "$flag_file"
|
||||
|
||||
@@ -302,7 +302,7 @@ create_alfred_workflow() {
|
||||
|
||||
for entry in "${workflows[@]}"; do
|
||||
IFS="|" read -r bundle name keyword subtitle command <<< "$entry"
|
||||
local workflow_uid="user.workflow.$(uuid | tr '[:upper:]' '[:lower:]')"
|
||||
local workflow_uid="user.workflow.$(uuid | LC_ALL=C tr '[:upper:]' '[:lower:]')"
|
||||
local input_uid
|
||||
local action_uid
|
||||
input_uid="$(uuid)"
|
||||
|
||||
Reference in New Issue
Block a user