73 lines
4.1 KiB
Python
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()
|