Skip to main content

Module dispatch

Module dispatch 

Source
Expand description

The two dispatchers.

They are NOT the same shape, and both shapes are load-bearing:

  • pre-commit runs its checks CONCURRENTLY and reports EVERY failure. Serial would be a visible slowdown on each commit; stopping at the first failure would hide the rest, so you’d fix one lint error, commit, and immediately meet the next.
  • pre-push runs them SERIALLY and stops at the FIRST failure, naming just that check. The steps are ordered and expensive (protected branch, then branch name, then rebase, then the whole test suite) and there is no point running tests after a rebase conflict.

Resist the tempting shared run_all helper — collapsing these is the obvious way to silently lose the distinction. tests/dispatchers.rs pins both.

Checks are FUNCTIONS in this binary, called directly. They used to be files: .git/hooks/pre-commit-*, each an identical sh shim whose only job was to re-exec this same binary and tell it its own name. One commit therefore cost 27 processes — a shim, the binary, then 13 more shims and 13 more binaries — to do work the binary already had in a table.

Deleting that removed the filename glob (order was lexicographic, so a rename could silently reorder a gate), the shebang emulation Windows needed because it cannot execute a #! script, and the spawn plumbing under both. Order is now a declared list in registry.

Functions§

enter_all_files_mode
Point every check at git ls-files instead of the index.
pre_commit
pre_push
run_all
amont run — every applicable check, on demand.
run_named
amont run <check> — one check by name. None when there is no such check, which the caller turns into a usage error.