main
Drew Owens 0.11.4 source 8889116 1d ago
#!/usr/bin/env python3
"""check-docs-only.py [<since>] - the gate behind tools/release.sh --publish --docs-only (0.11.4).

A docs-only release skips the live CSWA gate, so it may change NOTHING the bridge runs. Exit 0 only when,
since <since> (default: the last commit that touched the release manifest = the last publish), nothing
changed in src/ or resources/ (committed, uncommitted or untracked: resources/ ships in the zip as it is
on disk), and Cargo.toml / Cargo.lock changed in nothing but THIS package's own version (the bump every
release makes; a dependency's version is code). Prints every offending path.
"""
import re, subprocess, sys

MAN = "adom-bridge-solidworks-manifest.json"
CODE = ["src", "resources"]


def git(*args, ok=False):
    r = subprocess.run(["git", *args], capture_output=True, text=True)
    if r.returncode != 0:
        if ok:
            return None
        raise SystemExit(f"  git {' '.join(args)} failed: {r.stderr.strip()}")
    return r.stdout


def package_name(toml):
    m = re.search(r'^\[package\]\s*$(.*?)(?=^\[|\Z)', toml, re.M | re.S)
    n = m and re.search(r'^name\s*=\s*"([^"]*)"', m.group(1), re.M)
    return n.group(1) if n else None


def without_own_version(name, text, pkg):
    """The file with this package's own version line blanked out."""
    if name == "Cargo.toml":
        def blank(m):
            return re.sub(r'^version\s*=\s*"[^"]*"\s*$', 'version = "<own>"', m.group(0), count=1, flags=re.M)
        return re.sub(r'^\[package\]\s*$.*?(?=^\[|\Z)', blank, text, count=1, flags=re.M | re.S)
    # Cargo.lock: the version line right after `name = "<pkg>"`.
    return re.sub(r'(^name = "' + re.escape(pkg or "") + r'"\nversion = )"[^"]*"', r'\1"<own>"', text, count=1, flags=re.M)


def offending(since):
    bad = []
    # Working tree against <since>: committed AND uncommitted changes.
    for path in git("diff", "--name-only", since, "--", *CODE).split():
        bad.append(f"{path} changed since {since[:8]}")
    for path in git("ls-files", "--others", "--exclude-standard", "--", *CODE).split():
        bad.append(f"{path} is new (untracked) - resources/ ships in the zip as it is on disk")
    pkg = package_name(open("Cargo.toml").read()) if __import__("os").path.isfile("Cargo.toml") else None
    for name in ("Cargo.toml", "Cargo.lock"):
        old = git("show", f"{since}:{name}", ok=True)
        try:
            new = open(name).read()
        except OSError:
            new = None
        if old is None and new is None:
            continue
        if old is None or new is None:
            bad.append(f"{name} was {'added' if old is None else 'removed'} since {since[:8]}")
        elif without_own_version(name, old, pkg) != without_own_version(name, new, pkg):
            bad.append(f"{name} changed beyond the package's own version since {since[:8]}")
    return bad


def main(argv):
    since = argv[1] if len(argv) > 1 else git("log", "-1", "--format=%H", "--", MAN).strip()
    if not since:
        print(f"  no commit has touched {MAN} - nothing was ever published to compare with")
        return 1
    bad = offending(since)
    for b in bad:
        print("  " + b)
    if bad:
        print(f"NOT docs-only: the bridge's code changed since {since[:8]} - publish with --require-live <cswa-check report>")
        return 1
    print(f"docs-only OK: nothing in src/ or resources/, and nothing in Cargo.toml / Cargo.lock but the version, changed since {since[:8]}")
    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv))