fix(laws): read the hook executable bit from the git index - #17
Merged
Conversation
Git Hook Compliance called every hook of every Windows project non-executable, and the consumer could not act on it. NTFS carries no POSIX execute bit: `fs.stat().mode` is 0o666 for every file there and `chmod` is a no-op, so `chmod +x` — the suggestion the law printed — changes nothing. It also judged files git never runs: husky keeps `.gitignore`, `husky.sh` and `h` in its hooks directory. The bit now comes from the git index (`100755` / `100644`), which answers the same question identically on every platform and only for files a consumer can commit a mode for. Untracked hooks are not judged at all: husky ignores its generated `_` directory wholesale, so no mode exists there for git or anyone else to set. The law was right about the defect underneath, and keeping that was the harder half. The committed layout is `.husky/<hook>`, not the resolved hooks directory, so the check reads both — otherwise removing the false positive would have removed the true one with it. Our own hooks were committed at 100644 and are fixed here; a Linux clone would not have executed them. Reported by a Windows consumer whose build it blocked, having stayed on the previous version. Proven red and green, on this repository and on a real git fixture.
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.
Closes #15. Reported independently by a Windows consumer who stayed on 7.17.4 because this blocks their build.
The false positive
Git Hook Compliance called every hook of every Windows project non-executable — and the consumer could not act on it. Measured, not assumed:
NTFS has no POSIX execute bit, so
chmod +x— the suggestion the law printed — changes nothing. It also judged files git never runs: husky keeps.gitignore,husky.shandhin its hooks directory.The true positive, kept
The law was right about the defect underneath: hooks committed at
100644are not executable when the repo is cloned on Linux. Keeping that was the harder half.The committed layout is
.husky/<hook>, not the resolved hooks directory (.git/hooks, or husky's untracked_). Reading only the resolved directory would have removed the false positive and the true one — my first version scored 100/100 against hooks that were genuinely 100644. The check now reads both.Our own hooks were committed at 100644. Fixed in this PR — the law was right about us.
Evidence
Proven red and green on this repository:
Plus five regression tests on a real git fixture with committed hooks and an untracked husky
_directory.Verdict impact
Changes verdicts: the unactionable Windows violation disappears; committed-but-non-executable hooks are still reported, with an actionable message (
git update-index --chmod=+x). Three newdetectionLimitsentries declare what is now not checked — untracked hooks carry no mode to judge.Gate
npm run lint— 0 errorsnpx jest— 505 suites / 13871 tests, exit 0npm run canary— green (py100 / ng136 / node78)node dist/cli.js audit— exit 0