97 lines
4.4 KiB
Bash
Executable File
97 lines
4.4 KiB
Bash
Executable File
#!/bin/bash
|
||
# spec, разделы [C-7] No-shortcut на apply_*, [C-8] Mandatory SC trace block,
|
||
# [C-10] Mandatory deviation tracker
|
||
#
|
||
# Установка: создать симлинк из этого файла в .git/hooks/pre-commit:
|
||
# ln -sf "$(pwd)/scripts/pre-commit.sh" .git/hooks/pre-commit
|
||
# (либо запустить scripts/install-hooks.sh)
|
||
#
|
||
# Этот hook применяется ТОЛЬКО на коммиты в crates/, не на role/spec правки.
|
||
|
||
set -e
|
||
|
||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||
cd "$REPO_ROOT"
|
||
|
||
CHANGED=$(git diff --cached --name-only --diff-filter=ACM)
|
||
CONSENSUS_CHANGED=$(echo "$CHANGED" | grep -E 'crates/(mt-(state|account|entry|consensus|lottery|timechain)|montana-node)/.*\.rs$' || true)
|
||
|
||
# Gate 1 [C-8] SC trace block — проверяется в commit-msg hook (он получает
|
||
# commit message file как $1; pre-commit запускается ДО записи message
|
||
# и не имеет доступа к нему). См. scripts/commit-msg.sh.
|
||
|
||
# Gate 2 [C-10]: SPEC DEVIATION в коде требует DEV-N reference
|
||
BAD_DEV=$(git diff --cached -- 'crates/**/*.rs' 2>/dev/null | grep "^+.*SPEC DEVIATION" | grep -v "DEV-[0-9]" || true)
|
||
if [ -n "$BAD_DEV" ]; then
|
||
echo "ОТКАЗ [C-10]: SPEC DEVIATION без DEV-N reference"
|
||
echo "$BAD_DEV"
|
||
echo
|
||
echo "Каждое // SPEC DEVIATION: ОБЯЗАНО ссылаться на конкретный DEV-NNN entry в docs/SPEC_DEVIATIONS.md"
|
||
exit 1
|
||
fi
|
||
|
||
# Gate 3 [C-10]: deviation count в коде vs SPEC_DEVIATIONS.md
|
||
if [ -f docs/SPEC_DEVIATIONS.md ]; then
|
||
CODE_DEVS=$(grep -rcE "SPEC DEVIATION DEV-[0-9]+" crates/ 2>/dev/null | grep -v ":0$" | awk -F: '{s+=$2} END {print s+0}')
|
||
DOC_DEVS=$(grep -c "^## DEV-" docs/SPEC_DEVIATIONS.md 2>/dev/null || echo 0)
|
||
if [ "$CODE_DEVS" -gt "$DOC_DEVS" ]; then
|
||
echo "ОТКАЗ [C-10]: $CODE_DEVS SPEC DEVIATION в коде, $DOC_DEVS entries в docs/SPEC_DEVIATIONS.md"
|
||
echo "Каждый DEV-NNN в коде должен иметь entry в SPEC_DEVIATIONS.md"
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Gate 4 [C-7]: запрет прямого mut на consensus state в node/example crates.
|
||
# Контекст ±3 строки: cargo fmt может переместить `// SPEC DEVIATION DEV-N`
|
||
# comment на отдельную строку (struct literal multi-line) — hook должен видеть
|
||
# deviation marker в окрестности, не только на той же строке.
|
||
# Gate 4 scope: production binary code только. cargo example bins
|
||
# (crates/*/examples/*.rs) — shakedown demos, не consensus path.
|
||
BAD_MUT=$(git diff --cached -U3 -- 'crates/montana-node/**/*.rs' ':!crates/*/examples/*.rs' 2>/dev/null \
|
||
| awk '
|
||
/^\+/ && /\.(insert|remove)\(/ && /(accounts|nodes|candidates|account_table|node_table|candidate_pool)/ {
|
||
lines[NR] = $0
|
||
target_line[NR] = 1
|
||
}
|
||
/SPEC DEVIATION DEV-/ {
|
||
dev_line[NR] = 1
|
||
}
|
||
END {
|
||
for (n in target_line) {
|
||
has_dev = 0
|
||
for (k = n - 3; k <= n + 3; k++) {
|
||
if (dev_line[k]) { has_dev = 1; break }
|
||
}
|
||
if (!has_dev) print lines[n]
|
||
}
|
||
}
|
||
' \
|
||
|| true)
|
||
if [ -n "$BAD_MUT" ]; then
|
||
echo "ОТКАЗ [C-7]: прямой mut-доступ к consensus state таблице вне apply_* функции"
|
||
echo "$BAD_MUT"
|
||
echo
|
||
echo "Прямой insert/remove на AccountTable/NodeTable/CandidatePool разрешён только внутри apply_* функций соответствующего crate"
|
||
echo "Если deviation legitimate — добавьте // SPEC DEVIATION DEV-NNN с обоснованием в docs/SPEC_DEVIATIONS.md в пределах ±3 строк от insert/remove"
|
||
exit 1
|
||
fi
|
||
|
||
# Gate 5: четыре обязательные команды (workspace level)
|
||
# Этот gate тяжёлый — запускается только если consensus-critical изменены
|
||
if [ -n "$CONSENSUS_CHANGED" ]; then
|
||
echo "Pre-commit: проверка fmt..."
|
||
cargo fmt --all -- --check >/dev/null 2>&1 || {
|
||
echo "ОТКАЗ: cargo fmt --all -- --check не прошёл"
|
||
cargo fmt --all -- --check
|
||
exit 1
|
||
}
|
||
echo "Pre-commit: проверка clippy..."
|
||
cargo clippy --all-targets -- -D warnings >/dev/null 2>&1 || {
|
||
echo "ОТКАЗ: cargo clippy не прошёл"
|
||
cargo clippy --all-targets -- -D warnings 2>&1 | tail -30
|
||
exit 1
|
||
}
|
||
fi
|
||
|
||
echo "Pre-commit: все проверки пройдены"
|