#!/usr/bin/env python # -*- coding: utf-8 -*- """产品根定位自检:造临时夹具验 `_common.find_product_root()` 的三态行为。 为什么要有它:目录口径换成「工作区根 / 项目 / 产品根{产品规划, 产品原型{designs, pages}}」之后, **认错产品根**会让产物落到别的产品目录下(事后极难拆干净)。 本脚本只造临时夹具、**绝不碰任何真实工作区**,跑完自动清理。 用法: python scripts/selftest_product_root.py 退出码:0 = 全过;1 = 有用例没过。 """ import importlib.util import io import os import shutil import sys import tempfile try: sys.stdout.reconfigure(encoding="utf-8", errors="replace") except Exception: pass SK = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) COMMON = os.path.join(SK, "references", "stage-delivery", "scripts", "_common.py") def load_common(): spec = importlib.util.spec_from_file_location("_sm_common", COMMON) mod = importlib.util.module_from_spec(spec) sys.modules["_sm_common"] = mod spec.loader.exec_module(mod) return mod def mkproot(p): """按新结构造一个产品根:产品规划/ + 产品原型/{designs,pages}/""" for d in ("产品规划", os.path.join("产品原型", "designs"), os.path.join("产品原型", "pages")): os.makedirs(os.path.join(p, d), exist_ok=True) def main(): C = load_common() fix = tempfile.mkdtemp(prefix="proot-selftest-") out = [] def build_single(): mkproot(os.path.join(fix, "ws1", "项目", "only")) def build_multi(pointer=""): for nm in ("a", "b"): mkproot(os.path.join(fix, "ws2", "项目", nm)) reg = os.path.join(fix, "ws2", ".registry") os.makedirs(reg, exist_ok=True) if pointer: io.open(os.path.join(reg, "current-project"), "w", encoding="utf-8").write(pointer) cases = [ ("单产品·给工作区根", build_single, os.path.join(fix, "ws1"), os.path.join(fix, "ws1", "项目", "only")), ("单产品·给产品根本身", build_single, os.path.join(fix, "ws1", "项目", "only"), os.path.join(fix, "ws1", "项目", "only")), ("单产品·从子目录向上认", build_single, os.path.join(fix, "ws1", "项目", "only", "产品原型", "pages"), os.path.join(fix, "ws1", "项目", "only")), ("多产品·无指针·不许猜", build_multi, os.path.join(fix, "ws2"), ""), ("多产品·有指针·认指针", lambda: build_multi("b"), os.path.join(fix, "ws2"), os.path.join(fix, "ws2", "项目", "b")), ] try: nfail = 0 for name, build, arg, expect in cases: shutil.rmtree(fix, ignore_errors=True) os.makedirs(fix, exist_ok=True) build() got = C.find_product_root(arg) ok = os.path.normcase(os.path.abspath(got)) == os.path.normcase(os.path.abspath(expect)) out.append("%s %-26s 期望=%s | 实得=%s" % ( "[过]" if ok else "[FAIL]", name, os.path.relpath(expect, fix) if expect else "(空)", os.path.relpath(got, fix) if got else "(空)")) if not ok: nfail += 1 finally: shutil.rmtree(fix, ignore_errors=True) for line in out: print(line) print() print("小计:%d / %d 过" % (len(cases) - nfail, len(cases))) print("✅ 产品根定位全过。" if not nfail else "⛔ 有用例没过 —— 先修定位再跑流水线。") return 0 if not nfail else 1 if __name__ == "__main__": sys.exit(main())