#!/usr/bin/env python3 """Materialize the three verified, pinned tools without running download hooks.""" import hashlib import json from pathlib import Path, PurePosixPath import subprocess import tarfile import zipfile ROOT = Path(__file__).resolve().parents[2] SOURCE = ROOT / 'build-pdfium-intent/source' RESULTS = ROOT / 'tests/results/pdfium-intent-build' def sha(path): with path.open('rb') as stream: return hashlib.file_digest(stream, 'sha256').hexdigest() def main(): downloads = json.loads((RESULTS / 'tool-downloads.json').read_text()) destinations = { 'clang.tar.xz': 'third_party/llvm-build/Release+Asserts', 'sysroot.tar.xz': 'build/linux/debian_bullseye_amd64-sysroot', 'gn.zip': 'buildtools/linux64', } records = [] for row in downloads['inputs']: archive = ROOT / row['path'] assert sha(archive) == row['sha256'] destination = SOURCE / destinations[row['name']] already_extracted = destination.exists() destination.mkdir(parents=True, exist_ok=True) if row['name'].endswith('.tar.xz'): with tarfile.open(archive) as tar: members = tar.getmembers() assert len(members) < 30000 assert sum(member.size for member in members) < 1024**3 for member in members: assert member.isfile() or member.isdir() or member.issym() or member.islnk() assert not PurePosixPath(member.name).is_absolute() assert '..' not in PurePosixPath(member.name).parts # Python's data filter also rejects links that escape the destination. tarfile.data_filter(member, str(destination)) if not already_extracted: tar.extractall(destination, members=members, filter='data') for member in members: target = destination / member.name if member.isfile() or member.islnk(): with tar.extractfile(member) as stream: assert sha(target) == hashlib.file_digest(stream, 'sha256').hexdigest() elif member.issym(): assert target.is_symlink() and str(target.readlink()) == member.linkname else: with zipfile.ZipFile(archive) as zip_file: assert set(zip_file.namelist()) == {'gn', '.cipdpkg/manifest.json'} manifest = json.loads(zip_file.read('.cipdpkg/manifest.json')) assert manifest['package_name'] == row['cipdPackage'] for member in zip_file.infolist(): assert member.file_size < 16 * 1024**2 target = destination / member.filename target.parent.mkdir(parents=True, exist_ok=True) if not already_extracted: target.write_bytes(zip_file.read(member)) target.chmod((member.external_attr >> 16) & 0o777) assert target.read_bytes() == zip_file.read(member) records.append({'archive': row['path'], 'sha256': row['sha256'], 'destination': str(destination.relative_to(ROOT))}) stamp = SOURCE / 'third_party/llvm-build/Release+Asserts/cr_build_revision' stamp.write_text('llvmorg-24-init-3796-g20e97c4b-4\n') gclient = SOURCE / 'build/config/gclient_args.gni' gclient_text = ('android_ndk_version = "2@30.0.16138531"\n' 'build_with_chromium = false\ncheckout_android = false\n' 'checkout_libpng = true\ncheckout_skia = false\n') if gclient.exists(): assert gclient.read_text() == gclient_text else: gclient.write_text(gclient_text) versions = {} for name, relative in [('gn', 'buildtools/linux64/gn'), ('clang', 'third_party/llvm-build/Release+Asserts/bin/clang'), ('lld', 'third_party/llvm-build/Release+Asserts/bin/ld.lld')]: result = subprocess.run([str(SOURCE / relative), '--version'], check=True, capture_output=True, text=True) versions[name] = result.stdout.strip() assert '150a9d6ba0aa' in versions['gn'] assert 'clang version 24.0.0git' in versions['clang'] record = {'success': True, 'preparerSha256': sha(Path(__file__)), 'tools': records, 'versions': versions, 'gclientArgsSha256': sha(gclient), 'scope': 'Pinned tools extracted; version commands only. No system installation or source download hooks.'} (RESULTS / 'tool-materialization.json').write_text(json.dumps(record, indent=2) + '\n') print(json.dumps(record, indent=2)) if __name__ == '__main__': main()