Files
System-Sync-Restore/bin/ssr-update
T
Oliver Surke 9f745178b3 Add ssr update subcommand for self-update
- bin/ssr-update: fast-forward `git pull` on the clone with safety guards
  (dirty tree, detached HEAD, divergent history all abort).
- Re-renders & reloads the launchd plist when launchd/ or bin/ssr* changed
  AND the schedule is currently active, so the cron picks up any plist
  template updates automatically.
- Reports VERSION delta, commit log, and new config keys introduced in
  config/ssr.conf.example so users can opt-in via `ssr config edit`.
- `--dry-run` shows would-be changes without pulling or touching launchd.
- Wired into bin/ssr dispatcher + README updated (Updating section, layout
  entry, command help line).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 15:38:11 +02:00

118 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# ssr-update — pull the latest ssr code from origin and refresh side-effects.
#
# Behavior:
# 1. Verify the repo is a clean git checkout on a real branch.
# 2. git fetch + fast-forward pull. Bail if FF would be impossible.
# 3. Report VERSION delta.
# 4. If the launchd template or any bin/ file changed and the schedule is
# currently active, re-render and reload it.
# 5. If config/ssr.conf.example gained new keys, warn the user.
set -euo pipefail
SSR_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=../lib/common.sh
source "$SSR_ROOT/lib/common.sh"
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case "$1" in
-n|--dry-run) DRY_RUN=true; shift ;;
-h|--help)
cat <<EOF
Usage: ssr update [--dry-run]
Pulls the latest commit on the current branch and re-applies side effects:
- Re-renders & reloads the launchd plist if it changed (when schedule is active).
- Reports added config keys in config/ssr.conf.example.
EOF
exit 0 ;;
*) ssr::die "Unknown flag: $1" ;;
esac
done
ssr::require_cmd git
# --- 1. preflight ---------------------------------------------------------
[[ -d "$SSR_ROOT/.git" ]] \
|| ssr::die "Not a git checkout: $SSR_ROOT (re-clone the repo to enable updates)"
cd "$SSR_ROOT"
branch="$(git symbolic-ref --quiet --short HEAD 2>/dev/null || true)"
[[ -n "$branch" ]] || ssr::die "Detached HEAD — checkout a branch first"
if [[ -n "$(git status --porcelain)" ]]; then
ssr::die "Working tree has local changes — commit, stash, or revert before updating"
fi
origin_url="$(git remote get-url origin 2>/dev/null || true)"
[[ -n "$origin_url" ]] || ssr::die "No 'origin' remote configured"
ssr::log "Updating from $origin_url ($branch)"
# --- 2. fetch + ff pull ---------------------------------------------------
old_sha="$(git rev-parse HEAD)"
old_version="$(cat VERSION 2>/dev/null || echo unknown)"
if $DRY_RUN; then
git fetch --quiet origin "$branch"
new_sha="$(git rev-parse "origin/$branch")"
else
git fetch --quiet origin "$branch"
new_sha="$(git rev-parse "origin/$branch")"
if [[ "$old_sha" == "$new_sha" ]]; then
ssr::ok "Already up to date ($(git rev-parse --short HEAD))"
exit 0
fi
if ! git merge-base --is-ancestor "$old_sha" "$new_sha"; then
ssr::die "Cannot fast-forward (history diverged). Resolve manually: git pull --rebase"
fi
git merge --ff-only --quiet "origin/$branch"
fi
new_version="$(cat VERSION 2>/dev/null || echo unknown)"
if [[ "$old_sha" == "$new_sha" ]]; then
ssr::ok "No changes available."
exit 0
fi
# --- 3. summarize -----------------------------------------------------
ssr::ok "Updated $(git rev-parse --short "$old_sha")$(git rev-parse --short "$new_sha")"
if [[ "$old_version" != "$new_version" ]]; then
ssr::log "Version: $old_version$new_version"
fi
ssr::log "Changes:"
git --no-pager log --oneline "$old_sha..$new_sha" | sed 's/^/ /'
$DRY_RUN && { ssr::log "(dry-run: no side effects executed)"; exit 0; }
# --- 4. launchd refresh -----------------------------------------------
changed_files="$(git --no-pager diff --name-only "$old_sha" "$new_sha")"
plist_changed=false
case "$changed_files" in
*launchd/*|*bin/ssr*) plist_changed=true ;;
esac
label="${SSR_LAUNCHD_LABEL:-de.surke.ssr.sync}"
if $plist_changed && launchctl list 2>/dev/null | grep -q "$label"; then
ssr::log "launchd-relevant files changed → reloading schedule"
"$SSR_ROOT/bin/ssr-schedule" on
fi
# --- 5. config drift hint -------------------------------------------------
example="$SSR_ROOT/config/ssr.conf.example"
user_cfg="${SSR_CONFIG:-$HOME/.config/ssr/ssr.conf}"
if [[ -f "$user_cfg" && -f "$example" ]]; then
new_keys="$(comm -23 \
<(grep -E '^[A-Z_][A-Z0-9_]*=' "$example" | cut -d= -f1 | sort -u) \
<(grep -E '^[A-Z_][A-Z0-9_]*=' "$user_cfg" | cut -d= -f1 | sort -u))"
if [[ -n "$new_keys" ]]; then
ssr::warn "New config keys available in $example:"
echo "$new_keys" | sed 's/^/ /'
echo "Review with: ssr config edit"
fi
fi
ssr::ok "Update complete."