98 lines
4.7 KiB
Python
98 lines
4.7 KiB
Python
#!/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 = "[email protected]"\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()
|