// Ставит в .git/hooks/pre-commit диспетчер зонных хуков. Идемпотентен: свой (по маркеру) // перезаписывает свежей версией, чужой не трогает. Зовётся из npm prepare — то есть // каждый npm install/ci в frontend/ ставит защиту сам, отдельного шага у сессии нет. 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'; // Диспетчер зонно-нейтрален: каждая зона может положить свой фрагмент в // <зона>/scripts/githooks/pre-commit, и он подхватится без правки этого файла. const dispatcher = `#!/bin/sh # ${MARKER} v1 — сгенерирован frontend/scripts/githooks/install.mjs; правки перетираются. 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: не git-репозиторий — установка хука пропущена'); process.exit(0); } let hooksPath = ''; try { hooksPath = git('config core.hooksPath'); } catch { // не задан — стандартное расположение, путь ниже } if (hooksPath !== '') { console.log(`githooks: задан core.hooksPath=${hooksPath} — ставить туда не берусь.`); console.log('Подключите frontend/scripts/githooks/pre-commit из своего pre-commit вручную.'); 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} уже существует и написан не нами — не перетираю.`); console.log('Подключите frontend/scripts/githooks/pre-commit из своего pre-commit вручную.'); process.exit(0); } mkdirSync(hooksDir, { recursive: true }); writeFileSync(target, dispatcher); chmodSync(target, 0o755); console.log(`githooks: pre-commit диспетчер установлен → ${target}`);