🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
#!/usr/bin/env python3
"""Porownuje SEMANTYKE (yaml.safe_load) wersji HEAD i roboczej kazdej zmienionej receptury.
Wypisuje dla kazdego pliku:
- klucze, ktore realnie zmienily wartosc
- informacje, czy roznica jest wylacznie formatowaniem (te same dane, inny zapis)
"""
import subprocess
import sys
import yaml
R = "/var/lib/pagan-sync/recipes"
def sh(*args):
return subprocess.run(args, cwd=R, capture_output=True, text=True)
def load(text):
return yaml.safe_load(text)
def main():
st = sh("git", "status", "--porcelain")
files = []
for line in st.stdout.splitlines():
if not line.strip():
continue
code, path = line[:2], line[3:].strip()
if code.strip() == "??":
continue
if not path.endswith(".yaml"):
continue
files.append(path)
print(f"plikow do sprawdzenia: {len(files)}\n")
bad = []
only_fmt = []
real = []
for path in files:
try:
head_text = sh("git", "show", f"HEAD:{path}").stdout
except Exception as e:
print(f"!! {path}: nie moge czytac HEAD ({e})")
continue
try:
work_text = open(f"{R}/{path}", encoding="utf-8").read()
except Exception as e:
print(f"!! {path}: nie moge czytac pliku ({e})")
continue
try:
a = load(head_text)
b = load(work_text)
except Exception as e:
print(f"!! {path}: YAML nie parsuje sie: {e}")
bad.append(path)
continue
if a == b:
only_fmt.append(path)
continue
if not isinstance(a, dict) or not isinstance(b, dict):
print(f"%% {path}: zmiana typu danych ({type(a).__name__} -> {type(b).__name__})")
real.append((path, ["<typ>"]))
continue
keys = sorted(set(a) | set(b))
diff_keys = []
for k in keys:
va, vb = a.get(k, "<brak>"), b.get(k, "<brak>")
if va != vb:
diff_keys.append(k)
real.append((path, diff_keys))
print(f"## {path}")
for k in diff_keys:
va, vb = a.get(k, "<brak>"), b.get(k, "<brak>")
ra, rb = repr(va), repr(vb)
if len(ra) > 160:
ra = ra[:160] + f"...[len={len(str(va))}]"
if len(rb) > 160:
rb = rb[:160] + f"...[len={len(str(vb))}]"
print(f" {k}:\n HEAD: {ra}\n WORK: {rb}")
print()
print("=" * 70)
print(f"semantycznie identyczne (tylko formatowanie): {len(only_fmt)}")
for p in only_fmt:
print(f" ~ {p}")
print(f"z realna zmiana tresci: {len(real)}")
for p, ks in real:
print(f" * {p}: {', '.join(ks)}")
if bad:
print(f"NIEPARSOWALNE: {len(bad)}")
for p in bad:
print(f" ! {p}")
if __name__ == "__main__":
sys.exit(main())