#!/usr/bin/env bash # ============================================================================= # upgrade-stash-cleanup.sh — clean up stale upgrade-* git stashes # ============================================================================= # Older versions of upgrade.sh used `git stash push --include-untracked` to # protect tenant content during pulls. When pop conflicts went unresolved, # the stashes accumulated in `git stash list` forever — Pride Corner ended up # with three from 2026-03-09 alone, each containing displaced tenant # customizations that the running site no longer reflected. # # This script lists every `upgrade-*` stash, shows its scope, and offers to # drop them. It does NOT auto-restore content; that's a separate decision per # tenant. The intent is to clear the backlog so future `git stash list` is # meaningful. # # Usage: # bash scripts/upgrade-stash-cleanup.sh # interactive, lists + prompts # bash scripts/upgrade-stash-cleanup.sh --dry # list only # bash scripts/upgrade-stash-cleanup.sh --yes # drop all upgrade-* without prompt # ============================================================================= set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" cd "$PROJECT_DIR" # Colors if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' else RED='' GREEN='' YELLOW='' CYAN='' BOLD='' NC='' fi info() { echo -e "${CYAN}[INFO]${NC} $*"; } ok() { echo -e "${GREEN}[ OK ]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } DRY=false YES=false for arg in "$@"; do case "$arg" in --dry|--dry-run) DRY=true ;; --yes|-y) YES=true ;; --help|-h) sed -n '2,/^# =====/p' "$0" | sed -n '2,/^# =====/p' | sed 's/^# //;s/^#//' exit 0 ;; esac done if [[ ! -d .git ]]; then warn "Not a git repository — this script only applies to source installs." exit 0 fi # Collect upgrade-* stash refs mapfile -t STASHES < <(git stash list 2>/dev/null | grep -E ': (On|WIP on) [^:]+: upgrade-' || true) if [[ ${#STASHES[@]} -eq 0 ]]; then ok "No upgrade-* stashes found. Nothing to clean up." exit 0 fi echo "" echo -e "${BOLD}Found ${#STASHES[@]} upgrade-* stash(es):${NC}" echo "" for entry in "${STASHES[@]}"; do REF="${entry%%:*}" LABEL="${entry#*: }" FILE_COUNT=$(git stash show "$REF" --name-only 2>/dev/null | wc -l) HAS_MKDOCS_YML=$(git stash show "$REF" --name-only 2>/dev/null | grep -c '^mkdocs/mkdocs\.yml$' || true) printf " %-12s %-50s files=%-4d mkdocs.yml=%s\n" \ "$REF" "$LABEL" "$FILE_COUNT" "$HAS_MKDOCS_YML" done echo "" if [[ "$DRY" == "true" ]]; then info "Dry-run: no stashes will be dropped." exit 0 fi # Warn loudly if any stash holds mkdocs.yml — operator should manually review # before dropping (tenant content might be there). MKDOCS_STASHES=$(printf '%s\n' "${STASHES[@]}" \ | while read -r entry; do REF="${entry%%:*}" if git stash show "$REF" --name-only 2>/dev/null | grep -q '^mkdocs/mkdocs\.yml$'; then echo "$REF" fi done) if [[ -n "$MKDOCS_STASHES" ]]; then echo "" echo -e "${RED}${BOLD}⚠ WARNING:${NC} the following stashes contain ${BOLD}mkdocs/mkdocs.yml${NC}:" echo "$MKDOCS_STASHES" | sed 's/^/ /' echo "" echo " These may hold tenant branding (site_name, site_url, custom theme, etc.)" echo " that ISN'T reflected on disk. Before dropping, verify:" echo "" echo " git show :mkdocs/mkdocs.yml | head -10" echo " diff <(git show :mkdocs/mkdocs.yml) mkdocs/mkdocs.yml" echo "" echo " If disk mkdocs.yml already has the tenant content, the stash is safe to drop." echo " If disk is upstream and stash has tenant content, restore first:" echo " git checkout -- mkdocs/mkdocs.yml" echo "" fi if [[ "$YES" != "true" ]]; then echo -en "${BOLD}Drop all ${#STASHES[@]} upgrade-* stashes? [y/N] ${NC}" read -r CONFIRM case "$CONFIRM" in y|Y|yes|YES) ;; *) info "Cancelled. No stashes dropped."; exit 0 ;; esac fi # Drop in reverse order so indices stay stable mapfile -t SORTED_REFS < <(printf '%s\n' "${STASHES[@]}" \ | sed 's/:.*//' \ | sort -t'{' -k2 -n -r) for REF in "${SORTED_REFS[@]}"; do if git stash drop "$REF" >/dev/null 2>&1; then ok "Dropped $REF" else warn "Failed to drop $REF (already gone?)" fi done echo "" ok "Cleanup complete. Remaining stashes:" git stash list 2>/dev/null || echo " (none)"