From 85d0bd025d0275a4b75a0f730e955671e65e5315 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Sun, 14 Dec 2025 01:50:28 -0500 Subject: [PATCH] Fixed snapped stuff. --- zsh/functions/snapper.zsh | 198 +++++++++++++++++++++++++++++++++----- 1 file changed, 173 insertions(+), 25 deletions(-) diff --git a/zsh/functions/snapper.zsh b/zsh/functions/snapper.zsh index 8f02cda..8a22a9a 100644 --- a/zsh/functions/snapper.zsh +++ b/zsh/functions/snapper.zsh @@ -45,7 +45,7 @@ snap-create() { # Get limine.conf state before snapshot echo -e "${SNAP_BLUE}==>${SNAP_NC} Checking limine.conf state before snapshot" local before_checksum=$(sudo md5sum "$limine_conf" | awk '{print $1}') - local before_entries=$(sudo grep -c "^:.*Snapshot" "$limine_conf" || echo "0") + local before_entries=$(sudo grep -cP "^\\s*///\\d+\\s*│" "$limine_conf" || echo "0") echo -e "${SNAP_GREEN}✓${SNAP_NC} Before: $before_entries snapshot entries" echo -e "${SNAP_GREEN}✓${SNAP_NC} Before checksum: $before_checksum" @@ -80,7 +80,7 @@ snap-create() { # Get limine.conf state after snapshot echo -e "${SNAP_BLUE}==>${SNAP_NC} Validating limine.conf update" local after_checksum=$(sudo md5sum "$limine_conf" | awk '{print $1}') - local after_entries=$(sudo grep -c "^:.*Snapshot" "$limine_conf" || echo "0") + local after_entries=$(sudo grep -cP "^\\s*///\\d+\\s*│" "$limine_conf" || echo "0") # Validate the update local validation_passed=true @@ -103,12 +103,17 @@ snap-create() { # Check for the specific snapshot in limine.conf echo -e "\n${SNAP_BLUE}==>${SNAP_NC} Searching for snapshot #$snapshot_num in limine.conf" - if sudo grep -q "Snapshot $snapshot_num" "$limine_conf"; then + # Format in limine.conf is: ///[number] │ [date] + if sudo grep -qP "^\\s*///$snapshot_num\\s*│" "$limine_conf"; then echo -e "${SNAP_GREEN}✓${SNAP_NC} Found snapshot #$snapshot_num in limine.conf" - # Show the entry + # Show the entry with description echo -e "\n${SNAP_BLUE}Snapshot entry:${SNAP_NC}" - sudo grep -A 3 "Snapshot $snapshot_num" "$limine_conf" | sed 's/^/ /' + local entry_line=$(sudo grep -nP "^\\s*///$snapshot_num\\s*│" "$limine_conf" | head -n 1 | cut -d: -f1) + if [[ -n "$entry_line" ]]; then + # Show the snapshot header and description + sudo sed -n "${entry_line}p; $((entry_line+1))p" "$limine_conf" | sed 's/^/ /' + fi else echo -e "${SNAP_RED}✗${SNAP_NC} Snapshot #$snapshot_num NOT found in limine.conf" validation_passed=false @@ -159,8 +164,11 @@ snap-show() { sudo snapper -c root list | grep "^\s*$1\s" echo -e "\n${SNAP_BLUE}In limine.conf:${SNAP_NC}" - if sudo grep -q "Snapshot $1" /boot/limine.conf; then - sudo grep -A 3 "Snapshot $1" /boot/limine.conf + if sudo grep -qP "^\\s*///$1\\s*│" /boot/limine.conf; then + local entry_line=$(sudo grep -nP "^\\s*///$1\\s*│" /boot/limine.conf | head -n 1 | cut -d: -f1) + if [[ -n "$entry_line" ]]; then + sudo sed -n "${entry_line}p; $((entry_line+1))p" /boot/limine.conf + fi else echo -e "${SNAP_YELLOW}⚠${SNAP_NC} Not found in limine.conf" fi @@ -178,8 +186,8 @@ snap-delete() { echo -e "${SNAP_BLUE}==>${SNAP_NC} Deleting snapshot #$snapshot_num" - # Check before deletion - local before_entries=$(sudo grep -c "^:.*Snapshot" "$limine_conf" || echo "0") + # Check before deletion (count snapshot entries using correct format) + local before_entries=$(sudo grep -cP "^\\s*///\\d+\\s*│" "$limine_conf" || echo "0") # Delete the snapshot sudo snapper -c root delete "$snapshot_num" @@ -194,8 +202,8 @@ snap-delete() { # Wait for service to complete sleep 2 - # Check after deletion - local after_entries=$(sudo grep -c "^:.*Snapshot" "$limine_conf" || echo "0") + # Check after deletion (use correct format) + local after_entries=$(sudo grep -cP "^\\s*///\\d+\\s*│" "$limine_conf" || echo "0") if [[ "$after_entries" -lt "$before_entries" ]]; then echo -e "${SNAP_GREEN}✓${SNAP_NC} limine.conf updated (removed entry)" @@ -203,8 +211,8 @@ snap-delete() { echo -e "${SNAP_YELLOW}⚠${SNAP_NC} limine.conf may not have been updated" fi - # Verify snapshot is gone from limine.conf - if ! sudo grep -q "Snapshot $snapshot_num" "$limine_conf"; then + # Verify snapshot is gone from limine.conf (use correct format) + if ! sudo grep -qP "^\\s*///$snapshot_num\\s*│" "$limine_conf"; then echo -e "${SNAP_GREEN}✓${SNAP_NC} Snapshot #$snapshot_num removed from limine.conf" else echo -e "${SNAP_RED}✗${SNAP_NC} Snapshot #$snapshot_num still in limine.conf!" @@ -220,7 +228,7 @@ snap-check-limine() { local limine_conf="/boot/limine.conf" echo -e "${SNAP_BLUE}╔════════════════════════════════════════════════════════════╗${SNAP_NC}" - echo -e "${SNAP_BLUE}║${SNAP_NC} Limine Snapshot Entries ${SNAP_BLUE}║${SNAP_NC}" + echo -e "${SNAP_BLUE}║${SNAP_NC} Limine Snapshot Entries ${SNAP_BLUE}║${SNAP_NC}" echo -e "${SNAP_BLUE}╚════════════════════════════════════════════════════════════╝${SNAP_NC}\n" if [[ ! -f "$limine_conf" ]]; then @@ -228,33 +236,172 @@ snap-check-limine() { return 1 fi - # Count snapshot entries - local entry_count=$(sudo grep -c "^:.*Snapshot" "$limine_conf" || echo "0") + # Get latest snapshot number (excluding snapshot 0) + local latest_snapshot=$(sudo snapper -c root list | tail -n +3 | grep -v "^\s*0\s" | tail -n 1 | awk '{print $1}') + + if [[ -z "$latest_snapshot" ]]; then + echo -e "${SNAP_YELLOW}⚠${SNAP_NC} No snapshots found in snapper" + return 1 + fi + + echo -e "${SNAP_BLUE}Latest snapshot:${SNAP_NC} #$latest_snapshot" + + # Check if latest snapshot is in limine.conf + # Format in limine.conf is: ///49 │ 2025-12-14 01:15:33 + echo -e "${SNAP_BLUE}==>${SNAP_NC} Checking if latest snapshot is in limine.conf" + + if sudo grep -qP "^\\s*///$latest_snapshot\s*│" "$limine_conf"; then + echo -e "${SNAP_GREEN}✓${SNAP_NC} Latest snapshot #$latest_snapshot is present in limine.conf" + + # Show the entry with description + echo -e "\n${SNAP_BLUE}Latest snapshot entry:${SNAP_NC}" + local entry_line=$(sudo grep -nP "^\\s*///$latest_snapshot\s*│" "$limine_conf" | head -n 1 | cut -d: -f1) + if [[ -n "$entry_line" ]]; then + # Show the snapshot header and description (next line) + sudo sed -n "${entry_line}p; $((entry_line+1))p" "$limine_conf" | sed 's/^/ /' + fi + else + echo -e "${SNAP_RED}✗${SNAP_NC} Latest snapshot #$latest_snapshot is NOT in limine.conf" + echo -e "${SNAP_YELLOW}⚠${SNAP_NC} This may indicate the sync service hasn't run yet" + fi + + # Count snapshot entries (lines matching ///[number] │) + echo -e "\n${SNAP_BLUE}==>${SNAP_NC} Counting snapshot entries" + local entry_count=$(sudo grep -cP "^\\s*///\\d+\\s*│" "$limine_conf" || echo "0") echo -e "${SNAP_BLUE}Total snapshot entries:${SNAP_NC} $entry_count\n" # Show all snapshot entries if [[ "$entry_count" -gt 0 ]]; then echo -e "${SNAP_BLUE}Snapshot boot entries:${SNAP_NC}\n" - sudo grep "^:.*Snapshot" "$limine_conf" | nl -w2 -s'. ' + + # Extract snapshot entries with their descriptions + local snap_nums=($(sudo grep -oP "^\\s*///\\K\\d+(?=\\s*│)" "$limine_conf" | sort -n)) + + local i=1 + for snap_num in "${snap_nums[@]}"; do + local snap_line=$(sudo grep -nP "^\\s*///$snap_num\s*│" "$limine_conf" | head -n 1) + local line_num=$(echo "$snap_line" | cut -d: -f1) + local date_time=$(echo "$snap_line" | cut -d: -f2- | grep -oP "│\\s*\\K.*" || echo "") + + # Get description from next line (starts with "comment:") + local desc="" + if [[ -n "$line_num" ]]; then + desc=$(sudo sed -n "$((line_num+1))p" "$limine_conf" | grep -oP "comment:\\s*\\K.*" || echo "") + fi + + printf "%2d. Snapshot #%-3s %s %s\n" "$i" "$snap_num" "$date_time" "${desc:-(no description)}" + ((i++)) + done + + # Show snapshot range + if [[ ${#snap_nums[@]} -gt 0 ]]; then + echo -e "\n${SNAP_BLUE}Snapshot range in boot menu:${SNAP_NC}" + echo -e " Oldest: #${snap_nums[1]}" + echo -e " Newest: #${snap_nums[-1]}" + fi else echo -e "${SNAP_YELLOW}⚠${SNAP_NC} No snapshot entries found in limine.conf" fi # Compare with actual snapshots - echo -e "\n${SNAP_BLUE}Comparing with snapper list:${SNAP_NC}\n" + echo -e "\n${SNAP_BLUE}==>${SNAP_NC} Comparing with snapper list" + echo "" - local snapper_count=$(sudo snapper -c root list | grep -v "single" | tail -n +3 | wc -l) - echo -e "Snapshots in snapper: $snapper_count" + # Count all snapshots except snapshot 0 (current system) + local snapper_count=$(sudo snapper -c root list | tail -n +3 | grep -v "^\s*0\s" | wc -l) + + # Get oldest and newest snapshots + local oldest_snapshot=$(sudo snapper -c root list | tail -n +3 | grep -v "^\s*0\s" | head -n 1 | awk '{print $1}') + + echo -e "Snapshots in snapper: $snapper_count (range: #$oldest_snapshot to #$latest_snapshot)" echo -e "Entries in limine.conf: $entry_count" if [[ "$snapper_count" -eq "$entry_count" ]]; then - echo -e "Status: ${SNAP_GREEN}✓ SYNCED${SNAP_NC}" + echo -e "Status: ${SNAP_GREEN}✓ FULLY SYNCED${SNAP_NC}" else - echo -e "Status: ${SNAP_YELLOW}⚠ OUT OF SYNC${SNAP_NC}" - echo -e "\n${SNAP_YELLOW}Note:${SNAP_NC} Some snapshots may be excluded from boot menu by configuration" + local diff=$((snapper_count - entry_count)) + echo -e "Status: ${SNAP_YELLOW}⚠ PARTIALLY SYNCED${SNAP_NC}" + echo -e "Missing from boot menu: $diff snapshot(s)" + + # Check if latest is present (most important) + if sudo grep -qP "^\\s*///$latest_snapshot\s*│" "$limine_conf"; then + echo -e "\n${SNAP_GREEN}✓${SNAP_NC} Latest snapshot IS available for boot (this is what matters most)" + else + echo -e "\n${SNAP_RED}✗${SNAP_NC} Latest snapshot NOT available for boot (run: snap-sync)" + fi + + echo -e "\n${SNAP_BLUE}Note:${SNAP_NC} limine-snapper-sync typically limits boot entries to recent snapshots" + echo -e " This is normal and prevents boot menu clutter" + + # Check the limit from comment line + local limit_comment=$(sudo grep -oP "comment:\\s*\\K\\d+\\s*/\\s*\\d+" "$limine_conf" | head -n 1) + if [[ -n "$limit_comment" ]]; then + echo -e " Current limit: $limit_comment snapshots" + fi + + # Show which snapshots are missing if there aren't too many + if [[ $diff -le 20 ]]; then + echo -e "\n${SNAP_BLUE}Snapshots NOT in boot menu:${SNAP_NC}" + + local all_snapshots=($(sudo snapper -c root list | tail -n +3 | grep -v "^\s*0\s" | awk '{print $1}')) + local limine_snapshots=($(sudo grep -oP "^\\s*///\\K\\d+(?=\\s*│)" "$limine_conf")) + local missing_count=0 + + for snap_num in "${all_snapshots[@]}"; do + # Check if this snapshot is in limine.conf + local found=false + for limine_snap in "${limine_snapshots[@]}"; do + if [[ "$snap_num" == "$limine_snap" ]]; then + found=true + break + fi + done + + if [[ "$found" == false ]]; then + if [[ $missing_count -lt 10 ]]; then + local snap_info=$(sudo snapper -c root list | grep "^\s*$snap_num\s") + local snap_type=$(echo "$snap_info" | awk '{print $2}') + local snap_desc=$(echo "$snap_info" | awk -F'|' '{print $5}' | xargs) + echo -e " #$snap_num ($snap_type) - $snap_desc" + fi + ((missing_count++)) + fi + done + + if [[ $missing_count -gt 10 ]]; then + echo -e " ... and $((missing_count - 10)) more" + fi + fi fi } +# Show detailed snapshot information with types +snap-info() { + echo -e "${SNAP_BLUE}╔════════════════════════════════════════════════════════════╗${SNAP_NC}" + echo -e "${SNAP_BLUE}║${SNAP_NC} Detailed Snapshot Information ${SNAP_BLUE}║${SNAP_NC}" + echo -e "${SNAP_BLUE}╚════════════════════════════════════════════════════════════╝${SNAP_NC}\n" + + echo -e "${SNAP_BLUE}All snapshots with types:${SNAP_NC}\n" + sudo snapper -c root list + + echo -e "\n${SNAP_BLUE}Breakdown by type:${SNAP_NC}\n" + + local single_count=$(sudo snapper -c root list | grep -c "single" || echo "0") + local pre_count=$(sudo snapper -c root list | grep -c "pre" || echo "0") + local post_count=$(sudo snapper -c root list | grep -c "post" || echo "0") + local total=$(sudo snapper -c root list | tail -n +3 | grep -v "^\s*0\s" | wc -l) + + echo -e "Single snapshots: $single_count" + echo -e "Pre snapshots: $pre_count" + echo -e "Post snapshots: $post_count" + echo -e "Total snapshots: $total" + + echo -e "\n${SNAP_BLUE}Snapshot types explained:${SNAP_NC}" + echo -e " ${SNAP_GREEN}single${SNAP_NC} - Manual snapshots (created by you)" + echo -e " ${SNAP_GREEN}pre${SNAP_NC} - Before system changes (e.g., package updates)" + echo -e " ${SNAP_GREEN}post${SNAP_NC} - After system changes" +} + # Manually trigger sync service snap-sync() { echo -e "${SNAP_BLUE}==>${SNAP_NC} Manually triggering limine-snapper-sync..." @@ -329,7 +476,7 @@ snap-validate-service() { if [[ -f "/boot/limine.conf" ]]; then echo -e "${SNAP_GREEN}✓${SNAP_NC} limine.conf exists" - local snap_entries=$(sudo grep -c "^:.*Snapshot" /boot/limine.conf || echo "0") + local snap_entries=$(sudo grep -cP "^\\s*///\\d+\\s*│" /boot/limine.conf || echo "0") echo -e " Snapshot entries: $snap_entries" else echo -e "${SNAP_RED}✗${SNAP_NC} limine.conf not found" @@ -345,6 +492,7 @@ alias snaprm='snap-delete' alias snapshow='snap-show' alias snapcheck='snap-check-limine' alias snapsync='snap-sync' +alias snapinfo='snap-info' # ============================================================================ # Usage Examples (commented out - uncomment to see examples) @@ -356,4 +504,4 @@ alias snapsync='snap-sync' # snap-delete 42 # snap-check-limine # snap-sync -# snap-validate-serviceNC}" +# snap-validate-service