fix(build): LF contract for extensionless git hooks + a line-ending guard

The *.sh eol=lf rule landed via #1314, but the git hooks
(scripts/git-hooks/commit-msg, scripts/hooks/pre-commit) are extensionless
and were still at the mercy of core.autocrlf. Add their explicit entries,
plus the contract test from #1272 wired as scripts/test.sh Step 0t: every
shell entrypoint (*.sh + both hook directories) must carry an eol=lf
attribute, with a matched-zero-files guard so a broken glob can never pass
vacuously.

Distilled from #1272: the diagnosis (CRLF checkouts breaking shebangs under
WSL/MSYS), the hook-file coverage, and the guard design are @xumian520's;
verified RED without the *.sh rule (105 uncovered entrypoints) and green
with it (107 files).

Co-Authored-By: xumian520 <126989134+xumian520@users.noreply.github.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin Vogel
2026-08-18 00:20:54 +02:00
parent 07cac7d6b3
commit 32633bab9a
3 changed files with 49 additions and 0 deletions
+6
View File
@@ -5,3 +5,9 @@
# Vendored tree-sitter grammars — machine-generated, hide from stats and diffs
internal/cbm/vendored/grammars/**/parser.c linguist-generated=true diff=false
internal/cbm/vendored/grammars/**/scanner.c linguist-generated=true diff=false
# Shell entrypoints must check out LF everywhere: a CRLF shebang line breaks
# them under WSL/MSYS (`bash\r: no such file`). The *.sh rule covers scripts;
# the git hooks are extensionless and need explicit entries. (#1272)
scripts/git-hooks/commit-msg text eol=lf
scripts/hooks/pre-commit text eol=lf
+3
View File
@@ -260,6 +260,9 @@ bash "$ROOT/tests/test_release_gate_chain_contract.sh"
echo "=== Step 0t: test runtime isolation contract (#1691) ==="
bash "$ROOT/tests/test_runtime_isolation_contract.sh"
echo "=== Step 0u: shell line-ending contract ==="
bash "$ROOT/tests/test_shell_line_endings.sh"
# Verify compiler supports target arch
verify_compiler "$CC"
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Regression guard: shell entrypoints must remain LF in Windows checkouts so
# they can run directly from WSL and MSYS without a `bash\r` shebang failure.
#
# Distilled from PR #1272 by @xumian520, who both hit the breakage under
# core.autocrlf=true and wrote this contract so it stays fixed. The .sh rule
# itself landed via #1314; the extensionless git hooks need their own
# entries, which this guard also covers.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
failures=0
checked=0
while IFS= read -r -d '' path &&
IFS= read -r -d '' attribute &&
IFS= read -r -d '' eol; do
checked=$((checked + 1))
if [[ "$eol" != "lf" ]]; then
echo "FAIL: $path must declare eol=lf (got ${eol:-unset})" >&2
failures=$((failures + 1))
fi
done < <(
git ls-files -z '*.sh' 'scripts/git-hooks/*' 'scripts/hooks/*' |
git check-attr -z --stdin eol
)
if ((checked == 0)); then
echo "FAIL: the line-ending contract matched no files — the glob set is broken" >&2
exit 1
fi
if ((failures > 0)); then
echo "FAIL: $failures shell entrypoint(s) lack an LF checkout contract" >&2
exit 1
fi
echo "Shell line-ending contract passed ($checked files)"