Files

92 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Independent real-world cross-check for diffkit.
The self-test uses GNU `diff` output on synthetic files. This one uses a real
repository: it takes the diffs produced by `git diff` for the most recent commit
of a repo, applies each one with diffkit, and compares the result byte-for-byte
against what git itself says the file looks like at HEAD (`git show HEAD:path`).
Usage: python3 verify_realrepo.py [repo] [rev] [max_files]
Exit code 0 iff every applicable file matched.
"""
from __future__ import annotations
import os
import subprocess
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import diffkit # noqa: E402
MAX_BYTES = 400_000
def git(repo: str, *args: str) -> tuple[int, bytes]:
r = subprocess.run(["git", "-C", repo, *args], capture_output=True)
return r.returncode, r.stdout
def main() -> int:
repo = sys.argv[1] if len(sys.argv) > 1 else "/root/troupe-standup"
rev = sys.argv[2] if len(sys.argv) > 2 else "HEAD~1"
limit = int(sys.argv[3]) if len(sys.argv) > 3 else 15
verbose = os.environ.get("VERBOSE") == "1"
rc, out = git(repo, "diff", "--name-only", "-r", rev, "HEAD")
if rc != 0:
print("git diff failed for %s..HEAD" % rev)
return 2
names = [n for n in out.decode("utf-8", "replace").split("\n") if n]
print("repo=%s rev=%s..HEAD %d changed paths" % (repo, rev, len(names)))
checked = passed = skipped = 0
for name in names:
if checked >= limit:
break
rc_old, old = git(repo, "show", "%s:%s" % (rev, name))
rc_new, new = git(repo, "show", "HEAD:%s" % name)
if rc_old != 0 or rc_new != 0:
skipped += 1
if verbose:
print(" skip %-60s (added or deleted in this commit)" % name)
continue
if b"\x00" in old or b"\x00" in new or max(len(old), len(new)) > MAX_BYTES:
skipped += 1
if verbose:
print(" skip %-60s (binary or >%d bytes)" % (name, MAX_BYTES))
continue
rc_d, d = git(repo, "diff", "--no-color", "-U3", rev, "HEAD", "--", name)
if rc_d != 0 or not d.strip():
skipped += 1
if verbose:
print(" skip %-60s (no textual diff)" % name)
continue
old_s = old.decode("utf-8")
new_s = new.decode("utf-8")
diff_s = d.decode("utf-8")
checked += 1
try:
got = diffkit.apply_one(diff_s, old_s)
except Exception as e: # noqa: BLE001
print(" FAIL %-60s raised %s: %s" % (name, type(e).__name__, e))
continue
if got == new_s:
passed += 1
print(" ok %-60s %d bytes, %d hunks"
% (name, len(new_s.encode()), len(diffkit.parse_unified_diff(diff_s)[0].hunks)))
else:
print(" FAIL %-60s mismatch (got %d bytes, want %d)"
% (name, len(got.encode()), len(new_s.encode())))
print("\n%d/%d applicable files reproduced exactly (%d skipped)"
% (passed, checked, skipped))
return 0 if checked > 0 and passed == checked else 1
if __name__ == "__main__":
sys.exit(main())