Skip to content

Git Hook Compliance flags every hook as non-executable on Windows #15

Description

@ruleofcodedev

Git Hook Compliance reports Non-executable hooks found: … for every hook on
Windows
, on repositories whose hooks work. It also names files that are not hooks.

Found while verifying the v7.17.5 worktree fix end to end against the published
package, on a project set up with ruleofcode init --quick.

The check

src/checkers/git-laws/git-hook-compliance.ts:

const stats = FileUtils.getFileStats(hookPath);
if (stats && !(stats.mode & parseInt('111', 8))) {
  nonExecutableHooks.push(hookFile);
}

Why it always fires on Windows

NTFS carries no POSIX execute bit. Node reports the same mode for every file:

pre-commit    mode=666   exec bits=NO
husky.sh      mode=666   exec bits=NO
.gitignore    mode=666   exec bits=NO
h             mode=666   exec bits=NO
platform: win32

mode & 0o111 is therefore always 0, so the violation is unconditional. And git for
Windows does not need the bit — it runs hooks through sh. The law is asserting a
property that gates nothing on that platform, and calling its absence a violation.

It also flags files that are not hooks

The candidate list is "every file in the hooks directory that does not end in
.sample". In husky's generated _ directory that includes .gitignore, husky.sh
and h — support files. Complaining that .gitignore is not executable is wrong on
every platform, Linux included.

Observed violation, identical in a primary checkout and a linked worktree:

Non-executable hooks found: .gitignore, applypatch-msg, commit-msg, h, husky.sh,
post-applypatch, post-checkout, post-commit, post-merge, post-rewrite,
pre-applypatch, pre-auto-gc, pre-commit, pre-merge-commit, pre-push, pre-rebase,
prepare-commit-msg

Reproduction

git init && npm install --save-dev ruleofcode
npx ruleofcode init --quick          # installs husky, sets core.hooksPath=.husky/_
npx ruleofcode audit --mode=full     # on Windows

Direction

Two separate defects, and the second is not Windows-specific:

  1. Only assert the execute bit where it means something — skip the check on win32,
    or read git's own view (ls-files --stage, mode 100755) rather than the
    filesystem's.
  2. Judge hook files, not every file in the directory: match git's known hook names
    instead of "everything without a .sample suffix".

Whichever way it lands, the law must not report a violation a consumer cannot act on:
chmod +x cannot be satisfied on NTFS, so the current suggestion asks for the
impossible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions