#!/bin/bash set -eu set -o pipefail IFS=$'\n\t' DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" new_ref="${1:?Usage: upgrade.sh }" cached_repo="$HOME/.cache/diachron/v1/repositories/diachron.git" tmpdir="" cleanup() { if [ -n "$tmpdir" ]; then rm -rf "$tmpdir" fi } trap cleanup EXIT echo "=== Diachron Framework Upgrade ===" echo "" echo "This will replace all framework files in your project." echo "Make sure you have committed or backed up any local changes." echo "" read -r -p "Continue? [y/N] " answer if [[ ! "$answer" =~ ^[Yy]$ ]]; then echo "Aborted." exit 0 fi # Update cached repository "$DIR/update-cached-repository.sh" # Read current version if [ ! -f "$DIR/.diachron-version" ]; then echo "Error: .diachron-version not found." >&2 echo "Is this a diachron project?" >&2 exit 1 fi old_ref=$(cat "$DIR/.diachron-version") # Verify both refs exist in cached repo if ! git -C "$cached_repo" rev-parse --verify "$old_ref^{commit}" >/dev/null 2>&1; then echo "Error: current version '$old_ref' not found in cached repository." >&2 exit 1 fi if ! git -C "$cached_repo" rev-parse --verify "$new_ref^{commit}" >/dev/null 2>&1; then echo "Error: target version '$new_ref' not found in cached repository." >&2 exit 1 fi # Require a clean working tree if [ -n "$(git -C "$DIR" status --porcelain)" ]; then echo "Error: working tree is not clean." >&2 echo "Commit or stash all changes (including untracked files) before upgrading." >&2 exit 1 fi echo "" echo "Upgrading: $old_ref -> $new_ref" echo "" # Read current file-list (files to remove) # Entries prefixed with ? are sample files -- we don't remove those on upgrade. old_files=() old_samples=() while IFS= read -r line; do [[ "$line" =~ ^[[:space:]]*# ]] && continue [[ -z "$line" ]] && continue if [[ "$line" == \?* ]]; then old_samples+=("${line#\?}") else old_files+=("$line") fi done < "$DIR/file-list" # Clone and checkout new version into a temp directory tmpdir=$(mktemp -d) git clone --quiet "$cached_repo" "$tmpdir/diachron" git -C "$tmpdir/diachron" checkout --quiet "$new_ref" # Read new file-list (files to add) new_files=() new_samples=() while IFS= read -r line; do [[ "$line" =~ ^[[:space:]]*# ]] && continue [[ -z "$line" ]] && continue if [[ "$line" == \?* ]]; then new_samples+=("${line#\?}") else new_files+=("$line") fi done < "$tmpdir/diachron/file-list" # Remove old framework files (not samples -- those belong to the user) for f in "${old_files[@]}"; do git -C "$DIR" rm -rf --quiet --ignore-unmatch "$f" done # Copy in new framework files (cd "$tmpdir/diachron" && tar cf - "${new_files[@]}") | (cd "$DIR" && tar xf -) # Stage them for f in "${new_files[@]}"; do git -C "$DIR" add "$f" done # Handle sample files: copy only if the user doesn't already have them samples_added=() samples_skipped=() for f in "${new_samples[@]}"; do if [ -e "$DIR/$f" ]; then samples_skipped+=("$f") else # New sample that doesn't exist yet -- copy it in (cd "$tmpdir/diachron" && tar cf - "$f") | (cd "$DIR" && tar xf -) git -C "$DIR" add "$f" samples_added+=("$f") fi done # Update version marker echo "$new_ref" > "$DIR/.diachron-version" git -C "$DIR" add "$DIR/.diachron-version" echo "=== Upgrade staged: $old_ref -> $new_ref ===" echo "" echo "Framework files have been removed, replaced, and staged." if [ ${#samples_added[@]} -gt 0 ]; then echo "" echo "New sample files added:" for f in "${samples_added[@]}"; do echo " + $f" done fi if [ ${#samples_skipped[@]} -gt 0 ]; then echo "" echo "Sample files skipped (you already have these):" for f in "${samples_skipped[@]}"; do echo " ~ $f" done fi echo "" echo "Next steps:" echo " 1. Review: git diff --cached" echo " 2. Commit: git commit -m 'Upgrade diachron to $new_ref'" echo " 3. Install: ./sync.sh"