"""Regenerate SHA256SUMS.txt, then verify.

Run this last, after every other change. Any edit to any deposited file
invalidates the manifest, so the manifest is written from the files as they
stand and then checked, which is the only order that can end consistent.
"""
import hashlib
import os
import subprocess
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
# esm1.txt is the source Online Resource 1 is rebuilt from, so it is hashed
# like everything else; only the manifest itself and build artefacts are left out.
SKIP = ("manuscript/", "SHA256SUMS", "__pycache__", ".pyc")


def main():
    lines = ["# SHA-256 of every file in the deposited package",
             "#",
             "# Verify with:  sha256sum -c SHA256SUMS.txt",
             "# or:           python3 code/verify_package.py",
             "#"]
    n = 0
    for dirpath, dirnames, filenames in os.walk(ROOT):
        dirnames[:] = [d for d in dirnames
                       if d not in ("manuscript", "__pycache__")]
        for f in sorted(filenames):
            p = os.path.join(dirpath, f)
            rel = os.path.relpath(p, ROOT)
            if any(k in rel for k in SKIP):
                continue
            h = hashlib.sha256(open(p, "rb").read()).hexdigest()
            lines.append(f"{h}  {rel}")
            n += 1
    out = os.path.join(ROOT, "SHA256SUMS.txt")
    with open(out, "w") as fh:
        fh.write("\n".join(sorted(lines[:5]) + sorted(lines[5:])) + "\n")
    print(f"  SHA256SUMS.txt written for {n} files")
    r = subprocess.run([sys.executable,
                        os.path.join(HERE, "verify_package.py")],
                       capture_output=True, text=True, cwd=ROOT)
    print(f"  verify_package.py exit {r.returncode}")
    return r.returncode


if __name__ == "__main__":
    raise SystemExit(main())
