๐ฟ headcheck v1.0.2 ยท MIT
Verify the HEAD file of dumb-HTTP git repos is still cloneable โ read-only, from the outside, zero dependencies.
The problem
On a dumb-HTTP git server, the post-update hook (git update-server-info) regenerates info/refs but does not protect the bare repo's HEAD file. A broken HEAD (raw SHA instead of a symref, branch deleted, HEAD lost) makes git clone fail with empty repository even though info/refs answers 200 and the landing pages look fine. headcheck catches it before your users do.
What it does
- Discovery โ repos are listed from your index page (
--base), or checked individually via repeatable--repo. - Three checks per repo โ HEAD is a valid
ref: refs/heads/<branch>symref; the branch file holds a 40-hex SHA; that SHA is actually listed ininfo/refs. - Honest HTTP semantics โ a transient network failure is a warning, never "broken" (the classic false-positive trap of
curl | grep -q). - Output โ plain text,
--json, or--quietverdict-only; per-request--timeout. - Zero dependencies, Python โฅ 3.9, single module. Optional
[certs]extra pullscertififor macOS venvs without a system trust store (also used automatically when importable).
Install (pip)
pip install headcheck @ git+https://mandrilly.com/git/headcheck.git # macOS venv without system CA bundle: pip install "headcheck[certs] @ git+https://mandrilly.com/git/headcheck.git"
Usage
headcheck --base https://example.com/git # discover repos from the index headcheck --base https://example.com/git --repo mytool headcheck --base ... --json # machine-readable report headcheck --base ... --quiet # verdict line only
Sample output:
[OK ] pdfgen: HEAD -> main @ da08cab [FAIL] broken-repo: HEAD is not a valid symref (content: 'a1b2c3...') headcheck FAIL: 1/24 repos broken
Exit codes
| Code | Meaning |
|---|---|
0 | all checked repos HEAD-valid and resolvable |
1 | at least one repo broken (clone would fail) |
2 | error (index unreachable, no repos found) |
Cron pattern
headcheck --base https://example.com/git --quiet \ || echo "headcheck exit $?" | mail -s "git HEAD broken" ops@example.com
Tests
Self-contained unittest suite serving a fixture dumb-HTTP layout over a local HTTP server:
python -m unittest test_headcheck # 6 tests