mirror of
https://github.com/tw93/Mole.git
synced 2026-02-16 17:35:16 +00:00
feat(uninstall): keep progress visible until app list is ready
This commit is contained in:
@@ -342,9 +342,11 @@ scan_applications() {
|
|||||||
merged_file="${temp_file}.merged"
|
merged_file="${temp_file}.merged"
|
||||||
refresh_file="${temp_file}.refresh"
|
refresh_file="${temp_file}.refresh"
|
||||||
cache_snapshot_file="${temp_file}.cache"
|
cache_snapshot_file="${temp_file}.cache"
|
||||||
|
local scan_status_file="${temp_file}.scan_status"
|
||||||
: > "$scan_raw_file"
|
: > "$scan_raw_file"
|
||||||
: > "$refresh_file"
|
: > "$refresh_file"
|
||||||
: > "$cache_snapshot_file"
|
: > "$cache_snapshot_file"
|
||||||
|
: > "$scan_status_file"
|
||||||
|
|
||||||
ensure_user_dir "$MOLE_UNINSTALL_META_CACHE_DIR"
|
ensure_user_dir "$MOLE_UNINSTALL_META_CACHE_DIR"
|
||||||
ensure_user_file "$MOLE_UNINSTALL_META_CACHE_FILE"
|
ensure_user_file "$MOLE_UNINSTALL_META_CACHE_FILE"
|
||||||
@@ -411,11 +413,30 @@ scan_applications() {
|
|||||||
if [[ -f "$spinner_shown_file" ]]; then
|
if [[ -f "$spinner_shown_file" ]]; then
|
||||||
printf "\r\033[K" >&2
|
printf "\r\033[K" >&2
|
||||||
fi
|
fi
|
||||||
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file" "${temp_file}.sorted" "${temp_file}.progress" "$spinner_shown_file" 2> /dev/null || true
|
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file" "$scan_status_file" "${temp_file}.sorted" "$spinner_shown_file" 2> /dev/null || true
|
||||||
exit 130
|
exit 130
|
||||||
}
|
}
|
||||||
trap trap_scan_cleanup INT
|
trap trap_scan_cleanup INT
|
||||||
|
|
||||||
|
update_scan_status() {
|
||||||
|
local message="$1"
|
||||||
|
local completed="${2:-0}"
|
||||||
|
local total="${3:-0}"
|
||||||
|
printf "%s|%s|%s\n" "$message" "$completed" "$total" > "$scan_status_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_scan_spinner() {
|
||||||
|
if [[ -n "$spinner_pid" ]]; then
|
||||||
|
kill -TERM "$spinner_pid" 2> /dev/null || true
|
||||||
|
wait "$spinner_pid" 2> /dev/null || true
|
||||||
|
spinner_pid=""
|
||||||
|
fi
|
||||||
|
if [[ -f "$spinner_shown_file" ]]; then
|
||||||
|
printf "\r\033[K" >&2
|
||||||
|
fi
|
||||||
|
rm -f "$spinner_shown_file" "$scan_status_file" 2> /dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
# Pass 1: collect app paths and bundle IDs (no mdls).
|
# Pass 1: collect app paths and bundle IDs (no mdls).
|
||||||
local -a app_data_tuples=()
|
local -a app_data_tuples=()
|
||||||
local -a app_dirs=(
|
local -a app_dirs=(
|
||||||
@@ -489,7 +510,7 @@ scan_applications() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ ${#app_data_tuples[@]} -eq 0 ]]; then
|
if [[ ${#app_data_tuples[@]} -eq 0 ]]; then
|
||||||
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file" "${temp_file}.sorted" "${temp_file}.progress" "$spinner_shown_file" 2> /dev/null || true
|
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file" "$scan_status_file" "${temp_file}.sorted" "$spinner_shown_file" 2> /dev/null || true
|
||||||
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
||||||
restore_scan_int_trap
|
restore_scan_int_trap
|
||||||
printf "\r\033[K" >&2
|
printf "\r\033[K" >&2
|
||||||
@@ -538,22 +559,28 @@ scan_applications() {
|
|||||||
echo "${app_path}|${display_name}|${bundle_id}|${app_mtime}" >> "$output_file"
|
echo "${app_path}|${display_name}|${bundle_id}|${app_mtime}" >> "$output_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
local progress_file="${temp_file}.progress"
|
update_scan_status "Scanning applications..." "0" "$total_apps"
|
||||||
echo "0" > "$progress_file"
|
|
||||||
|
|
||||||
(
|
(
|
||||||
# shellcheck disable=SC2329 # Function invoked indirectly via trap
|
# shellcheck disable=SC2329 # Function invoked indirectly via trap
|
||||||
cleanup_spinner() { exit 0; }
|
cleanup_spinner() { exit 0; }
|
||||||
trap cleanup_spinner TERM INT EXIT
|
trap cleanup_spinner TERM INT EXIT
|
||||||
sleep "$MOLE_UNINSTALL_SCAN_SPINNER_DELAY_SEC" 2> /dev/null || sleep 1
|
sleep "$MOLE_UNINSTALL_SCAN_SPINNER_DELAY_SEC" 2> /dev/null || sleep 1
|
||||||
[[ -f "$progress_file" ]] || exit 0
|
[[ -f "$scan_status_file" ]] || exit 0
|
||||||
local spinner_chars="|/-\\"
|
local spinner_chars="|/-\\"
|
||||||
local i=0
|
local i=0
|
||||||
: > "$spinner_shown_file"
|
: > "$spinner_shown_file"
|
||||||
while true; do
|
while true; do
|
||||||
local completed=$(cat "$progress_file" 2> /dev/null || echo 0)
|
local status_line status_message status_completed status_total
|
||||||
|
status_line=$(cat "$scan_status_file" 2> /dev/null || echo "")
|
||||||
|
IFS='|' read -r status_message status_completed status_total <<< "$status_line"
|
||||||
|
[[ -z "$status_message" ]] && status_message="Scanning applications..."
|
||||||
local c="${spinner_chars:$((i % 4)):1}"
|
local c="${spinner_chars:$((i % 4)):1}"
|
||||||
printf "\r\033[K%s Scanning applications... %d/%d" "$c" "$completed" "$total_apps" >&2
|
if [[ "$status_completed" =~ ^[0-9]+$ && "$status_total" =~ ^[0-9]+$ && $status_total -gt 0 ]]; then
|
||||||
|
printf "\r\033[K%s %s %d/%d" "$c" "$status_message" "$status_completed" "$status_total" >&2
|
||||||
|
else
|
||||||
|
printf "\r\033[K%s %s" "$c" "$status_message" >&2
|
||||||
|
fi
|
||||||
((i++))
|
((i++))
|
||||||
sleep 0.1 2> /dev/null || sleep 1
|
sleep 0.1 2> /dev/null || sleep 1
|
||||||
done
|
done
|
||||||
@@ -564,7 +591,7 @@ scan_applications() {
|
|||||||
((app_count++))
|
((app_count++))
|
||||||
process_app_metadata "$app_data_tuple" "$scan_raw_file" &
|
process_app_metadata "$app_data_tuple" "$scan_raw_file" &
|
||||||
pids+=($!)
|
pids+=($!)
|
||||||
echo "$app_count" > "$progress_file"
|
update_scan_status "Scanning applications..." "$app_count" "$total_apps"
|
||||||
|
|
||||||
if ((${#pids[@]} >= max_parallel)); then
|
if ((${#pids[@]} >= max_parallel)); then
|
||||||
wait "${pids[0]}" 2> /dev/null
|
wait "${pids[0]}" 2> /dev/null
|
||||||
@@ -576,27 +603,18 @@ scan_applications() {
|
|||||||
wait "$pid" 2> /dev/null
|
wait "$pid" 2> /dev/null
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ -n "$spinner_pid" ]]; then
|
update_scan_status "Building uninstall index..." "0" "0"
|
||||||
kill -TERM "$spinner_pid" 2> /dev/null || true
|
|
||||||
wait "$spinner_pid" 2> /dev/null || true
|
|
||||||
fi
|
|
||||||
if [[ -f "$spinner_shown_file" ]]; then
|
|
||||||
echo -ne "\r\033[K" >&2
|
|
||||||
fi
|
|
||||||
rm -f "$progress_file" "$spinner_shown_file"
|
|
||||||
|
|
||||||
if [[ ! -s "$scan_raw_file" ]]; then
|
if [[ ! -s "$scan_raw_file" ]]; then
|
||||||
|
stop_scan_spinner
|
||||||
echo "No applications found to uninstall" >&2
|
echo "No applications found to uninstall" >&2
|
||||||
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file" "${temp_file}.sorted" "${temp_file}.progress" "$spinner_shown_file" 2> /dev/null || true
|
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file" "${temp_file}.sorted" "$spinner_shown_file" 2> /dev/null || true
|
||||||
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
||||||
restore_scan_int_trap
|
restore_scan_int_trap
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $total_apps -gt 50 ]]; then
|
update_scan_status "Merging cache data..." "0" "0"
|
||||||
printf "\rProcessing %d applications... " "$total_apps" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
awk -F'|' '
|
awk -F'|' '
|
||||||
NR == FNR {
|
NR == FNR {
|
||||||
cache_mtime[$1] = $2
|
cache_mtime[$1] = $2
|
||||||
@@ -618,8 +636,18 @@ scan_applications() {
|
|||||||
local current_epoch
|
local current_epoch
|
||||||
current_epoch=$(get_epoch_seconds)
|
current_epoch=$(get_epoch_seconds)
|
||||||
local inline_metadata_count=0
|
local inline_metadata_count=0
|
||||||
|
local metadata_total=0
|
||||||
|
metadata_total=$(wc -l < "$merged_file" 2> /dev/null || echo "0")
|
||||||
|
[[ "$metadata_total" =~ ^[0-9]+$ ]] || metadata_total=0
|
||||||
|
local metadata_processed=0
|
||||||
|
update_scan_status "Collecting metadata..." "0" "$metadata_total"
|
||||||
|
|
||||||
while IFS='|' read -r app_path display_name bundle_id app_mtime cached_mtime cached_size_kb cached_epoch cached_updated_epoch cached_bundle_id cached_display_name; do
|
while IFS='|' read -r app_path display_name bundle_id app_mtime cached_mtime cached_size_kb cached_epoch cached_updated_epoch cached_bundle_id cached_display_name; do
|
||||||
|
((metadata_processed++))
|
||||||
|
if ((metadata_processed % 5 == 0 || metadata_processed == metadata_total)); then
|
||||||
|
update_scan_status "Collecting metadata..." "$metadata_processed" "$metadata_total"
|
||||||
|
fi
|
||||||
|
|
||||||
[[ -n "$app_path" && -e "$app_path" ]] || continue
|
[[ -n "$app_path" && -e "$app_path" ]] || continue
|
||||||
|
|
||||||
local cache_match=false
|
local cache_match=false
|
||||||
@@ -698,6 +726,7 @@ scan_applications() {
|
|||||||
echo "${final_epoch}|${app_path}|${display_name}|${bundle_id}|${final_size}|${final_last_used}|${final_size_kb}" >> "$temp_file"
|
echo "${final_epoch}|${app_path}|${display_name}|${bundle_id}|${final_size}|${final_last_used}|${final_size_kb}" >> "$temp_file"
|
||||||
done < "$merged_file"
|
done < "$merged_file"
|
||||||
|
|
||||||
|
update_scan_status "Updating cache..." "0" "0"
|
||||||
if [[ -s "$cache_snapshot_file" ]]; then
|
if [[ -s "$cache_snapshot_file" ]]; then
|
||||||
if uninstall_acquire_metadata_lock "$MOLE_UNINSTALL_META_CACHE_LOCK"; then
|
if uninstall_acquire_metadata_lock "$MOLE_UNINSTALL_META_CACHE_LOCK"; then
|
||||||
mv "$cache_snapshot_file" "$MOLE_UNINSTALL_META_CACHE_FILE" 2> /dev/null || {
|
mv "$cache_snapshot_file" "$MOLE_UNINSTALL_META_CACHE_FILE" 2> /dev/null || {
|
||||||
@@ -708,7 +737,9 @@ scan_applications() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
update_scan_status "Sorting application list..." "0" "0"
|
||||||
sort -t'|' -k1,1n "$temp_file" > "${temp_file}.sorted" || {
|
sort -t'|' -k1,1n "$temp_file" > "${temp_file}.sorted" || {
|
||||||
|
stop_scan_spinner
|
||||||
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file"
|
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$refresh_file" "$cache_snapshot_file"
|
||||||
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
||||||
restore_scan_int_trap
|
restore_scan_int_trap
|
||||||
@@ -717,9 +748,9 @@ scan_applications() {
|
|||||||
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$cache_snapshot_file"
|
rm -f "$temp_file" "$scan_raw_file" "$merged_file" "$cache_snapshot_file"
|
||||||
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
[[ $cache_source_is_temp == true ]] && rm -f "$cache_source" 2> /dev/null || true
|
||||||
|
|
||||||
[[ $total_apps -gt 50 ]] && printf "\r\033[K" >&2
|
update_scan_status "Finalizing list..." "0" "0"
|
||||||
|
|
||||||
start_uninstall_metadata_refresh "$refresh_file"
|
start_uninstall_metadata_refresh "$refresh_file"
|
||||||
|
stop_scan_spinner
|
||||||
|
|
||||||
if [[ -f "${temp_file}.sorted" ]]; then
|
if [[ -f "${temp_file}.sorted" ]]; then
|
||||||
restore_scan_int_trap
|
restore_scan_int_trap
|
||||||
|
|||||||
Reference in New Issue
Block a user