Add .gitattributes: *.sh text eol=lf for Windows clones (#19) #21

Merged
pbwraith merged 1 commits from issue-19 into main 2026-08-26 08:45:15 +02:00
Owner

Add .gitattributes so every Windows clone gets LF in the repo's shell scripts

The repo ships three shell scripts (scripts/gate.sh, data/icon/generate.sh,
data/shader/output.sh) and no .gitattributes. Git for Windows defaults to
core.autocrlf=true, so a plain Windows clone checks those files out with CRLF
and scripts/gate.sh dies at exec with /usr/bin/env: 'bash\r': No such file or directory (EXIT=127) — which reads like a broken script even though the
committed blobs are byte-clean. This repo root .gitattributes asserts
*.sh text eol=lf so every clone gets clean scripts.

Diff vs main: one new file, .gitattributes (7 lines) only.
Branch rebased onto current main (8a46ac5).

Verification (fresh clones, core.autocrlf=true set explicitly)

BEFORE — fresh clone of main (no .gitattributes) with core.autocrlf=true:

$ tr -cd '\r' < scripts/gate.sh | wc -c        # → 81
$ tr -cd '\r' < data/icon/generate.sh | wc -c  # → 6
$ tr -cd '\r' < data/shader/output.sh | wc -c  # → 5
$ head -c 24 scripts/gate.sh | od -c           # … b a s h \r \n  ← the bug
$ ./scripts/gate.sh
/usr/bin/env: 'bash\r': No such file or directory
EXIT=127

AFTER — fresh clone of this branch with core.autocrlf=true:

$ tr -cd '\r' < scripts/gate.sh | wc -c        # → 0
$ tr -cd '\r' < data/icon/generate.sh | wc -c  # → 0
$ tr -cd '\r' < data/shader/output.sh | wc -c  # → 0
$ head -c 24 scripts/gate.sh | od -c
0000000   #   !   /   u   s   r   /   b   i   n   /   e   n   v       b
0000020   a   s   h  \n                        # clean shebang, no \r
$ bash -n scripts/gate.sh && bash -n data/icon/generate.sh && bash -n data/shader/output.sh
# all three parse OK

Committed blobs were already byte-clean (git show <branch>:scripts/gate.sh | tr -cd '\r' | wc -c = 0), so no renormalization commit is needed; the
attributes file only governs future checkouts. Existing CRLF working copies
need the documented forced re-checkout (rm -f .git/index && git reset --hard HEAD).

Out of scope per the issue: no change to scripts/gate.sh contents or build
configuration, and the full cargo gate remains blocked by the known disk-space
issue (gitea-worker-ops#24) — this change is verifiable by inspection and a
fresh clone.

Closes #19

## Add `.gitattributes` so every Windows clone gets LF in the repo's shell scripts The repo ships three shell scripts (`scripts/gate.sh`, `data/icon/generate.sh`, `data/shader/output.sh`) and no `.gitattributes`. Git for Windows defaults to `core.autocrlf=true`, so a plain Windows clone checks those files out with CRLF and `scripts/gate.sh` dies at exec with `/usr/bin/env: 'bash\r': No such file or directory` (EXIT=127) — which reads like a broken script even though the committed blobs are byte-clean. This repo root `.gitattributes` asserts `*.sh text eol=lf` so every clone gets clean scripts. **Diff vs `main`:** one new file, `.gitattributes` (7 lines) only. Branch rebased onto current `main` (`8a46ac5`). ## Verification (fresh clones, `core.autocrlf=true` set explicitly) BEFORE — fresh clone of `main` (no `.gitattributes`) with `core.autocrlf=true`: ``` $ tr -cd '\r' < scripts/gate.sh | wc -c # → 81 $ tr -cd '\r' < data/icon/generate.sh | wc -c # → 6 $ tr -cd '\r' < data/shader/output.sh | wc -c # → 5 $ head -c 24 scripts/gate.sh | od -c # … b a s h \r \n ← the bug $ ./scripts/gate.sh /usr/bin/env: 'bash\r': No such file or directory EXIT=127 ``` AFTER — fresh clone of this branch with `core.autocrlf=true`: ``` $ tr -cd '\r' < scripts/gate.sh | wc -c # → 0 $ tr -cd '\r' < data/icon/generate.sh | wc -c # → 0 $ tr -cd '\r' < data/shader/output.sh | wc -c # → 0 $ head -c 24 scripts/gate.sh | od -c 0000000 # ! / u s r / b i n / e n v b 0000020 a s h \n # clean shebang, no \r $ bash -n scripts/gate.sh && bash -n data/icon/generate.sh && bash -n data/shader/output.sh # all three parse OK ``` Committed blobs were already byte-clean (`git show <branch>:scripts/gate.sh | tr -cd '\r' | wc -c` = 0), so no renormalization commit is needed; the attributes file only governs future checkouts. Existing CRLF working copies need the documented forced re-checkout (`rm -f .git/index && git reset --hard HEAD`). Out of scope per the issue: no change to `scripts/gate.sh` contents or build configuration, and the full cargo gate remains blocked by the known disk-space issue (gitea-worker-ops#24) — this change is verifiable by inspection and a fresh clone. Closes #19
pbwraith added 1 commit 2026-08-26 04:46:33 +02:00
Add .gitattributes: *.sh text eol=lf for Windows clones
Some checks failed
Rust / build-linux (linux-x86_64, X64, ubuntu-24.04, x86_64-unknown-linux-gnu) (pull_request) Failing after 4s
Rust / build-android (29.0.14206865, ubuntu-24.04, 33) (pull_request) Failing after 4s
Rust-lint / lint-linux (pull_request) Failing after 16s
Rust / build-linux (linux-aarch64, ARM64, ubuntu-24.04-arm, aarch64-unknown-linux-gnu) (pull_request) Has been cancelled
Rust / build-windows (windows-aarch64, woa64, windows-11-arm, aarch64-pc-windows-msvc) (pull_request) Has been cancelled
Rust / build-windows (windows-x86_64, win64, windows-2025, x86_64-pc-windows-msvc) (pull_request) Has been cancelled
Rust / build-macos (macos-aarch64, ARM64, aarch64-apple-darwin) (pull_request) Has been cancelled
Rust / Collect release artifacts (pull_request) Has been cancelled
cfa469428c
Windows clones default to core.autocrlf=true, which checks out CRLF into
*.sh working copies even though the committed blobs are byte-clean. The
shebang then dies with "env: 'bash\r': No such file or directory"
(exit 127), which read like a broken script rather than a line-ending
artifact. Assert LF for all shell scripts at the repo root so every
Windows clone gets clean scripts/gate.sh, data/icon/generate.sh and
data/shader/output.sh.

Closes #19
Author
Owner

Merged - correct, and it documents its own limits

.gitattributes with *.sh text eol=lf. Seven lines, no code, no build
impact.

I checked the thing that usually makes this change a half-fix: whether the
already-committed blobs are dirty, using tr -cd '\r' | wc -c (not
grep -c $'\r', which is broken in this Git Bash and returns the line count):

git cat-file -p origin/main:scripts/gate.sh | tr -cd '\r' | wc -c   ->  0

The blob is already clean, so no git add --renormalize commit is needed and
none is missing. This is purely preventive for future Windows clones.

The comment in the file also states the trap correctly and unprompted --
that git will not rewrite a working copy whose blob is unchanged, so existing
clones need rm -f .git/index && git reset --hard HEAD. That is exactly right
and is the part people usually get wrong.

Gate, against the composed MERGE RESULT

Not each PR alone -- main + !21 + !22 + !14 merged into one warm clone on the
review box (WSL), then ./scripts/gate.sh:

GATE step 1/3: cargo check --all-targets
GATE step 2/3: cargo test --no-run
GATE step 3/3: cargo test --lib
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; finished in 57.65s
GATE_OK

Control on origin/main @ 8a46ac5 in the same clone: gate_exit=0, but
step 3 ran 0 tests. So this set also makes gate step 3 non-vacuous for the
first time -- 0 -> 4 real tests.

## Merged - correct, and it documents its own limits `.gitattributes` with `*.sh text eol=lf`. Seven lines, no code, no build impact. I checked the thing that usually makes this change a half-fix: whether the already-committed blobs are dirty, using `tr -cd '\r' | wc -c` (**not** `grep -c $'\r'`, which is broken in this Git Bash and returns the line count): ``` git cat-file -p origin/main:scripts/gate.sh | tr -cd '\r' | wc -c -> 0 ``` The blob is already clean, so no `git add --renormalize` commit is needed and none is missing. This is purely preventive for future Windows clones. The comment in the file also states the trap correctly and unprompted -- that git will not rewrite a working copy whose blob is unchanged, so existing clones need `rm -f .git/index && git reset --hard HEAD`. That is exactly right and is the part people usually get wrong. ### Gate, against the composed MERGE RESULT Not each PR alone -- `main` + !21 + !22 + !14 merged into one warm clone on the review box (WSL), then `./scripts/gate.sh`: ``` GATE step 1/3: cargo check --all-targets GATE step 2/3: cargo test --no-run GATE step 3/3: cargo test --lib test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; finished in 57.65s GATE_OK ``` Control on `origin/main` @ `8a46ac5` in the same clone: `gate_exit=0`, but step 3 ran **0 tests**. So this set also makes gate step 3 non-vacuous for the first time -- 0 -> 4 real tests.
pbwraith merged commit 82a4e2ba2f into main 2026-08-26 08:45:15 +02:00
This repo is archived. You cannot comment on pull requests.
No description provided.