initial commit

This commit is contained in:
2026-09-21 13:41:40 +09:00
commit 855c7328df
411 changed files with 85352 additions and 0 deletions
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""Check recorded Arch patches on selected pristine release sources, without building."""
import argparse
import hashlib
import json
from pathlib import Path, PurePosixPath
import shutil
import subprocess
ROOT = Path(__file__).resolve().parents[2]
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def main():
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--output', type=Path, required=True)
a = p.parse_args(); output = a.output.resolve()
if not output.is_relative_to(ROOT):
p.error('Use an output directory inside the workspace')
inspection = ROOT / 'tests/results/source-archives/qt-inspection'
record = json.loads((inspection / 'report.json').read_text())
if not record['success'] or sha(inspection / 'files.jsonl') != record['inventorySha256']:
raise SystemExit('A verified source inventory is required')
inventory = {row['path']: row for line in (inspection / 'files.jsonl').open() if (row := json.loads(line))}
source = ROOT / record['sourceTree']
evidence = ROOT / 'tests/results/source-correspondence/arch'
patches = [
('qtbase', evidence / 'packages/qt6-base/qt6-base-cflags.patch'),
('qtbase', evidence / 'packages/qt6-base/qt6-base-nostrip.patch'),
('qtbase', evidence / 'upstream-metadata/qtbase-e80e3f0.patch'),
('qtdeclarative', evidence / 'upstream-metadata/qtdeclarative-2efb7c6.patch')]
output.mkdir(parents=True, exist_ok=False)
inputs, steps = {}, []
for module, patch in patches:
for line in patch.read_text().splitlines():
if not line.startswith('+++ b/'):
continue
name = line[len('+++ b/'):].split('\t', 1)[0]
path = PurePosixPath(name)
if path.is_absolute() or '..' in path.parts:
raise ValueError('Unsafe patch target')
relative = module + '/' + name
target = output / 'tree' / relative
target.parent.mkdir(parents=True, exist_ok=True)
if relative in inputs:
continue
before = None
if (source / relative).exists():
before = sha(source / relative)
if before != inventory[relative]['sha256']:
raise ValueError('Selected release file changed')
shutil.copyfile(source / relative, target)
inputs[relative] = before
success = True
for module, patch in patches:
# The two local Arch patches use GNU patch's default fuzz tolerance.
# Keep exact context for the separately recorded upstream changes.
fuzz = 2 if patch.name.startswith('qt6-base-') else 0
step = {'module': module, 'patch': str(patch.relative_to(ROOT)), 'patchSha256': sha(patch), 'fuzzLimit': fuzz}
for label, extra in [('dryRun', ['--dry-run']), ('apply', [])]:
command = ['patch', '--batch', '--forward', '--fuzz=' + str(fuzz), '-p1', '-d', str(output / 'tree' / module), '-i', str(patch), *extra]
run = subprocess.run(command, capture_output=True, text=True, timeout=20)
step[label] = {'exitCode': run.returncode, 'stdout': run.stdout, 'stderr': run.stderr}
if run.returncode:
success = False; break
steps.append(step)
if not success:
break
after = {name: sha(output / 'tree' / name) if (output / 'tree' / name).is_file() else None for name in inputs}
report = {'success': success, 'sourceArchiveSha256': record['archiveSha256'],
'beforeSha256': inputs, 'afterSha256': after, 'steps': steps,
'pristineFilesUnchanged': all(sha(source / name) == digest for name, digest in inputs.items() if digest),
'scope': 'Recorded Arch patches checked on a private selected-file copy with explicit tolerances; no upstream build scripts run and no resulting binaries rebuilt'}
report['installedMkspecComparisons'] = {
name: sha(output / 'tree/qtbase/mkspecs/common' / name) == sha(Path('/usr/lib/qt6/mkspecs/common') / name)
for name in ['g++-unix.conf', 'gcc-base.conf']}
(output / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
print(json.dumps({'success': success, 'patches': len(steps), 'targetFiles': len(inputs), 'pristineFilesUnchanged': report['pristineFilesUnchanged']}))
return 0 if success else 1
if __name__ == '__main__':
raise SystemExit(main())