// Puts the dispatcher of the zone hooks into .git/hooks/pre-commit. Idempotent: its own one (by the // marker) it overwrites with a fresh version, somebody else's it does not touch. Called from // npm prepare — that is, every npm install/ci in frontend/ puts the protection in place itself, and // a session has no separate step for it. import { execSync } from 'node:child_process'; import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { resolve } from 'node:path'; const MARKER = 'textmachine zone-hook dispatcher'; // The dispatcher is zone-neutral: every zone may put its own fragment into // /scripts/githooks/pre-commit, and it is picked up with no edit to this file. const dispatcher = `#!/bin/sh # ${MARKER} v1 — generated by frontend/scripts/githooks/install.mjs; edits are overwritten. status=0 for hook in */scripts/githooks/pre-commit; do [ -x "$hook" ] || continue "$hook" || status=1 done exit $status `; /** @param {string} args */ function git(args) { return execSync(`git ${args}`, { encoding: 'utf8' }).trim(); } let gitDir; try { gitDir = git('rev-parse --git-common-dir'); } catch { console.log('githooks: not a git repository — installing the hook was skipped'); process.exit(0); } let hooksPath = ''; try { hooksPath = git('config core.hooksPath'); } catch { // not set — the standard location, the path is below } if (hooksPath !== '') { console.log(`githooks: core.hooksPath=${hooksPath} is set — I will not install into it.`); console.log('Wire frontend/scripts/githooks/pre-commit into your own pre-commit by hand.'); process.exit(0); } const hooksDir = resolve(process.cwd(), gitDir, 'hooks'); const target = resolve(hooksDir, 'pre-commit'); if (existsSync(target) && !readFileSync(target, 'utf8').includes(MARKER)) { console.log(`githooks: ${target} already exists and was written not by us — not overwriting.`); console.log('Wire frontend/scripts/githooks/pre-commit into your own pre-commit by hand.'); process.exit(0); } mkdirSync(hooksDir, { recursive: true }); writeFileSync(target, dispatcher); chmodSync(target, 0o755); console.log(`githooks: the pre-commit dispatcher is installed → ${target}`);