🔒 Repository is read-only – file editing is disabled.

PaganLinux/tmp-probe-firmware.py main

116 linii Raw ← Powrót
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())