import os
import re
import sys
import tempfile
PATCH_SEG_RE = re.compile(r'^\[patch\.(?:"(?P<url>[^"]+)"|(?P<bare>[^\]]+))\]')
ENTRY_RE = re.compile(r'^\s*(?P<name>[A-Za-z0-9_.\-]+)\s*=\s*\{(?P<body>[^}]*)\}')
GIT_RE = re.compile(r'\bgit\s*=\s*"(?P<url>[^"]+)"')
SSH_DECL_RE = re.compile(r'^[ \t]*[^#]*ssh://')
GIT_LINE_RE = re.compile(r'\bgit\s*=')
def scheme_of(url):
m = re.match(r'^([A-Za-z][A-Za-z0-9+.\-]*)://', url)
return m.group(1).lower() if m else None
def strip_query(url):
"""⇒ 剥离 `?...`(`#…` 不在本形内)后之 URL —— cargo 源身份之【实判据面】。
★ v1.7.4 裁决 01 §二.2: `ref`(`?tag=`/`?rev=`/`?branch=`)**不参与**源身份比较
⇒ 二 URL 之【同源】判定 = 剥离 query 后**逐字同形**。
"""
return url.split('?', 1)[0]
def same_source(key_url, entry_url):
"""⇒ 二 URL 是否【同源】(= 剥离 query 后逐字同形)—— cargo 之实判据。"""
return strip_query(key_url) == strip_query(entry_url)
def parse_sections(text):
"""⇒ [(段名, 键url 或 None, [条目名…], [(条目名, 条目url)…]), …]"""
segs = []
cur = None
for line in text.splitlines():
m = PATCH_SEG_RE.match(line)
if m:
cur = {'seg': line.strip(), 'key': m.group('url'), 'names': [], 'entries': []}
segs.append(cur)
continue
if line.startswith('['):
cur = None
continue
if cur is None or line.lstrip().startswith('#'):
continue
e = ENTRY_RE.match(line)
if not e:
continue
g = GIT_RE.search(e.group('body'))
if not g:
continue
cur['names'].append(e.group('name'))
cur['entries'].append((e.group('name'), g.group('url')))
return segs
def flip_violations(text):
"""守① 禁同源 ⇒ [(段名, 条目名, 条目url), …]
★★ v1.7.4 裁决 01 §二.2【谓词收紧】: 「同 `scheme`」⇒「剥离 `?...` 后逐字同形」。
旧谓词系【代理】—— `https://git@…` 形**同 scheme 而实异源**(cargo `rc=0` 实证)
⇒ 代理【假阳】; 新谓词**即 cargo 之实判据**, 系**收紧**兼去假阳。
★ 具名注册表键(如 `[patch.crates-io]`, 无 scheme)非本守之面 ⇒ 跳过。
"""
out = []
for s in parse_sections(text):
kurl = s['key']
if not kurl or scheme_of(kurl) is None:
continue
for name, url in s['entries']:
if same_source(kurl, url):
out.append((s['seg'], name, url))
return out
def ssh_decl_count(text):
return sum(1 for ln in text.splitlines() if SSH_DECL_RE.match(ln))
def lock_ssh_count(text):
return sum(1 for ln in text.splitlines() if 'git+ssh://' in ln)
LOCK_GIT_SRC_RE = re.compile(r'^\s*source = "git\+')
URL_TOKEN_RE = re.compile(r'://')
def lock_git_source_count(text):
"""锁面【`git+` 源行】数(分母)—— 守③ 非空前提。"""
return sum(1 for ln in text.splitlines() if LOCK_GIT_SRC_RE.match(ln))
def manifest_url_token_count(text):
"""声明面【非注释行含 scheme 记号 `://`】数(分母)—— 守③ 非空前提(承裁决 24① 剔注释口径)。"""
return sum(1 for ln in text.splitlines()
if not ln.lstrip().startswith('#') and URL_TOKEN_RE.search(ln))
TERMINAL_BASELINE_SEG = 0
def rebirth_state(manifest_text, lock_text):
"""守② 禁重生 ⇒ (前件已达?, 段数, 终态基线, 增量, 违规数)
★★ 谓词形【增量形】(承 ar 裁决 36 · `docs/V1.6.7_RULINGS_16.md`):
增量 = 现段数 − 【终态基线】; 判据 = 前件 ∧ 增量 > 0。
★ 禁【绝对形】(段数 > 0 而不设前件)—— 于【态 A】段数 = 16 ⇒ 绝对形【恒红】= 假红,
而其红【非缺陷之征】。
★★ 前件(v1.7.4 裁决 01 §二.3【修正】)= 【终态已达成】, 谓词 = **`[patch]` 段数 = 0**
(= 真终态之**定义**)。旧前件「`ssh` 字面量二面归零」**已废** ——
据: 段之真职为【覆写传递钉】(版本收敛), 去段即图碎裂 ⇒ 「`ssh` 归零」**不蕴含**「段已无职」
⇒ 旧前件于 `AC2` 之后**恒真** ⇒ 必假红(实测: `pre=yes ∧ 段数=19` ⇒ 增量 `19`)。
前件未达 ⇒ 本守【不适用(前件未达)】—— ★ 禁书【非绿】(裁决 36 原文)。
★★ ★ 射程之【照实】(免读者误读为「已守」): 段数【随版本漂】⇒ 以实跑 `__FACE__` 读数为准
(`v1.8.0` 本刻 = `17`; 旧文本此处硬写 `19` 系 `v1.7.4` 之值, 随 `v1.7.5` 之 N1 逐段清偿降至 `17`
—— 硬写之值必腐, 故改为【指路】形)。⇒ 本仓本刻**前件未达** ⇒ 本守**不适用**。
且【增量恒 `0`】(前件达 ⟺ 段数 = 0 ⇒ 增量 = 0 − 0)⇒ **无阳性对照可接** ⇒
承裁定 241「恒真之谓词不承证力」⇒ **本守本刻不承证力**, 照实载明。
⇒ `AC2` 之后之防护网 = **守①**(已收紧至 cargo 实判据)∧ **守③**(新增 · `ssh` 零容忍)。
★★ v1.8.0 `M0`(承审计 `F1`): 前件未达时出口码由 `0`(与绿同码)改 **`3`**(= 不适用)——
旧形下「前件未达(不适用)」与「判据成立(绿)」**同码** ⇒ 以 `rc == 0` 判绿之调用方
拿到的是**永久性假绿**。今以第三码显名区分(`0` 绿 / `1` 违规 / `2` 载体异常 / `3` 不适用)。
"""
p = patch_seg_count(manifest_text)
pre = (p == 0)
base = TERMINAL_BASELINE_SEG
delta = p - base
return pre, p, base, delta, (delta if (pre and delta > 0) else 0)
def ssh_zero_violations(manifest_text, lock_text):
"""守③ `ssh` 零容忍(v1.7.4 裁决 01 §二.4 · 新增)⇒ (声明面数, 锁面数, 违规数)
谓词: 声明面 `ssh://` 字面量(**非注释行** · 承裁决 24① 口径)> 0
∨ 锁面 `git+ssh` > 0 ⇒ 违规。
★ 面之显名: 本守之面 = **主线 manifest**(`Cargo.toml`)+ **`Cargo.lock`**;
插件侧 manifest 之 `ssh` 字面量**不在**本守面内(其归 守① 之插件侧面)。
★ 由(补强之据): 二守修正后 `ssh` 回归若无专守即漏网 —— 守① 只管【同源】,
不管【`ssh` 是否回来】⇒ 本守补之。
"""
s = ssh_decl_count(manifest_text)
l = lock_ssh_count(lock_text)
return s, l, (1 if (s > 0 or l > 0) else 0)
def face_sets(text):
"""⇒ (声明面集, patch 面集) —— 二者皆取【git 项/条目】之名(单位 = 名)。
面: 同一 manifest 之二段 —— 声明面 = `[workspace.dependencies]` ∧ patch 面 = `[patch.*]`。
★ 二面【同轴可比】之据: 皆以 `git =` 声明同一批仓; 然【非同一对象】——
声明面定【主钉】, patch 面定【覆写】⇒ 仅一面有名者 = 【单面项】。
"""
decl, patch = set(), set()
mode = None
for ln in text.splitlines():
if ln.startswith('[workspace.dependencies]'):
mode = 'd'
continue
if ln.startswith('[patch.'):
mode = 'p'
continue
if ln.startswith('['):
mode = None
continue
if mode is None or ln.lstrip().startswith('#'):
continue
if not GIT_LINE_RE.search(ln):
continue
m = re.match(r'^\s*([A-Za-z0-9_.\-]+)\s*=', ln)
if m:
(decl if mode == 'd' else patch).add(m.group(1))
return decl, patch
def lock_git_pkg_names(text):
"""`Cargo.lock` 中【`git+` 源】包之【名集】(块法 · 与 `lock_stats` 同器)。
★ v1.8.0 `M0`(承审计 `A4.3`/`F1` · ar 择 (b)): 供 `check24` 之【第三集】——
唯传递钉 = 锁面 git 包名 − 声明面名 − patch 面名(= **二面皆无**者)。
"""
names = set()
for b in re.findall(r'^\[\[(?:package|patch\.unused)\]\]\n(.*?)(?=^\[\[|\Z)', text, re.M | re.S):
if re.search(r'^source = "git\+', b, re.M):
m = re.search(r'^name = "([^"]+)"', b, re.M)
if m:
names.add(m.group(1))
return names
def lock_stats(text):
"""⇒ dict —— `Cargo.lock` 之三读数(承 ar 令: AC1 判据须三读数并报)。
域 = `[[package]]` 段(★ 先切 `[[patch.unused]]` —— 该块系在册已知条件且【非】`[[package]]`,
不切则 `git+ssh://` 行数法 `35` ≠ 逐块法 `34`, 差 `1` 即此块)。
单位 = 包实例 / 名。
· pkgs = `[[package]]` 实例数
· git_pkgs = 其中 `source` 以 `git+` 起首者(本项目自有 + 传递 git 源, 二者【同域】)
· same_name_multi = 【git 源同名多实例】(= `test` 所订【无双实例】之域; 基线 = `0`)
· revtag_dual = 【同 commit 之 `rev`/`tag` 二形 DUAL】(承裁决 33 扩载)
"""
body = text.partition('[[patch.unused]]')[0]
names = {}
by_commit = {}
total = 0
for b in body.split('[[package]]')[1:]:
n = re.search(r'^name = "([^"]+)"', b, re.M)
s = re.search(r'^source = "([^"]+)"', b, re.M)
if not n:
continue
total += 1
src = s.group(1) if s else ''
if not src.startswith('git+'):
continue
names.setdefault(n.group(1), []).append(src)
m = re.match(r'git\+([^?]+)\?(rev|tag)=([^#]+)#(.+)$', src)
if m:
by_commit.setdefault(m.group(4), {}).setdefault(m.group(2), set()).add(
f"{n.group(1)}@{m.group(3)}")
dual = {c: v for c, v in by_commit.items() if 'rev' in v and 'tag' in v}
return {
'pkgs': total,
'git_pkgs': sum(len(v) for v in names.values()),
'same_name_multi': sum(1 for v in names.values() if len(v) > 1),
'commits': len(by_commit),
'revtag_dual': len(dual),
'dual_detail': dual,
}
def patch_seg_count(text):
return sum(1 for ln in text.splitlines() if ln.startswith('[patch.'))
def entry_line_count(text):
"""段内【原始】`git =` 行数(计数谓词)—— 与解析所得条目数(解析谓词)对表,
二者之差即【盲区】(在册族: 计数谓词 vs 解析谓词之差即盲区 ⇒ 报「全部」须附分母)。"""
n, inp = 0, False
for ln in text.splitlines():
if ln.startswith('[patch.'):
inp = True
continue
if ln.startswith('['):
inp = False
continue
if inp and not ln.lstrip().startswith('#') and GIT_LINE_RE.search(ln):
n += 1
return n
def _reg_set(raw):
"""名册参 ⇒ 名集(`,` 分隔 · 剥空白 · 弃空项)。★ 空串 ⇒ 空集(**非**错误)。"""
return {t.strip() for t in raw.split(',') if t.strip()}
def align_check(manifest_text, lock_text, decl_reg, patch_reg, trans_reg):
"""⇒ `(rc, lines)` —— `检查24` 之三集【名册 ⇄ 实面】比较(承 `ar` 裁决 04 · 裁甲取丙)。
★ 立条之由(`v1.9.2` 三环批复核 `test` 捕一 · 已裁): 比较逻辑原在 `verify_release.sh`
之内联段 ⇒ 载体 `selftest` **结构性不可达** ⇒ 「全量红侧 `PASS`」**不承**该面之证力。
移入载体 ⇒ 夹具级(秒级)覆盖 ⇒ 零门禁跑。
射程(照实): 唯【比较】; 面之解析仍由 `face_sets` / `lock_git_pkg_names` /
`patch_seg_count` 承(**非**本函数自造等价形)。
★ 三集(承 `v1.6.7` 裁决 20 ∧ `v1.8.0 M0` 择 (b)):
· 集一 `decl_only` = 仅声明面项(有 `[workspace.dependencies]` ∧ 无 `[patch.*]`)
· 集二 `patch_only` = 仅 `patch` 面项
· 集三 `trans_only` = 唯传递钉(二面皆无 · 锁面 `git+` 包名 − 二面名)
★★ `seg == 0`(终态之形 · `[patch]` 段数 = 0): 依在册判例(裁决 20 · 反向守归 `检查23`
守②)⇒ 集一/集二之比较**对象消解** ⇒ 本函数**唯判集三**(与 `verify_release.sh`
原内联段之早退**逐义同**)。★ 此系【语义搬运】非【语义变更】。
出口码阶梯(承在册「出口码阶梯禁以未判掩红」· 语义序 `FAIL > GAP > 绿`):
`0` = 应判之集**皆合**(绿)
`1` = 有**失对齐**(`FAIL`)
`2` = **前提不成立 / 载体异常**(`GAP` · 未判)
★ 二码不得互掩: 前提不成立 ⇒ 无从判 `FAIL` ⇒ 唯出 `2`; 一旦可判 ⇒ `FAIL` **优先于**绿。
★ 并载【低序计数】(本形: 失对齐集数与名数)—— 免以单码掩其量。
"""
lines = []
if manifest_text is None or lock_text is None:
lines.append("__VERDICT__ decl_only=GAP patch_only=GAP trans_only=GAP")
lines.append("__ALIGN_RC__ 2")
lines.append("__NOTE__ 前提不成立(manifest / lock 不可读)⇒ 三集【未判】")
return 2, lines
decl, patch = face_sets(manifest_text)
segs = patch_seg_count(manifest_text)
lock = lock_git_pkg_names(lock_text)
d_now, p_now, t_now = decl - patch, patch - decl, lock - decl - patch
lines.append(f"__FACE__ decl={len(decl)} patch={len(patch)} both={len(decl & patch)} "
f"decl_only={len(d_now)} patch_only={len(p_now)} patch_seg={segs}")
lines.append("__DECL_ONLY__" + ",".join(sorted(d_now)))
lines.append("__PATCH_ONLY__" + ",".join(sorted(p_now)))
lines.append("__TRANSITIVE__ lock_git={} decl={} patch={} trans_only={}".format(
len(lock), len(decl), len(patch), len(t_now)))
lines.append("__TRANS_ONLY__" + ",".join(sorted(t_now)))
d_reg, p_reg, t_reg = _reg_set(decl_reg), _reg_set(patch_reg), _reg_set(trans_reg)
lines.append("__REG__ decl=[{}] patch=[{}] trans=[{}]".format(
",".join(sorted(d_reg)), ",".join(sorted(p_reg)), ",".join(sorted(t_reg))))
checks = [("trans_only", t_now, t_reg)]
if segs > 0:
checks = [("decl_only", d_now, d_reg), ("patch_only", p_now, p_reg)] + checks
bad = []
for name, now, reg in checks:
hit = now == reg
lines.append("__VERDICT__ {}={}".format(name, "OK" if hit else "MISMATCH"))
if not hit:
bad.append((name, now, reg))
if segs == 0:
lines.append("__VERDICT__ decl_only=SKIP patch_only=SKIP")
lines.append("__NOTE__ 终态之形(patch 段数 = 0)⇒ 集一/集二 对象消解(承裁决 20 · 反向守归 检查23 守②)")
if bad:
for name, now, reg in bad:
lines.append("__NOTE__ 失对齐 {}: 现 [{}] ⇄ 册 [{}]".format(
name, ",".join(sorted(now)), ",".join(sorted(reg))))
lines.append("__ALIGN_MISMATCH_FACES__ {}".format(len(bad)))
lines.append("__ALIGN_RC__ 1")
return 1, lines
lines.append("__ALIGN_MISMATCH_FACES__ 0")
lines.append("__ALIGN_RC__ 0")
return 0, lines
def coverage(text):
"""⇒ (解析条目数, 原始条目行数);二者不等 ⇒ 谓词有盲区, 不得以零命中充绿。"""
parsed = sum(len(s['entries']) for s in parse_sections(text))
return parsed, entry_line_count(text)
_FIX_OK = '''\
[patch."https://gitcode.com/kemeng1/xwkernel.git"]
kernel = { git = "ssh://git@gitcode.com/kemeng1/xwkernel.git", tag = "v1.4.8" }
kernel-host = { git = "ssh://git@gitcode.com/kemeng1/xwkernel.git", tag = "v1.4.8" }
'''
_FIX_FLIPPED = '''\
[patch."https://gitcode.com/kemeng1/xwkernel.git"]
kernel = { git = "https://gitcode.com/kemeng1/xwkernel.git", tag = "v1.4.8" }
'''
_FIX_MIXED = '''\
[patch."https://gitcode.com/kemeng1/xwkernel.git"]
kernel = { git = "ssh://git@gitcode.com/kemeng1/xwkernel.git", tag = "v1.4.8" }
[patch.crates-io]
foo = { git = "https://example.com/foo.git", tag = "v1" }
'''
_FIX_TRANSITION = '''\
ssh://git@gitcode.com/kemeng1/xwcore.git
ssh://git@gitcode.com/kemeng1/xwtools.git
[patch."https://gitcode.com/kemeng1/xwcore.git"]
xwcore = { git = "ssh://git@gitcode.com/kemeng1/xwcore.git", tag = "v0.1.29" }
'''
_FIX_TERMINAL = '''\
https://gitcode.com/kemeng1/xwcore.git
[patch."https://gitcode.com/kemeng1/xwcore.git"]
'''
_FIX_TERMINAL_LOCK = '''\
version = 4
[[package]]
name = "xwcore"
version = "0.1.29"
source = "git+https://gitcode.com/kemeng1/xwcore.git?tag=v0.1.29#790082df"
'''
_FIX_TRAILING = '''\
[patch."https://gitcode.com/kemeng1/xwtui.git"]
xwtui = { git = "ssh://git@gitcode.com/kemeng1/xwtui.git", tag = "v0.3.15" } # deref ec22f7faa80f353e7d233bf92862dc97f1e164bd
xwbad = { git = "https://gitcode.com/kemeng1/xwtui.git", tag = "v0.3.15" } # deref x
'''
_FIX_V174 = '''\
[patch."https://gitcode.com/kemeng1/xwtui.git"]
xwtui = { git = "https://git@gitcode.com/kemeng1/xwtui.git", tag = "v0.3.19" } # deref 119444601d463df220ee868c75d1766cde51afaf
'''
_FIX_SEGS_NONTERMINAL = '''\
[patch."https://gitcode.com/kemeng1/xwcore.git"]
xwcore = { git = "https://git@gitcode.com/kemeng1/xwcore.git", tag = "v0.1.31" }
'''
_FIX_LOCK_SSH = '''\
version = 4
[[package]]
name = "xwcore"
version = "0.1.31"
source = "git+ssh://git@gitcode.com/kemeng1/xwcore.git?tag=v0.1.31#ed2dcfad"
'''
_FIX_LOCK_HTTPS = '''\
version = 4
[[package]]
name = "xwcore"
version = "0.1.31"
source = "git+https://git@gitcode.com/kemeng1/xwcore.git?tag=v0.1.31#ed2dcfad"
'''
_FIX_ALIGN_MANIFEST = '''\
[workspace.dependencies]
d1 = { git = "https://gitcode.com/kemeng1/d1.git", tag = "v1" }
d2 = { git = "https://gitcode.com/kemeng1/d2.git", tag = "v1" }
[patch."https://gitcode.com/kemeng1/d1.git"]
d1 = { git = "https://git@gitcode.com/kemeng1/d1.git", tag = "v1" }
[patch."https://gitcode.com/kemeng1/p1.git"]
p1 = { git = "https://git@gitcode.com/kemeng1/p1.git", tag = "v1" }
'''
_FIX_ALIGN_LOCK = '''\
[[package]]
name = "d1"
version = "0.1.0"
source = "git+https://git@gitcode.com/kemeng1/d1.git?tag=v1#aaa"
[[package]]
name = "d2"
version = "0.1.0"
source = "git+https://git@gitcode.com/kemeng1/d2.git?tag=v1#bbb"
[[package]]
name = "p1"
version = "0.1.0"
source = "git+https://git@gitcode.com/kemeng1/p1.git?tag=v1#ccc"
[[package]]
name = "t1"
version = "0.1.0"
source = "git+https://git@gitcode.com/kemeng1/t1.git?tag=v1#ddd"
'''
def selftest():
ok = True
def chk(label, got, want):
nonlocal ok
good = got == want
print(f" [{'✓' if good else '✗'}] {label}: got={got} want={want}")
if not good:
ok = False
print("夹具一 阴性对照(ssh 条目形: https 键 + ssh 条目 ⇒ 异源)")
chk("守①违规数", len(flip_violations(_FIX_OK)), 0)
chk("段数", patch_seg_count(_FIX_OK), 1)
chk("条目数", sum(len(s['entries']) for s in parse_sections(_FIX_OK)), 2)
print("夹具二 ★阳性对照(真同源形: 键与条目 URL 逐字同形)")
chk("守①违规数", len(flip_violations(_FIX_FLIPPED)), 1)
v = flip_violations(_FIX_FLIPPED)
chk("违规条目名", v[0][1] if v else None, "kernel")
chk("违规条目 url", v[0][2] if v else None, "https://gitcode.com/kemeng1/xwkernel.git")
print("夹具三 混合形(具名注册表键不涉本守)")
chk("守①违规数", len(flip_violations(_FIX_MIXED)), 0)
chk("段数", patch_seg_count(_FIX_MIXED), 2)
print("夹具四 守② 前件未达(段数 > 0 ⇒ 不适用)—— ★ 承裁决 01 §二.3")
pre4, segs4, _b4, _d4, vio4 = rebirth_state(_FIX_SEGS_NONTERMINAL, _FIX_LOCK_HTTPS)
chk("前件(段数 = 0)?", pre4, False)
chk("段数", segs4, 1)
chk("守②违规数(不适用 ⇒ 0 · 禁书「非绿」)", vio4, 0)
chk("ssh 声明行(本形)", ssh_decl_count(_FIX_SEGS_NONTERMINAL), 0)
chk("锁面 ssh 行(本形)", lock_ssh_count(_FIX_LOCK_HTTPS), 0)
print("夹具五 阴性对照(守② 真终态形: 段数 = 0 ⇒ 前件达 ∧ 增量 0 ⇒ 无违规)")
pre5, segs5, base5, delta5, vio5 = rebirth_state("https://gitcode.com/kemeng1/xwcore.git\n", _FIX_LOCK_HTTPS)
chk("前件(段数 = 0)?", pre5, True)
chk("段数", segs5, 0)
chk("终态基线", base5, 0)
chk("增量(= 段数 − 基线)", delta5, 0)
chk("守②违规数", vio5, 0)
print("夹具六 ★照实(守② 无阳性对照可接 —— 前件达 ⇒ 增量恒 0 ⇒ 恒不触发; 承裁定 241)")
chk("前件达之形之违规数(恒 0)", rebirth_state("", _FIX_LOCK_HTTPS)[4], 0)
chk("前件达?", rebirth_state("", _FIX_LOCK_HTTPS)[0], True)
print("夹具七 ★阳性对照(行尾注释条目须入覆盖面 ∧ 其同源须被捕)")
chk("解析条目数", coverage(_FIX_TRAILING)[0], 2)
chk("原始条目行数", coverage(_FIX_TRAILING)[1], 2)
chk("覆盖面无盲区", coverage(_FIX_TRAILING)[0] == coverage(_FIX_TRAILING)[1], True)
chk("守①违规数(唯 xwbad 同源)", len(flip_violations(_FIX_TRAILING)), 1)
print("夹具八 ★阳性对照(覆盖面盲区须可捕)")
blind_fix = '''\
[patch."https://gitcode.com/kemeng1/x.git"]
x = { git = "ssh://git@gitcode.com/kemeng1/x.git" }
'''
chk("无盲区之面", coverage(blind_fix)[0] == coverage(blind_fix)[1], True)
print("夹具九 ★★阳性对照(v1.7.4 本批实态形: https 键 + `https://git@` 条目 ⇒ 异源 ⇒ 零命中)")
chk("守①违规数(旧谓词于此形假阳 ⇒ 新谓词须 0)", len(flip_violations(_FIX_V174)), 0)
chk("段数", patch_seg_count(_FIX_V174), 1)
chk("条目数", sum(len(s['entries']) for s in parse_sections(_FIX_V174)), 1)
chk("同源判定(键 vs 条目)", same_source("https://gitcode.com/kemeng1/xwtui.git",
"https://git@gitcode.com/kemeng1/xwtui.git"), False)
chk("同源判定(剥离 query 后仍同形 ⇒ True)", same_source("https://gitcode.com/a.git?tag=v1",
"https://gitcode.com/a.git?tag=v2"), True)
print("夹具十 ★阳性对照(守③: 锁面 `git+ssh` > 0 ⇒ 违规)")
chk("守③违规数(锁面 ssh 态)", ssh_zero_violations(_FIX_V174, _FIX_LOCK_SSH)[2], 1)
chk("守③声明面数(本形 0)", ssh_zero_violations(_FIX_V174, _FIX_LOCK_SSH)[0], 0)
chk("守③锁面数(本形 1)", ssh_zero_violations(_FIX_V174, _FIX_LOCK_SSH)[1], 1)
print("夹具十一 阴性对照(守③: 二面皆零 ⇒ 无违规)")
chk("守③违规数(本批实态形)", ssh_zero_violations(_FIX_V174, _FIX_LOCK_HTTPS)[2], 0)
print("夹具十二 ★阳性对照(守③: 声明面 `ssh://` 非注释行 > 0 ⇒ 违规)")
chk("守③违规数(声明面 ssh 态)", ssh_zero_violations(_FIX_OK, _FIX_LOCK_HTTPS)[2], 1)
chk("守③声明面数(本形 2)", ssh_zero_violations(_FIX_OK, _FIX_LOCK_HTTPS)[0], 2)
print("夹具十三 ★★阳性对照 + 阴性对照(v1.8.0 `M0` 守② 出口码: 前件未达 ⇒ `rc=3` ≠ 绿 `rc=0`)")
with tempfile.TemporaryDirectory() as _td:
_mp, _lp = os.path.join(_td, 'Cargo.toml'), os.path.join(_td, 'Cargo.lock')
with open(_mp, 'w', encoding='utf-8') as _f:
_f.write(_FIX_SEGS_NONTERMINAL)
with open(_lp, 'w', encoding='utf-8') as _f:
_f.write(_FIX_LOCK_HTTPS)
chk("守② rc(前件未达 ⇒ 不适用)", main(['ac1_patch_guard.py', 'rebirth', _mp, _lp]), 3)
with tempfile.TemporaryDirectory() as _td:
_mp, _lp = os.path.join(_td, 'Cargo.toml'), os.path.join(_td, 'Cargo.lock')
with open(_mp, 'w', encoding='utf-8') as _f:
_f.write("https://gitcode.com/kemeng1/xwcore.git\n")
with open(_lp, 'w', encoding='utf-8') as _f:
_f.write(_FIX_LOCK_HTTPS)
chk("守② rc(前件已达 ⇒ 绿)", main(['ac1_patch_guard.py', 'rebirth', _mp, _lp]), 0)
print("夹具十四 ★★阳性对照 + 阴性对照(v1.8.0 `M0` 守③ 空面 ⇒ `rc=2`; 非空面 ⇒ `rc=0`)")
with tempfile.TemporaryDirectory() as _td:
_mp, _lp = os.path.join(_td, 'Cargo.toml'), os.path.join(_td, 'Cargo.lock')
open(_mp, 'w', encoding='utf-8').close()
open(_lp, 'w', encoding='utf-8').close()
chk("守③ rc(空面 ⇒ 不可读作绿)", main(['ac1_patch_guard.py', 'sshzero', _mp, _lp]), 2)
with tempfile.TemporaryDirectory() as _td:
_mp, _lp = os.path.join(_td, 'Cargo.toml'), os.path.join(_td, 'Cargo.lock')
with open(_mp, 'w', encoding='utf-8') as _f:
_f.write(_FIX_V174)
with open(_lp, 'w', encoding='utf-8') as _f:
_f.write(_FIX_LOCK_HTTPS)
chk("守③ rc(非空面 ∧ 二面零 ⇒ 绿)", main(['ac1_patch_guard.py', 'sshzero', _mp, _lp]), 0)
chk("守③ 分母(非空面: 声明面记号数 > 0)", manifest_url_token_count(_FIX_V174) > 0, True)
chk("守③ 分母(非空面: 锁面 git 源行数 > 0)", lock_git_source_count(_FIX_LOCK_HTTPS) > 0, True)
print("夹具十五 ★★阳性对照 + 阴性对照 + 判别力 + GAP(v1.9.2 裁甲取丙: 检查24 三集比较入载体)")
_mf, _lf = _FIX_ALIGN_MANIFEST, _FIX_ALIGN_LOCK
chk("甲 rc(三集皆合 ⇒ 绿)", align_check(_mf, _lf, "d2", "p1", "t1")[0], 0)
chk("甲 实面: 仅声明面", ",".join(sorted(face_sets(_mf)[0] - face_sets(_mf)[1])), "d2")
chk("甲 实面: 仅 patch 面", ",".join(sorted(face_sets(_mf)[1] - face_sets(_mf)[0])), "p1")
chk("甲 实面: 唯传递钉", ",".join(sorted(lock_git_pkg_names(_lf) - set(face_sets(_mf)[0])
- set(face_sets(_mf)[1]))), "t1")
chk("乙 rc(唯传递钉名册缺 ⇒ 失对齐)", align_check(_mf, _lf, "d2", "p1", "")[0], 1)
_rc_c, _ln_c = align_check(_mf, _lf, "d2", "p9", "t1")
chk("丙 rc(名异数同 ⇒ 仍失对齐)", _rc_c, 1)
chk("丙 判别力(计数谓词于此形相等 ⇒ 故计数不承证力)",
len(face_sets(_mf)[1] - face_sets(_mf)[0]) == len({"p9"}), True)
chk("丙 名面之差可显", any("失对齐 patch_only" in x for x in _ln_c), True)
chk("丁 rc(manifest 不可读 ⇒ GAP)", align_check(None, _lf, "d2", "p1", "t1")[0], 2)
chk("丁 rc(lock 不可读 ⇒ GAP)", align_check(_mf, None, "d2", "p1", "t1")[0], 2)
_term = '[workspace.dependencies]\nd1 = { git = "https://gitcode.com/kemeng1/d1.git", tag = "v1" }\n'
_rc_e, _ln_e = align_check(_term, _lf, "", "", "d2,p1,t1")
chk("戊 rc(终态之形 · 集三合 ⇒ 绿)", _rc_e, 0)
chk("戊 集一/集二 显名 SKIP", any("decl_only=SKIP" in x for x in _ln_e), True)
chk("戊 rc(终态之形 · 集三缺 p1 ⇒ 仍失对齐)", align_check(_term, _lf, "", "", "d2,t1")[0], 1)
chk("己 汇总行锚行首(末段取值)",
[x.split()[-1] for x in align_check(_mf, _lf, "d2", "p9", "t1")[1]
if x.startswith("__ALIGN_MISMATCH_FACES__")][-1], "1")
print(f"selftest {'全符 ✓' if ok else '★ 不符 ⇒ 谓词不承证力'}")
return 0 if ok else 2
def main(argv):
if len(argv) < 2:
print(__doc__ or "usage: ac1_patch_guard.py {flip|rebirth|face|selftest} …", file=sys.stderr)
return 2
cmd = argv[1]
if cmd == 'selftest':
return selftest()
if cmd == 'flip':
if len(argv) < 3:
print("flip 须给至少一个 manifest", file=sys.stderr)
return 2
total = 0
blind = 0
for path in argv[2:]:
try:
text = open(path, encoding='utf-8', errors='replace').read()
except OSError as e:
print(f"__UNREACHABLE__ {path} {e}", file=sys.stderr)
return 2
parsed, raw = coverage(text)
print(f"__COVER__ {path} parsed={parsed} raw={raw}")
if parsed != raw:
print(f"__BLIND__ {path} 解析条目 {parsed} ≠ 原始条目行 {raw} ⇒ 谓词有盲区, "
f"本刻之零命中【不可读作绿】", file=sys.stderr)
blind += 1
for seg, name, url in flip_violations(text):
print(f"{path}: 同源 {seg} 条目 {name} url={url}")
total += 1
print(f"__FLIP_COUNT__{total}")
if blind:
return 2
return 1 if total else 0
if cmd == 'sshzero':
if len(argv) < 4:
print("sshzero 须给 <manifest> <lockfile>", file=sys.stderr)
return 2
try:
mtxt = open(argv[2], encoding='utf-8', errors='replace').read()
ltxt = open(argv[3], encoding='utf-8', errors='replace').read()
except OSError as e:
print(f"__UNREACHABLE__ {e}", file=sys.stderr)
return 2
s, l, vio = ssh_zero_violations(mtxt, ltxt)
dm, dl = manifest_url_token_count(mtxt), lock_git_source_count(ltxt)
print(f"__SSHZERO__ decl={s} lock={l} denom_manifest={dm} denom_lock={dl} face={argv[2]}")
print(f"__SSHZERO_COUNT__{vio}")
if dm == 0 and dl == 0:
print("__SSHZERO_EMPTY__ 空面: 声明面无 scheme 记号 ∧ 锁面无 `git+` 源行 ⇒ "
"本刻零命中【不可读作绿】(无分母之零不承证力)", file=sys.stderr)
return 2
return 1 if vio else 0
if cmd == 'rebirth':
if len(argv) < 4:
print("rebirth 须给 <manifest> <lockfile>", file=sys.stderr)
return 2
try:
mtxt = open(argv[2], encoding='utf-8', errors='replace').read()
ltxt = open(argv[3], encoding='utf-8', errors='replace').read()
except OSError as e:
print(f"__UNREACHABLE__ {e}", file=sys.stderr)
return 2
s, l, p = ssh_decl_count(mtxt), lock_ssh_count(ltxt), patch_seg_count(mtxt)
pre, segs, base, delta, vio = rebirth_state(mtxt, ltxt)
print(f"__FACE__ ssh_decl={s} lock_ssh={l} patch_seg={segs} baseline={base} delta={delta} "
f"pre={'yes' if pre else 'no'}")
print(f"__REBIRTH_COUNT__{vio}")
if not pre:
print(f"__REBIRTH_NA__ 前件未达([patch] 段数 = {segs} ≠ 终态基线 {base})⇒ 本守"
f"【不适用(前件未达)】⇒ rc=3(★ 与绿 rc=0 相区别 · 承审计 F1)", file=sys.stderr)
return 3
return 1 if vio else 0
if cmd == 'face':
if len(argv) < 3:
print("face 须给 manifest", file=sys.stderr)
return 2
text = open(argv[2], encoding='utf-8', errors='replace').read()
segs = parse_sections(text)
parsed, raw = coverage(text)
print(f"__FACE__ seg={len(segs)} entries={sum(len(s['entries']) for s in segs)} "
f"raw_entry_lines={raw} ssh_decl={ssh_decl_count(text)}")
if parsed != raw:
print(f"__BLIND__ 解析条目 {parsed} ≠ 原始条目行 {raw} ⇒ 谓词有盲区", file=sys.stderr)
return 2
return 0
if cmd == 'sshfaces':
if len(argv) < 3:
print("sshfaces 须给至少一个 manifest", file=sys.stderr)
return 2
ta = td = 0
for path in argv[2:]:
try:
text = open(path, encoding='utf-8', errors='replace').read()
except OSError:
continue
a = sum(1 for ln in text.splitlines() if 'ssh://' in ln)
d = ssh_decl_count(text)
ta += a
td += d
if a or d:
print(f" {path}: 含注释={a} 非注释={d}")
print(f"__SSHFACES__ all={ta} decl={td} diff={ta - td}")
return 0
if cmd == 'lockstats':
if len(argv) < 3:
print("lockstats 须给 lockfile", file=sys.stderr)
return 2
text = open(argv[2], encoding='utf-8', errors='replace').read()
st = lock_stats(text)
print(f"__LOCK__ pkgs={st['pkgs']} git_pkgs={st['git_pkgs']} "
f"same_name_multi={st['same_name_multi']} commits={st['commits']} "
f"revtag_dual={st['revtag_dual']}")
for c, v in sorted(st['dual_detail'].items()):
print(f" DUAL commit={c[:12]} rev={sorted(v['rev'])} tag={sorted(v['tag'])}")
return 0
if cmd == 'align':
if len(argv) < 3:
print("align 须给 manifest", file=sys.stderr)
return 2
text = open(argv[2], encoding='utf-8', errors='replace').read()
decl, patch = face_sets(text)
segs = patch_seg_count(text)
print(f"__FACE__ decl={len(decl)} patch={len(patch)} both={len(decl & patch)} "
f"decl_only={len(decl - patch)} patch_only={len(patch - decl)} patch_seg={segs}")
print("__DECL_ONLY__" + ",".join(sorted(decl - patch)))
print("__PATCH_ONLY__" + ",".join(sorted(patch - decl)))
return 0
if cmd == 'transitive':
if len(argv) < 4:
print("transitive 须给 <manifest> <lockfile>", file=sys.stderr)
return 2
try:
mtext = open(argv[2], encoding='utf-8', errors='replace').read()
ltext = open(argv[3], encoding='utf-8', errors='replace').read()
except OSError as e:
print(f"__UNREACHABLE__ {e}", file=sys.stderr)
return 2
decl, patch = face_sets(mtext)
lock = lock_git_pkg_names(ltext)
trans = sorted(lock - decl - patch)
print(f"__TRANSITIVE__ lock_git={len(lock)} decl={len(decl)} patch={len(patch)} "
f"trans_only={len(trans)}")
print("__TRANS_ONLY__" + ",".join(trans))
return 0
if cmd == 'align-check':
if len(argv) < 7:
print("align-check 须给 <manifest> <lockfile> <decl_reg> <patch_reg> <trans_reg>",
file=sys.stderr)
return 2
try:
mtext = open(argv[2], encoding='utf-8', errors='replace').read()
ltext = open(argv[3], encoding='utf-8', errors='replace').read()
except OSError as e:
print(f"__UNREACHABLE__ {e}", file=sys.stderr)
mtext = ltext = None
rc, lines = align_check(mtext, ltext, argv[4], argv[5], argv[6])
for ln in lines:
print(ln)
return rc
print(f"未知子命令: {cmd}", file=sys.stderr)
return 2
if __name__ == '__main__':
sys.exit(main(sys.argv))