diff --git a/bin/clean.sh b/bin/clean.sh index c0e7d01..914cb09 100755 --- a/bin/clean.sh +++ b/bin/clean.sh @@ -137,6 +137,11 @@ note_activity() { fi } +# shellcheck disable=SC2329 +has_cached_sudo() { + sudo -n true 2> /dev/null +} + CLEANUP_DONE=false # shellcheck disable=SC2329 cleanup() { @@ -717,7 +722,6 @@ start_cleanup() { if [[ "$DRY_RUN" == "true" ]]; then echo -e "${YELLOW}Dry Run Mode${NC}, Preview only, no deletions" echo "" - SYSTEM_CLEAN=false ensure_user_file "$EXPORT_LIST_FILE" cat > "$EXPORT_LIST_FILE" << EOF @@ -732,11 +736,22 @@ start_cleanup() { # EOF + + # Preview system section when sudo is already cached (no password prompt). + if has_cached_sudo; then + SYSTEM_CLEAN=true + echo -e "${GREEN}${ICON_SUCCESS}${NC} Admin access available, system preview included" + echo "" + else + SYSTEM_CLEAN=false + echo -e "${GRAY}${ICON_WARNING} System caches need sudo, run ${NC}sudo -v && mo clean --dry-run${GRAY} for full preview${NC}" + echo "" + fi return fi if [[ -t 0 ]]; then - if sudo -n true 2> /dev/null; then + if has_cached_sudo; then SYSTEM_CLEAN=true echo -e "${GREEN}${ICON_SUCCESS}${NC} Admin access already available" echo "" @@ -776,7 +791,7 @@ EOF else echo "" echo "Running in non-interactive mode" - if sudo -n true 2> /dev/null; then + if has_cached_sudo; then SYSTEM_CLEAN=true echo " ${ICON_LIST} System-level cleanup enabled, sudo session active" else diff --git a/tests/clean_core.bats b/tests/clean_core.bats index 3994c64..8da50b2 100644 --- a/tests/clean_core.bats +++ b/tests/clean_core.bats @@ -25,13 +25,66 @@ setup() { rm -rf "${HOME:?}"/* rm -rf "$HOME/Library" "$HOME/.config" mkdir -p "$HOME/Library/Caches" "$HOME/.config/mole" + unset TEST_MOCK_BIN +} + +set_mock_sudo_cached() { + TEST_MOCK_BIN="$HOME/bin" + mkdir -p "$TEST_MOCK_BIN" + cat > "$TEST_MOCK_BIN/sudo" << 'MOCK' +#!/bin/bash +# Shim: sudo -n true succeeds, all other sudo calls are no-ops. +if [[ "$1" == "-n" && "$2" == "true" ]]; then exit 0; fi +if [[ "$1" == "test" ]]; then exit 1; fi +if [[ "$1" == "find" ]]; then exit 0; fi +exit 0 +MOCK + chmod +x "$TEST_MOCK_BIN/sudo" +} + +set_mock_sudo_uncached() { + TEST_MOCK_BIN="$HOME/bin" + mkdir -p "$TEST_MOCK_BIN" + cat > "$TEST_MOCK_BIN/sudo" << 'MOCK' +#!/bin/bash +# Shim: sudo -n always fails (no cached credentials). +exit 1 +MOCK + chmod +x "$TEST_MOCK_BIN/sudo" +} + +run_clean_dry_run() { + local test_path="$PATH" + if [[ -n "${TEST_MOCK_BIN:-}" ]]; then + test_path="$TEST_MOCK_BIN:$PATH" + fi + + run env HOME="$HOME" MOLE_TEST_MODE=1 PATH="$test_path" \ + "$PROJECT_ROOT/mole" clean --dry-run } @test "mo clean --dry-run skips system cleanup in non-interactive mode" { - run env HOME="$HOME" MOLE_TEST_MODE=1 "$PROJECT_ROOT/mole" clean --dry-run + set_mock_sudo_uncached + run_clean_dry_run [ "$status" -eq 0 ] [[ "$output" == *"Dry Run Mode"* ]] - [[ "$output" != *"Deep system-level cleanup"* ]] + [[ "$output" == *"sudo -v && mo clean --dry-run"* ]] + [[ "$output" != *"system preview included"* ]] +} + +@test "mo clean --dry-run includes system preview when sudo is cached" { + set_mock_sudo_cached + run_clean_dry_run + [ "$status" -eq 0 ] + [[ "$output" == *"system preview included"* ]] +} + +@test "mo clean --dry-run shows hint when sudo is not cached" { + set_mock_sudo_uncached + run_clean_dry_run + [ "$status" -eq 0 ] + [[ "$output" == *"sudo -v"* ]] + [[ "$output" == *"full preview"* ]] } @test "mo clean --dry-run reports user cache without deleting it" { @@ -264,4 +317,3 @@ EOF [[ "$output" == *"Time Machine backup in progress, skipping cleanup"* ]] } -