Add diff-upstream.sh and document framework change workflow
New script extracts a diff of framework files against the upstream ref in .diachron-version. Both DIACHRON.md and diachron/AGENTS.md now explain how to use it and recommend keeping framework changes in discrete, well-described commits to ease upstreaming. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
116
diff-upstream.sh
Executable file
116
diff-upstream.sh
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/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
|
||||
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
|
||||
Reference in New Issue
Block a user