🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
#!/usr/bin/env python3
"""Sonda wykonalnosci naprawy firmware bez tarballa.
Dla kazdej receptury *-firmware:
- parsuje lokalny WHENCE (ktore pliki trafiaja do pakietu),
- wyciaga z OPUBLIKOWANEJ paczki .pag liste plikow + sha256,
- porownuje z tym, co daloby sie pobrac pojedynczo z GitLaba (raw).
Raport: ile receptur da sie przestawic na pojedyncze pliki bez zmiany zawartosci.
"""
import collections
import hashlib
import os
import re
import subprocess
import sys
import tempfile
R = "/var/lib/pagan-sync/recipes"
REPO = "/var/www/repo.paganlinux.eu/stable"
REV = "20260622"
RAW = "https://gitlab.com/kernel-firmware/linux-firmware/-/raw/%s/" % REV
# rodzaje wpisow w WHENCE
KIND = re.compile(r"^(File|Source|Link|Raw|Version|Licence|Info|Driver|File:|Source:|Link:)\b", re.I)
def wh_find_local():
out = []
for dp, _d, fs in os.walk(R):
if ".git" in dp:
continue
if "PAGBUILD.yaml" in fs:
try:
import yaml
d = yaml.safe_load(open(os.path.join(dp, "PAGBUILD.yaml"), newline="", encoding="utf-8")) or {}
except Exception:
continue
n = str(d.get("pkgname", ""))
if n.endswith("-firmware") and "linux-firmware" in str(d.get("source")):
w = os.path.join(dp, "WHENCE")
out.append((os.path.relpath(dp, R), n, str(d.get("pkgver")), w if os.path.isfile(w) else None))
return sorted(out)
def parse_whence(path):
"""Zwraca liste wpisow: dict(kind, value). Prosty parser: linie 'Klucz: wartosc'."""
entries = []
cur = None
for line in open(path, encoding="utf-8", errors="replace"):
s = line.rstrip("\n")
m = re.match(r"^(File|Source|Link|Raw|Version|Info|Licence|Driver):\s*(.*)$", s)
if m:
k, v = m.group(1), m.group(2).strip()
if k == "File":
cur = {"file": v, "source": None, "link": None, "raw": None}
entries.append(cur)
elif cur is not None and k in ("Source", "Link", "Raw"):
cur[k.lower()] = v
return entries
def pag_files(name, ver):
"""Zwraca {sciezka: sha256} z opublikowanej paczki (o ile jest)."""
f = os.path.join(REPO, f"{name}-{ver}-1.pag")
if not os.path.isfile(f):
alt = [x for x in os.listdir(REPO) if x.startswith(f"{name}-{ver}-") and x.endswith(".pag")]
if not alt:
return None
f = os.path.join(REPO, sorted(alt)[-1])
tmp = tempfile.mkdtemp(prefix="pag-")
r = subprocess.run(["tar", "-xf", f, "-C", tmp], capture_output=True, text=True)
dt = os.path.join(tmp, "data.tar.xz")
if r.returncode != 0 or not os.path.isfile(dt):
return None
subprocess.run(["tar", "-xJf", dt, "-C", tmp], capture_output=True)
sums = {}
for dp, _d, fs in os.walk(tmp):
for x in fs:
p = os.path.join(dp, x)
rel = os.path.relpath(p, tmp)
if rel.startswith("metadata.json") or rel == "sums.json":
continue
h = hashlib.sha256()
with open(p, "rb") as fh:
for c in iter(lambda: fh.read(1 << 20), b""):
h.update(c)
sums[rel] = h.hexdigest()
return sums
def main():
recipes = wh_find_local()
print(f"receptur *-firmware korzystajacych z linux-firmware: {len(recipes)}")
kinds = collections.Counter()
no_whence = 0
for rel, name, ver, w in recipes:
if not w:
no_whence += 1
continue
for e in parse_whence(w):
for k in ("file", "source", "link", "raw"):
if e.get(k):
kinds[k] += 1
print(f"bez pliku WHENCE: {no_whence}")
print("wystapienia pol w WHENCE:", dict(kinds))
print()
print("przyklady (pierwsze 8):")
for rel, name, ver, w in recipes[:8]:
es = parse_whence(w) if w else []
print(f" {name} [{ver}] wpisow={len(es)}")
for e in es[:3]:
print(" ", e)
if __name__ == "__main__":
sys.exit(main())