diff --git a/scripts/extract.sh b/scripts/extract.sh new file mode 100644 index 0000000..212a29a --- /dev/null +++ b/scripts/extract.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# Reverse sync: show diff between consumer-file and brain template, optionally apply +# +# Usage: extract.sh --source= --file= [--dry-run] +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +source "$SCRIPT_DIR/lib/common.sh" + +BRAIN_ROOT="${BRAIN_ROOT:-$(cd "$SCRIPT_DIR/.." && pwd)}" + +source_dir="" +file="" +dry_run=0 + +while [ $# -gt 0 ]; do + case "$1" in + --source=*) source_dir="${1#--source=}" ;; + --file=*) file="${1#--file=}" ;; + --dry-run) dry_run=1 ;; + *) log_error "Unknown: $1"; exit 1 ;; + esac + shift +done + +[ -n "$source_dir" ] || { log_error "--source required"; exit 1; } +[ -n "$file" ] || { log_error "--file required"; exit 1; } + +consumer_file="$source_dir/$file" +[ -f "$consumer_file" ] || { log_error "Not found: $consumer_file"; exit 1; } + +# Find brain template (try with and without .template suffix) +brain_file="" +if [ -f "$BRAIN_ROOT/project-files/$file.template" ]; then + brain_file="$BRAIN_ROOT/project-files/$file.template" +elif [ -f "$BRAIN_ROOT/project-files/$file" ]; then + brain_file="$BRAIN_ROOT/project-files/$file" +else + log_error "Brain template not found for: $file" + exit 1 +fi + +log_info "Comparing $consumer_file <-> $brain_file" +if diff -q "$brain_file" "$consumer_file" >/dev/null; then + log_info "Identical, no changes needed" + exit 0 +fi + +log_warn "Files differ:" +diff -u "$brain_file" "$consumer_file" || true + +if [ "$dry_run" -eq 1 ]; then + exit 2 +fi + +# Interactive prompt +printf "Action [a]pply / [r]eject / [q]uit: " >&2 +read -r action +case "$action" in + a|apply) + cp "$consumer_file" "$brain_file" + log_info "Applied. Don't forget to commit brain repo + bump version." + ;; + r|reject) + log_info "Rejected. Brain template unchanged." + ;; + *) + log_info "Quit. No changes." + ;; +esac diff --git a/scripts/tests/extract-test.sh b/scripts/tests/extract-test.sh new file mode 100644 index 0000000..6074071 --- /dev/null +++ b/scripts/tests/extract-test.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -u +SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +source "$SCRIPT_DIR/lib/common.sh" + +FAILURES=0 +assert_eq() { + if [ "$1" = "$2" ]; then echo "PASS: $3"; else echo "FAIL: $3 (expected '$1', got '$2')"; FAILURES=$((FAILURES + 1)); fi +} + +# Test: identical content → exit 0 (no diff) +tmpdir=$(mktemp -d) +brain="$tmpdir/brain" +consumer="$tmpdir/consumer" +mkdir -p "$brain/project-files" "$consumer" +echo "same content" > "$brain/project-files/CLAUDE.md.template" +echo "same content" > "$consumer/CLAUDE.md" + +BRAIN_ROOT="$brain" bash "$SCRIPT_DIR/extract.sh" --source="$consumer" --file=CLAUDE.md --dry-run >/dev/null 2>&1 +assert_eq "0" "$?" "identical content returns exit 0" + +# Test: different content → exit non-zero +echo "consumer different" > "$consumer/CLAUDE.md" +BRAIN_ROOT="$brain" bash "$SCRIPT_DIR/extract.sh" --source="$consumer" --file=CLAUDE.md --dry-run >/dev/null 2>&1 +result=$? +[ "$result" -ne 0 ] && assert_eq "0" "0" "different content returns non-zero" || assert_eq "0" "1" "different content returns non-zero" + +rm -rf "$tmpdir" + +echo "---" +echo "Failures: $FAILURES" +exit $FAILURES