mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 18:07:06 +01:00
Two levels of pure taxonomy carrying no information, and a 2-directory
cap leaves no room for them. Categories now sit directly under
linux_configuration/: features, fixes, utils, misc, fresh-install,
installers, diagnostics, gaming, boot_recovery, periodic_background, lib,
meta, tests. A script's own lib/ and tests/ are exempt from the cap, so
those stay put.
Depth violations 248 -> 139; roughly 40 of the remainder are inside
digital_wellbeing and hosts, deferred until the guard-lib repoint.
The moves are the easy half. What breaks is every path that counted
levels, and three classes of it had to be found by resolving paths rather
than reading diffs:
- 52 relative `source` lines for lib/common.sh and lib/android.sh. The
correct prefix differs per file: 40 were ../../ and 12 were ../../../,
so a blanket replace would have fixed one set and broken the other.
- REPO_ROOT in 7 fixes/lib/tests harnesses and setup_syncyomi_guard.sh,
each walking up four levels from a directory now two levels shallower.
This caused a real regression -- the fixes suite went red with
"log_warn: command not found" -- caught by running it and comparing
against the pre-move baseline worktree.
- conftest.py's sys.path entries, which took the pytest gate down with
14 collection errors, and the `# shellcheck source=` directives, which
took shellcheck down with SC1091.
16 symlinks in $HOME broke, including the entire i3blocks bar. All
repointed, and cpu_monitor/memory/disk/time/volume were run to confirm
they emit real output rather than merely resolving.
Verified: 1798 tests pass at 100% coverage, 8 of 9 lib/tests suites pass
(the ninth needs the coverage jail, identically at baseline), pre-commit
is clean, and the two untracked secret configs are still ignored after
their gitignore paths changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
225 lines
8.1 KiB
Bash
Executable File
225 lines
8.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Unlock shutdown schedule config for editing with smart friction
|
|
# This script:
|
|
# - NO delay if making schedule STRICTER (earlier shutdown hours)
|
|
# - DELAY if making schedule more LENIENT (later shutdown hours)
|
|
# - BLOCKS lowering MORNING_END_HOUR (that would shorten the shutdown window)
|
|
|
|
set -euo pipefail
|
|
|
|
DELAY_SECONDS=45
|
|
GUARD_NAME="shutdown-schedule"
|
|
CONFIG_FILE="/etc/shutdown-schedule.conf"
|
|
LOG_FILE="/var/log/shutdown-schedule-guard.log"
|
|
EDITOR="${EDITOR:-nano}"
|
|
TEMP_FILE="/tmp/shutdown-schedule-edit.$$"
|
|
|
|
log() {
|
|
printf '%s - %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG_FILE" >&2
|
|
}
|
|
|
|
# Must be root
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root (sudo)"
|
|
exit 1
|
|
fi
|
|
|
|
CANONICAL_FILE="$(guardctl file-guard canonical-path "$GUARD_NAME")"
|
|
if [[ -z "$CANONICAL_FILE" ]]; then
|
|
echo "Error: guard-lib instance '$GUARD_NAME' is not installed (guardctl file-guard canonical-path returned empty)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Log the unlock attempt
|
|
log "=== UNLOCK ATTEMPT by $(logname 2>/dev/null || echo 'unknown') from TTY $(tty 2>/dev/null || echo 'unknown') ==="
|
|
|
|
# Load current values
|
|
OLD_MON_WED=""
|
|
OLD_THU_SUN=""
|
|
OLD_MORNING_END=""
|
|
if [[ -f "$CANONICAL_FILE" ]]; then
|
|
# shellcheck source=/dev/null
|
|
source "$CANONICAL_FILE" 2>/dev/null || true
|
|
OLD_MON_WED="${MON_WED_HOUR:-}"
|
|
OLD_THU_SUN="${THU_SUN_HOUR:-}"
|
|
OLD_MORNING_END="${MORNING_END_HOUR:-}"
|
|
fi
|
|
|
|
echo ""
|
|
echo "╔══════════════════════════════════════════════════════════════════╗"
|
|
echo "║ SHUTDOWN SCHEDULE CONFIG UNLOCK ║"
|
|
echo "╚══════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
echo "Current schedule:"
|
|
echo " Monday-Wednesday: ${OLD_MON_WED:-??}:00 - 0${OLD_MORNING_END:-?}:00"
|
|
echo " Thursday-Sunday: ${OLD_THU_SUN:-??}:00 - 0${OLD_MORNING_END:-?}:00"
|
|
echo ""
|
|
echo "Rules:"
|
|
echo " ✓ Making shutdown EARLIER (stricter) = No delay"
|
|
echo " ⏳ Making shutdown LATER (lenient) = ${DELAY_SECONDS}s delay required"
|
|
echo " ❌ Lowering MORNING_END_HOUR = BLOCKED (would shorten shutdown window)"
|
|
echo ""
|
|
|
|
# Stop the path watcher temporarily. This is NOT optional: `chattr -i`
|
|
# below is itself enough to fire guard-file@shutdown-schedule.path (its
|
|
# PathModified reacts to attribute changes, not just content writes), and
|
|
# that watcher's enforce pass unconditionally re-locks the target at the
|
|
# end even when no drift is found - which would silently re-lock the file
|
|
# out from under us during the 45s delay below. Confirmed live: without
|
|
# this stop, the delayed-apply cp failed with "Operation not permitted".
|
|
systemctl stop "guard-file@${GUARD_NAME}.path" 2>/dev/null || true
|
|
|
|
# Remove immutable attributes
|
|
chattr -i -a "$CONFIG_FILE" 2>/dev/null || true
|
|
chattr -i -a "$CANONICAL_FILE" 2>/dev/null || true
|
|
|
|
# Copy config to temp file for editing
|
|
cp "$CONFIG_FILE" "$TEMP_FILE"
|
|
|
|
echo "Opening editor..."
|
|
echo ""
|
|
|
|
# Open editor on temp file
|
|
$EDITOR "$TEMP_FILE"
|
|
|
|
# Load new values from edited file
|
|
NEW_MON_WED=""
|
|
NEW_THU_SUN=""
|
|
NEW_MORNING_END=""
|
|
# shellcheck source=/dev/null
|
|
source "$TEMP_FILE" 2>/dev/null || true
|
|
NEW_MON_WED="${MON_WED_HOUR:-}"
|
|
NEW_THU_SUN="${THU_SUN_HOUR:-}"
|
|
NEW_MORNING_END="${MORNING_END_HOUR:-}"
|
|
|
|
echo ""
|
|
echo "Checking changes..."
|
|
|
|
# Check for blocked changes (lowering MORNING_END_HOUR)
|
|
if [[ -n "$OLD_MORNING_END" ]] && [[ -n "$NEW_MORNING_END" ]]; then
|
|
if [[ "$NEW_MORNING_END" -lt "$OLD_MORNING_END" ]]; then
|
|
echo ""
|
|
echo "╔══════════════════════════════════════════════════════════════════╗"
|
|
echo "║ ❌ CHANGE BLOCKED - CANNOT LOWER MORNING_END_HOUR ❌ ║"
|
|
echo "╚══════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
echo "You tried to lower MORNING_END_HOUR from $OLD_MORNING_END to $NEW_MORNING_END"
|
|
echo "This would SHORTEN the shutdown window, making it more lenient."
|
|
echo ""
|
|
echo "This change is NOT allowed. The shutdown window must end at"
|
|
echo "0${OLD_MORNING_END}:00 or later."
|
|
echo ""
|
|
rm -f "$TEMP_FILE"
|
|
# Re-apply protection
|
|
chattr +i "$CONFIG_FILE" 2>/dev/null || true
|
|
chattr +i "$CANONICAL_FILE" 2>/dev/null || true
|
|
systemctl start "guard-file@${GUARD_NAME}.path" 2>/dev/null || true
|
|
log "BLOCKED: User tried to lower MORNING_END_HOUR from $OLD_MORNING_END to $NEW_MORNING_END"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Check if changes require delay (making schedule more lenient)
|
|
NEEDS_DELAY=false
|
|
LENIENT_CHANGES=()
|
|
|
|
if [[ -n "$OLD_MON_WED" ]] && [[ -n "$NEW_MON_WED" ]]; then
|
|
if [[ "$NEW_MON_WED" -gt "$OLD_MON_WED" ]]; then
|
|
NEEDS_DELAY=true
|
|
LENIENT_CHANGES+=("Mon-Wed: ${OLD_MON_WED}:00 → ${NEW_MON_WED}:00 (later)")
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$OLD_THU_SUN" ]] && [[ -n "$NEW_THU_SUN" ]]; then
|
|
if [[ "$NEW_THU_SUN" -gt "$OLD_THU_SUN" ]]; then
|
|
NEEDS_DELAY=true
|
|
LENIENT_CHANGES+=("Thu-Sun: ${OLD_THU_SUN}:00 → ${NEW_THU_SUN}:00 (later)")
|
|
fi
|
|
fi
|
|
|
|
# Check for stricter changes (allowed without delay)
|
|
STRICTER_CHANGES=()
|
|
|
|
if [[ -n "$OLD_MON_WED" ]] && [[ -n "$NEW_MON_WED" ]]; then
|
|
if [[ "$NEW_MON_WED" -lt "$OLD_MON_WED" ]]; then
|
|
STRICTER_CHANGES+=("Mon-Wed: ${OLD_MON_WED}:00 → ${NEW_MON_WED}:00 (earlier)")
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$OLD_THU_SUN" ]] && [[ -n "$NEW_THU_SUN" ]]; then
|
|
if [[ "$NEW_THU_SUN" -lt "$OLD_THU_SUN" ]]; then
|
|
STRICTER_CHANGES+=("Thu-Sun: ${OLD_THU_SUN}:00 → ${NEW_THU_SUN}:00 (earlier)")
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$OLD_MORNING_END" ]] && [[ -n "$NEW_MORNING_END" ]]; then
|
|
if [[ "$NEW_MORNING_END" -gt "$OLD_MORNING_END" ]]; then
|
|
STRICTER_CHANGES+=("Morning end: 0${OLD_MORNING_END}:00 → 0${NEW_MORNING_END}:00 (later = longer window)")
|
|
fi
|
|
fi
|
|
|
|
# Report stricter changes
|
|
if [[ ${#STRICTER_CHANGES[@]} -gt 0 ]]; then
|
|
echo ""
|
|
echo "✓ Stricter changes detected (no delay needed):"
|
|
for s in "${STRICTER_CHANGES[@]}"; do
|
|
echo " • $s"
|
|
done
|
|
fi
|
|
|
|
# Handle lenient changes
|
|
if [[ "$NEEDS_DELAY" == true ]]; then
|
|
echo ""
|
|
echo "⚠️ More lenient changes detected:"
|
|
for l in "${LENIENT_CHANGES[@]}"; do
|
|
echo " • $l"
|
|
done
|
|
echo ""
|
|
echo "Are you making this change for a good reason, or are you just"
|
|
echo "trying to stay up later? Remember why you set these limits."
|
|
echo ""
|
|
echo "To proceed, you must wait $DELAY_SECONDS seconds..."
|
|
echo ""
|
|
|
|
# Countdown with opportunity to cancel
|
|
for ((i=DELAY_SECONDS; i>0; i--)); do
|
|
printf "\r ⏳ Waiting: %2d seconds remaining... (Ctrl+C to cancel)" "$i"
|
|
sleep 1
|
|
done
|
|
echo ""
|
|
echo ""
|
|
log "User waited through delay for lenient changes: ${LENIENT_CHANGES[*]}"
|
|
else
|
|
echo ""
|
|
echo "✓ No delay required (schedule is same or stricter)"
|
|
fi
|
|
|
|
# Apply the changes
|
|
cp "$TEMP_FILE" "$CONFIG_FILE"
|
|
cp "$TEMP_FILE" "$CANONICAL_FILE"
|
|
rm -f "$TEMP_FILE"
|
|
|
|
chmod 644 "$CONFIG_FILE"
|
|
chmod 644 "$CANONICAL_FILE"
|
|
|
|
# Re-apply immutable
|
|
chattr +i "$CONFIG_FILE" || echo "Warning: Could not set immutable attribute"
|
|
chattr +i "$CANONICAL_FILE" || echo "Warning: Could not set immutable attribute"
|
|
|
|
# Restart path watcher (stopped near the start of this script)
|
|
systemctl start "guard-file@${GUARD_NAME}.path" 2>/dev/null || true
|
|
|
|
log "Config updated and re-locked by user"
|
|
|
|
echo ""
|
|
echo "✓ Config file updated and re-protected"
|
|
echo "✓ Canonical copy updated"
|
|
echo "✓ Path watcher re-enabled"
|
|
echo ""
|
|
echo "New schedule (will take effect on next timer check):"
|
|
# shellcheck source=/dev/null
|
|
source "$CONFIG_FILE" 2>/dev/null || true
|
|
echo " Monday-Wednesday: ${MON_WED_HOUR:-??}:00 - 0${MORNING_END_HOUR:-?}:00"
|
|
echo " Thursday-Sunday: ${THU_SUN_HOUR:-??}:00 - 0${MORNING_END_HOUR:-?}:00"
|
|
echo ""
|