Files
diachron/diff-upstream.sh
Michael Wolf 5947dcdc86 Add ? prefix for sample files in file-list; fix bootstrap/upgrade
bootstrap.sh wrote .diachron-version to the temp clone directory
instead of the target project, causing upgrade.sh to fail. Fix that
and teach all three scripts (bootstrap, upgrade, diff-upstream) about
the new ? prefix convention in file-list.

Sample files (?-prefixed) are copied on bootstrap but left alone on
upgrade so user modifications are preserved. New samples introduced
in a newer framework version are still copied if absent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 06:58:09 -05:00

117 lines
3.1 KiB
Bash
Executable File

#!/bin/bash
# Generate a diff of framework files against the upstream version this
# project is based on. Useful for contributing changes back to diachron.
#
# Usage:
# ./diff-upstream.sh # diff against .diachron-version
# ./diff-upstream.sh <ref> # diff against a specific ref
# ./diff-upstream.sh --stat # show changed files only
set -eu
set -o pipefail
IFS=$'\n\t'
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
stat_only=false
ref=""
for arg in "$@"; do
case "$arg" in
--stat) stat_only=true ;;
*) ref="$arg" ;;
esac
done
if [ -z "$ref" ]; then
if [ ! -f "$DIR/.diachron-version" ]; then
echo "Error: .diachron-version not found and no ref specified." >&2
echo "Usage: $0 [--stat] [<ref>]" >&2
exit 1
fi
ref=$(cat "$DIR/.diachron-version")
fi
cached_repo="$HOME/.cache/diachron/v1/repositories/diachron.git"
if [ ! -d "$cached_repo" ]; then
echo "Error: cached repository not found at $cached_repo" >&2
echo "Run ./update-cached-repository.sh first." >&2
exit 1
fi
# Update cached repo
"$DIR/update-cached-repository.sh"
# Verify ref exists
if ! git -C "$cached_repo" rev-parse --verify "$ref^{commit}" >/dev/null 2>&1; then
echo "Error: ref '$ref' not found in cached repository." >&2
exit 1
fi
# Read file-list (strip ? prefix from sample entries)
files=()
while IFS= read -r line; do
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "$line" ]] && continue
files+=("${line#\?}")
done < "$DIR/file-list"
# Check out upstream into a temp directory
tmpdir=$(mktemp -d)
cleanup() { rm -rf "$tmpdir"; }
trap cleanup EXIT
git clone --quiet "$cached_repo" "$tmpdir/upstream"
git -C "$tmpdir/upstream" checkout --quiet "$ref"
# Generate diff
if $stat_only; then
diff -rq "$tmpdir/upstream" "$DIR" \
--no-dereference \
2>/dev/null \
| grep -v '^\.' \
|| true
# Simpler: just list files that differ
for f in "${files[@]}"; do
# Skip directories
[ -d "$DIR/$f" ] && continue
upstream="$tmpdir/upstream/$f"
local="$DIR/$f"
if [ ! -f "$upstream" ] && [ -f "$local" ]; then
echo "added: $f"
elif [ -f "$upstream" ] && [ ! -f "$local" ]; then
echo "removed: $f"
elif [ -f "$upstream" ] && [ -f "$local" ]; then
if ! diff -q "$upstream" "$local" >/dev/null 2>&1; then
echo "modified: $f"
fi
fi
done
else
for f in "${files[@]}"; do
[ -d "$DIR/$f" ] && continue
upstream="$tmpdir/upstream/$f"
local="$DIR/$f"
if [ ! -f "$upstream" ] && [ -f "$local" ]; then
diff -u /dev/null "$local" \
--label "a/$f" --label "b/$f" \
|| true
elif [ -f "$upstream" ] && [ ! -f "$local" ]; then
diff -u "$upstream" /dev/null \
--label "a/$f" --label "b/$f" \
|| true
elif [ -f "$upstream" ] && [ -f "$local" ]; then
diff -u "$upstream" "$local" \
--label "a/$f" --label "b/$f" \
|| true
fi
done
fi