# -*- coding: utf-8 -*- """ Regressionsschutz: Rendert alle Richtlinien in einer Framework-Sicht und vergleicht das Ergebnis mit einem Git-Stand. Erwartung fuer TISAX: 0 Abweichungen. python3 _render_diff.py [--framework TISAX|ISO|BEIDE] Beispiele: python3 _render_diff.py a9649b3 # TISAX-Sicht gegen den Stand vor dem ISO-Umbau python3 _render_diff.py dev --framework ISO # ISO-Sicht gegen dev Verglichen wird der gerenderte Text ohne Leerzeilen und ohne Kommentar-Anker — also das, was ein Mandant tatsaechlich zu sehen bekommt. """ import difflib, glob, json, os, re, subprocess, sys BASE = os.path.dirname(os.path.abspath(__file__)) REPO = subprocess.run(["git", "rev-parse", "--show-toplevel"], cwd=BASE, capture_output=True, text=True).stdout.strip() if len(sys.argv) < 2: print(__doc__); sys.exit(2) REV = sys.argv[1] FW = "TISAX" if "--framework" in sys.argv: FW = sys.argv[sys.argv.index("--framework") + 1].upper() schema = json.load(open(os.path.join(BASE, "variables.schema.json"), encoding="utf-8")) def ctx(): c = {k: (True if k.startswith("FLAG_") else "{%s}" % k) for k in schema["properties"]} for k in ["FLAG_OT_USED", "FLAG_DEV_INHOUSE", "FLAG_CRYPTO_PKI", "FLAG_CUSTOMER_SYSTEMS"]: c[k] = False c["FLAG_FW_TISAX"] = FW in ("TISAX", "BEIDE") c["FLAG_FW_ISO27001"] = FW in ("ISO", "BEIDE") return c def render(txt, c): pat = re.compile(r"\{\{#if (\w+)\}\}((?:(?!\{\{#if )(?!\{\{/if\}\}).)*?)\{\{/if\}\}", re.S) prev = None while prev != txt: prev = txt txt = pat.sub(lambda m: (m.group(2) if c.get(m.group(1)) else ""), txt) txt = re.sub(r"", "", txt, flags=re.S) txt = re.sub(r"\{\{LINK:([^}]+)\}\}", r"[\1]", txt) txt = re.sub(r"\{\{(\w+)\}\}", lambda m: str(c.get(m.group(1), "?")), txt) return [l.rstrip() for l in txt.split("\n") if l.strip()] def at_rev(relpath): r = subprocess.run(["git", "show", "%s:%s" % (REV, relpath)], cwd=REPO, capture_output=True, text=True) return r.stdout if r.returncode == 0 else None c = ctx() drift, missing, checked = 0, 0, 0 for path in sorted(glob.glob(os.path.join(BASE, "richtlinien", "*.md"))): rel = os.path.relpath(path, REPO) old_raw = at_rev(rel) if old_raw is None: missing += 1 print(" neu in dieser Fassung:", os.path.basename(path)) continue checked += 1 old, new = render(old_raw, c), render(open(path, encoding="utf-8").read(), c) if old != new: drift += 1 print("ABWEICHUNG:", os.path.basename(path)) for line in list(difflib.unified_diff(old, new, lineterm="", n=0))[:10]: print(" ", line[:140]) print() print("Sicht: %s · Vergleichsstand: %s" % (FW, REV)) print("geprueft: %d Richtlinien, neu: %d, abweichend: %d" % (checked, missing, drift)) print("OK" if drift == 0 else "PRUEFEN") sys.exit(0 if drift == 0 else 1)