Files
docview/tests/cmyk_lut/prepare_pdfium_source.py
2026-09-21 13:41:40 +09:00

73 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""Materialize previously verified fixed Git archives for an isolated PDFium build."""
import hashlib
import json
from pathlib import Path, PurePosixPath
import tarfile
ROOT = Path(__file__).resolve().parents[2]
def sha(path):
with path.open('rb') as stream: return hashlib.file_digest(stream,'sha256').hexdigest()
def main():
reports=[ROOT/'tests/results/source-archives/pdfium-git/report.json',
ROOT/'tests/results/source-archives/pdfium-gitlink/report.json']
repositories=[]
for path in reports:
report=json.loads(path.read_text()); assert report['success']
repositories.extend(report['repositories'])
source=ROOT/'build-pdfium-intent/source'
source.mkdir(parents=True,exist_ok=False)
output=ROOT/'tests/results/pdfium-intent-build'; output.mkdir(parents=True,exist_ok=False)
materialized=[]; links=[]; total=0; count=0
for repository in repositories:
archive=ROOT/repository['archive']; inventory=ROOT/repository['inventory']
assert sha(archive)==repository['archiveSha256'] and sha(inventory)==repository['inventorySha256']
expected={r['path']:r for line in inventory.open() if (r:=json.loads(line))['archived']}
prefix='pdfium/'+('' if repository['path']=='.' else repository['path']+'/')
found=set()
with tarfile.open(archive) as stream:
for member in stream:
assert member.name.startswith(prefix)
relative=member.name.removeprefix(prefix)
if member.isdir(): continue
assert relative in expected and relative not in found
found.add(relative); row=expected[relative]
name=PurePosixPath(member.name.removeprefix('pdfium/'))
assert not name.is_absolute() and '..' not in name.parts and '\\' not in str(name)
path=source/name; assert path.resolve().is_relative_to(source) and not path.exists()
path.parent.mkdir(parents=True,exist_ok=True)
if member.issym():
assert row['mode']=='120000' and member.linkname==row['linkTarget']
target=PurePosixPath(member.linkname)
assert not target.is_absolute() and (path.parent/target).resolve().is_relative_to(source)
assert hashlib.sha256(member.linkname.encode()).hexdigest()==row['sha256']
links.append((path,member.linkname))
continue
assert member.isfile() and row['mode'] in ('100644','100755') and member.size==row['bytes']
total+=member.size; count+=1
assert member.size<=256*1024**2 and total<=2*1024**3 and count<=100000
digest=hashlib.sha256()
with stream.extractfile(member) as incoming, path.open('xb') as outgoing:
for chunk in iter(lambda:incoming.read(1024*1024),b''):
digest.update(chunk); outgoing.write(chunk)
assert digest.hexdigest()==row['sha256']
path.chmod(0o755 if row['mode']=='100755' else 0o644)
assert found==expected.keys()
materialized.append({k:repository[k] for k in ('path','revision','archive','archiveSha256','inventory','inventorySha256')})
for path,target in links:
assert (path.parent/target).resolve().is_file()
path.symlink_to(target)
record={'success':True,'preparerSha256':sha(Path(__file__)),'source':str(source.relative_to(ROOT)),
'repositories':materialized,'regularFiles':count,'regularBytes':total,'symlinks':len(links),
'sourceReports':{str(p.relative_to(ROOT)):sha(p) for p in reports},
'scope':'Fixed sources materialized for a separate local build. No source hooks, downloads or build executed by this preparer. Production dependency remains unchanged.'}
(output/'source-materialization.json').write_text(json.dumps(record,indent=2)+'\n')
print(json.dumps({'repositories':len(materialized),'regularFiles':count,'regularBytes':total,'symlinks':len(links)}))
if __name__=='__main__':main()