#!/usr/bin/env bash
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="${1:-$(cd "$HERE/../.." && pwd)}"
cd "$ROOT" || { echo "仓根不可达: $ROOT" >&2; exit 1; }
PASS=0
FAIL=0
ok() { printf ' ✓ %s\n' "$1"; PASS=$((PASS + 1)); }
no() { printf ' ✗ %s\n' "$1"; FAIL=$((FAIL + 1)); }
command -v cargo >/dev/null 2>&1 || { echo "缺 cargo" >&2; exit 1; }
cargo deny --help >/dev/null 2>&1 || { echo "缺 cargo-deny" >&2; exit 1; }
export CARGO_TERM_COLOR=never
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
echo "== AC6 腿 · 面 = $ROOT =="
echo "-- G1 cargo deny check(advisories ∧ bans ∧ licenses ∧ sources)"
DENY_OUT="$TMP/deny_all.txt"
cargo deny check >"$DENY_OUT" 2>&1
RC=$?
TAIL="$(tail -1 "$DENY_OUT")"
if grep -q $'\x1b' "$DENY_OUT"; then
no "G0 ★ 捕获面含 ANSI 转义 ⇒ 纯文本谓词将假红(色面未归一 · 禁静默)"
else
ok "G0 捕获面无 ANSI 转义(谓词与实形同形)"
fi
if [ "$RC" -eq 0 ] && printf '%s' "$TAIL" | grep -q 'advisories ok, bans ok, licenses ok, sources ok'; then
ok "G1 rc=0 ∧ 四类皆 ok(${TAIL})"
else
no "G1 rc=$RC ∧ 末行 = ${TAIL}"
fi
echo "-- G2 licenses 零僵尸(allow ⊆ cargo deny list 实见许可名集)"
cargo deny list >"$TMP/deny_list.txt" 2>/dev/null
G2_OUT="$(python3 - "$TMP/deny_list.txt" <<'PY'
import re, sys
names = set()
for ln in open(sys.argv[1], encoding='utf-8'):
m = re.match(r'^(.+?)\s*\(\d+\):', ln)
if m:
names.add(m.group(1).strip())
t = open('deny.toml', encoding='utf-8').read()
blk = re.search(r'^allow = \[(.*?)^\]', t, re.M | re.S).group(1)
allow = [s.strip() for s in re.findall(r'"([^"]+)"', blk)]
missing = [a for a in allow if a not in names]
print(f'{len(allow)} {len(names)} {len(missing)} {",".join(missing)}')
PY
)"
read -r N_ALLOW N_USED N_MISSING MISSING <<<"$G2_OUT"
if [ "$N_ALLOW" -gt 0 ] && [ "$N_MISSING" -eq 0 ]; then
ok "G2 allow=$N_ALLOW ⊆ 实见名集=$N_USED ∧ 僵尸=$N_MISSING(零僵尸)"
else
no "G2 allow=$N_ALLOW ⇄ 实见名集=$N_USED ∧ 僵尸=$N_MISSING($MISSING)"
fi
# ── 绿侧 G3: sources 【集合】谓词(`allow-git` ⊆ `Cargo.lock` git 仓键集)──────
# ★★ v1.8.0 `M0`(承审计 `F-2`): 旧谓词系【计数对表】(`N_ALLOWGIT == N_LOCKGIT`)——
# 计数相等【不承】成员相等之证 ⇒ 成员错而计数仍等则报绿(且旧报文并书「差集空」,
# 而全函数无差集计算)。今改【集合】谓词: 判 `allow ⊆ lock`(零未用),
# 并【报】`lock \ allow`(该侧即 `unknown-git = "deny"` 所实际强制者)。
# ★ 键之【归一形】(本席阳性对照实证 · `cargo-deny 0.20.2`): 仅 scheme 变
# (`ssh://git@…` ⇄ `https://git@…`)⇒ `cargo deny check sources` `rc=0`; 而改 host /
# 改 path ⇒ `rc=8` `source-not-allowed` ⇒ 匹配键 = **host + path**,**scheme 不参与**。
# 故键 = 去 `git+` 前缀 ∧ 去 scheme ∧ 去 userinfo ∧ 去 `?`/`#` 查询 ∧ 去尾 `.git` ∧ 去尾 `/`。
# ★ 谓词书其正则原文(承在册: 报谓词须书正则,禁描述式名)。
g3_predicate() { # $1 = deny.toml 路径(默认 deny.toml)⇒ 5 行: 计数 ∧ 未用数 ∧ lock\allow 数 ∧ 二明细
python3 - "$1" <<'PY'
import re, sys
def key(u):
u = re.sub(r'^git\+', '', u)
u = re.sub(r'[?#].*$', '', u)
u = u.rstrip('/')
u = re.sub(r'\.git$', '', u)
m = re.match(r'^[A-Za-z][A-Za-z0-9+.\-]*://(?:[^@/]*@)?(.*)$', u)
return m.group(1) if m else u
t = open(sys.argv[1], encoding='utf-8').read()
m = re.search(r'^allow-git = \[(.*?)^\]', t, re.M | re.S)
allow = {key(s) for s in re.findall(r'"([^"]+)"', m.group(1))} if m else set()
lk = open('Cargo.lock', encoding='utf-8').read()
blocks = re.findall(r'^\[\[(?:package|patch\.unused)\]\]\n(.*?)(?=^\[\[|\Z)', lk, re.M | re.S)
lock = set()
for b in blocks:
mm = re.search(r'^source = "(git\+.*)"$', b, re.M)
if mm:
lock.add(key(mm.group(1)))
print(len(allow), len(lock), len(allow - lock), len(lock - allow))
print(','.join(sorted(allow - lock)) or '-')
print(','.join(sorted(lock - allow)) or '-')
PY
}
echo "-- G3 sources 集合谓词(allow-git ⊆ Cargo.lock git 仓键集 · 键 = host+path)"
G3_OUT="$(g3_predicate deny.toml)"
{ read -r N_A N_L N_UNUSED N_UNCOV; read -r UNUSED; read -r UNCOV; } <<<"$G3_OUT"
if [ "$N_A" -gt 0 ] && [ "$N_UNUSED" -eq 0 ]; then
ok "G3 allow($N_A) ⊆ lock($N_L) ⇒ 未用=$N_UNUSED(零未用)· lock\\allow=$N_UNCOV($UNCOV)"
else
no "G3 allow($N_A) ⊄ lock($N_L) ⇒ 未用=$N_UNUSED($UNUSED)"
fi
# ── 绿侧 G4: 收紧键在位(未用许可清零之硬门)────────────────────────────────
echo "-- G4 收紧键在位(unused-allowed-license = \"deny\")"
if grep -qE '^unused-allowed-license = "deny"' deny.toml; then
ok 'G4 unused-allowed-license = "deny" 在位'
else
no 'G4 unused-allowed-license = "deny" 缺席 ⇒ 清零无门'
fi
# ── 红侧 R1(阳性对照): 注入一条【未用】许可 ⇒ 硬门必咬 ──────────────────────
echo "-- R1 阳性对照: allow 注入未用之 \"AGPL-3.0\" ⇒ licenses 必红"
python3 - "$TMP/deny_red.toml" <<'PY'
import re, sys
t = open('deny.toml', encoding='utf-8').read()
t2, n = re.subn(r'(^allow = \[\n)', r'\1 "AGPL-3.0",\n', t, count=1, flags=re.M)
assert n == 1, 'inject failed'
open(sys.argv[1], 'w', encoding='utf-8').write(t2)
PY
RED_OUT="$TMP/deny_red_out.txt"
cargo deny --config "$TMP/deny_red.toml" check licenses >"$RED_OUT" 2>&1
RRC=$?
# ★★ 显名支(承裁19 §2 同律 · `test` 域修): 照实 —— 本腿**零** `timeout`(`cargo deny`
# 直调)⇒ `124` 支为**防御**(不可达)。真伪由 = 原 `else` 以任意 `rc≠0` 径判
# 「谓词不承证力」—— 器/环境之失(config 解析、取源失败)亦落此 ⇒ **伪由**。
if [ "$RRC" -eq 124 ]; then
no "R1 ★ 逾时被杀 rc=124(**本腿未判**)—— 承裁19 §2: 超时 ≠ 未咬合 · 禁混(候复跑)"
elif [ ! -s "$RED_OUT" ]; then
no "R1 ★ 器无输出 rc=$RRC(**未判**)—— 无从判咬合(显名 · 非判「未咬合」)"
elif [ "$RRC" -ne 0 ] && grep -q 'unmatched license allowance' "$RED_OUT"; then
ok "R1 咬合 rc=$RRC ∧ 命中 'unmatched license allowance'"
else
no "R1 未咬合 rc=$RRC ∧ 有输出 ∧ 未中(阳性对照失败 ⇒ 谓词不承证力)"
tail -3 "$RED_OUT" | sed 's/^/ /'
fi
# ── 红侧 R2(阳性对照 · 接入出口码): `allow` 一条 path 改错 ⇒ 集合谓词必咬 ────
# ★ 判别力之证(**专打旧计数谓词之盲**): 注入后**条数不变**(`allow` 仍 29 ∧ lock 仍 29)
# ⇒ 旧【计数】谓词报绿(= 盲); 新【集合】谓词 ⇒ `allow ⊄ lock`(未用 ≥ 1)⇒ 必红。
# 二者之差即本项之判别力(承在册: 阳性对照须接入出口码 ∧ 零命中可有独立因)。
# ★ 注入形【scheme 无关 ∧ org 无关】(`…/xwcore` ⇒ `…/xwcore-typo`)⇒ 对 `S1` 翻转前后同效。
# ★★ 订正(`v1.9.6` `M1` 源切批 · 2026-10-17): 原锚逐字钉 `kemeng1/xwcore"` ⇒ 源切(`kemeng1` ⇒
echo "-- R2 阳性对照: allow 一条 path 改错 ⇒ 集合谓词必咬(而条数不变 ⇒ 旧计数谓词不咬)"
python3 - "$TMP/deny_g3red.toml" <<'PY'
import re, sys
t = open('deny.toml', encoding='utf-8').read()
t2, n = re.subn(r'(/xwcore)"', r'\1-typo"', t, count=1)
assert n == 1, 'inject failed'
open(sys.argv[1], 'w', encoding='utf-8').write(t2)
PY
REDG3_OUT="$(g3_predicate "$TMP/deny_g3red.toml")"
{ read -r RA RL RU RC2; read -r _RU; read -r _RC; } <<<"$REDG3_OUT"
DENY_G3RC=0
cargo deny --config "$TMP/deny_g3red.toml" check sources >"$TMP/deny_g3red_out.txt" 2>&1 || DENY_G3RC=$?
if [ "$DENY_G3RC" -eq 124 ]; then
no "R2 ★ 逾时被杀 rc=124(**本腿未判**)—— 超时 ≠ 未咬合 · 禁混(候复跑)"
elif [ ! -s "$TMP/deny_g3red_out.txt" ]; then
no "R2 ★ 器无输出 rc=$DENY_G3RC(**未判**)—— 无从判咬合(显名 · 非判「未咬合」)"
elif [ "$RU" -ge 1 ] && [ "$RA" -eq "$RL" ] && [ "$DENY_G3RC" -ne 0 ]; then
ok "R2 咬合: 集合谓词 未用=$RU(必红)∧ 条数 $RA==$RL 不变(旧计数谓词报绿 = 盲)∧ 器 rc=$DENY_G3RC"
else
no "R2 未咬合: 未用=$RU ∧ 条数 $RA⇄$RL ∧ 器 rc=$DENY_G3RC(有输出 ∧ 未中 ⇒ 阳性对照失败)"
fi
echo "== 结果: PASS=$PASS FAIL=$FAIL =="
[ "$FAIL" -eq 0 ] || exit 1
exit 0