fix: keep shell scripts on LF line endings on every checkout - #1411
Merged
Merged
Conversation
Git for Windows installs with core.autocrlf=true, which rewrites text
files to CRLF on checkout. Bash reads the trailing carriage return as
part of each line, so a CRLF script dies on its first real statement
("command not found", then "set: pipefail: invalid option name"). The
repo had no .gitattributes, so every bash gate script and all three git
hooks broke for anyone contributing from Windows, which is why pnpm
check:all could not run there (reported in #1403). The terminal's shell
integration files under src-tauri/resources would check out as CRLF too.
.gitattributes now pins *.sh, *.bash, *.zsh and .githooks/* to eol=lf,
which overrides autocrlf per path. Everything else keeps git defaults.
scripts/shell-script-eol.test.mjs asks git check-attr about every tracked
shell script, found by extension and by shebang so the extensionless
hooks are covered, plus probe paths for scripts not yet written. It also
fails on a shell script whose committed blob already holds CRLF. Without
the new file it fails and names all 50 scripts; a deliberately staged
CRLF blob is caught.
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
core.autocrlf=truerewrites them to CRLF, and bash dies on the first real statement ($'\r': command not found,set: pipefail: invalid option name). This is whypnpm check:allcould not run on Windows, as reported in feat: add native read aloud integration #1403..gitattributesnow pins*.sh,*.bash,*.zshand.githooks/*toeol=lf, which overrides autocrlf per path. Everything else keeps git's defaults.Root cause
The repo had no
.gitattributes, so line endings on checkout were decided by each machine's git config. The files that break are the 45*.shscripts (including everybash scripts/*.shgate), the three extensionless hooks in.githooks/, and the terminal's shell-integration filessrc-tauri/resources/shell-integration/vmark.{bash,zsh}. The index already holds LF for all of them, so no file content changes.Reproduced locally by converting
scripts/lint-console.shto CRLF and running it with bash, which failed with the two errors above.What changed
.gitattributes: the foureol=lfrules, with the mechanism written next to them.scripts/shell-script-eol.test.mjs(gates tier, runs incheck:static):git check-attrabout every tracked shell script, found by extension and by shebang, so the extensionless hooks count.Validation
.gitattributes, 2 of the 4 tests fail and the message names all 50 unpinned scripts.git update-index --cacheinfofails the committed-CRLF test.scripts/check-scripts-parity.test.mjspasses, so the new test belongs to exactly one tier.pnpm check:predelta: 44 of 44 gates pass, exit 0.pnpm check:all: exit 0.Not covered
rustcheck will be red until therustlsadvisory fix (RUSTSEC-2026-0285) lands in its own PR. The failure is onmainand unrelated to this change.Type of Change