diff --git a/.gitattributes b/.gitattributes index e69de29b..305730ff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -0,0 +1 @@ +.beads/issues.jsonl merge=beads diff --git a/scripts/beads-merge-driver.sh b/scripts/beads-merge-driver.sh new file mode 100755 index 00000000..d3e19d1e --- /dev/null +++ b/scripts/beads-merge-driver.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env sh +# Git merge driver for .beads/issues.jsonl. Reasoning: context/code/tooling.md. +set -eu + +BASE="$1"; OURS="$2"; THEIRS="$3"; PATHNAME="${4:-.beads/issues.jsonl}" + +say() { echo "beads-merge: $*" >&2; } + +if ! command -v bd >/dev/null 2>&1; then + say "bd is not on PATH; leaving $PATHNAME conflicted" + exit 1 +fi + +# Opt-in, because a merge driver that reaches the network fails in ways a merge +# cannot report. Off by default; the export alone is enough for a git merge. +if [ "${BEADS_MERGE_PULL:-0}" = "1" ]; then + bd dolt pull "${BEADS_MERGE_REMOTE:-gh}" >&2 || say "dolt pull failed; continuing from local" +fi + +# Both sides, not just theirs: `bd import` skips any row whose updated_at is not +# strictly newer than the local one, so neither call can move the database +# backwards, and importing OURS restores a database that has lost rows. +for side in "$OURS" "$THEIRS"; do + [ -s "$side" ] || continue + bd import "$side" >&2 || { say "import failed; leaving $PATHNAME conflicted"; exit 1; } +done + +bd export -o "$OURS" || { say "export failed; leaving $PATHNAME conflicted"; exit 1; } + +if grep -qE '^(<<<<<<<|=======|>>>>>>>)' "$OURS"; then + say "export produced conflict markers; refusing" + exit 1 +fi + +say "resolved $PATHNAME from the database ($(wc -l < "$OURS" | tr -d ' ') rows)" +exit 0