#!/usr/bin/env bash # Refuse to commit working memory, and refuse format-only dirt nobody staged. # # `context/` is local: artifacts, externals, agent clones and the RE tooling and # its bases live there and `.gitignore` keeps them out. This is the second wall # — `git add -f` walks through the first. Nothing under `context/` is an # exception: the shipped repo is the runtime, and the RE side of the work is not # published. # # Installed from xtask/githooks/pre-commit by `cargo xtask mr new|fmt|ship`. set -euo pipefail ROOT="$(git rev-parse --show-toplevel)" # Deletions (untracking something that should never have been in) are fine. staged=() while IFS= read -r rel; do [[ -n "$rel" ]] || continue staged+=("$rel") done < <(git diff --cached --name-only --diff-filter=ACMR -- context/ || true) if ((${#staged[@]} > 0)); then printf '%s\n' \ 'pre-commit: context/ is working memory, not the product. Do not git add it (not even -f).' \ 'The files stay on disk. Unstage with:' \ ' git restore --staged -- context/' \ 'Nothing under context/ belongs in git.' \ 'Staged paths:' >&2 printf ' %s\n' "${staged[@]}" >&2 exit 1 fi # Unstaged .rs whose working tree equals rustfmt(index) is the cargo-fmt-all # leftover: files the agent did not stage, rewritten in place. Real WIP does # not compare equal. Do not guess "my files" — refuse the leftover. if command -v rustfmt >/dev/null; then dirt=() tmpdir="$(mktemp -d)" cleanup() { rm -rf "$tmpdir"; } trap cleanup EXIT while IFS= read -r rel; do [[ -n "$rel" && "$rel" == *.rs ]] || continue wt="$ROOT/$rel" [[ -f "$wt" ]] || continue idx="$tmpdir/idx.rs" if ! git show ":$rel" >"$idx" 2>/dev/null; then continue fi if ! rustfmt --edition 2024 "$idx" >/dev/null 2>&1; then continue fi if cmp -s "$idx" "$wt"; then dirt+=("$rel") fi done < <(git diff --name-only --diff-filter=ACMR || true) if ((${#dirt[@]} > 0)); then printf '%s\n' \ 'pre-commit: unstaged .rs files match rustfmt(index) — likely cargo fmt --all / -p.' \ 'Restore them; format only the files you own:' \ " git restore -- ${dirt[*]}" \ ' cargo xtask mr fmt ' \ 'Unstaged format-only paths:' >&2 printf ' %s\n' "${dirt[@]}" >&2 exit 1 fi fi exit 0