#!/usr/bin/env python3
"""Installer hardware-DB ↔ nixos-hardware drift check (flake check
`hardware-db-modules`).

Usage: check-hardware-db.py <hardware-db.sh> <nixos-hardware-modules.txt>

Every nixos-hardware module name the installer references — the third
`|`-field of each HARDWARE_DB table row, plus the literal `common-*`
modules the CPU/GPU/chassis autodetect emits — must exist in the pinned
`nixos-hardware.nixosModules`. A lock bump can rename a module upstream
(the X1 Carbon → `x1-Nth-gen` churn is the canonical example) and silently
break profiled installs on exactly the machines whose DMI matches — a
class of bug that never shows up in a VM. `nixos-hardware-modules.txt` is
generated at eval time in flake.nix from `attrNames
nixos-hardware.nixosModules`, so the "what actually exists" side can't go
stale by itself.
"""

import re
import sys

db_file, modules_file = sys.argv[1], sys.argv[2]

available = {l.strip() for l in open(modules_file) if l.strip()}
db = open(db_file).read()

referenced = {}  # module name -> short reason (first seen)

# HARDWARE_DB rows: "sys_vendor_regex | product_regex | module". The first
# two fields are bash regexes (may contain anything but a literal quote);
# the module name is a plain nixos-hardware attr (lower-case, dashes).
for vendor, product, module in re.findall(
    r'"([^"|]*)\|([^"|]*)\|([a-z0-9][a-z0-9-]*)"', db
):
    referenced.setdefault(module, f"HARDWARE_DB row ({vendor.strip()} {product.strip()})")

# Literal `common-*` (and any other bare-literal) modules emitted by the
# autodetect via `echo "MODULE <name>"`. The `$mod` variable form is the
# HARDWARE_DB table above and is skipped here.
for module in re.findall(r'echo "MODULE ([a-z0-9][a-z0-9-]*)"', db):
    referenced.setdefault(module, "autodetect MODULE line")

if not referenced:
    sys.exit("hardware-db: parsed no module references — parser or file changed")

missing = sorted(m for m in referenced if m not in available)
if missing:
    print(f"hardware-db: {len(missing)} module(s) not in nixos-hardware.nixosModules")
    for m in missing:
        print(f"  {m} — referenced by {referenced[m]}")
    sys.exit(1)

print(f"hardware-db: all {len(referenced)} referenced modules exist in nixos-hardware")
