Files
ARCADIA-Studio/harness/experiments/canvas-repair-package-33e30c1-20260912/payload/r2/extract-preview.py
T

101 lines
5.1 KiB
Python

"""Extract the accepted package producer result once; verify exact extracted bytes."""
from pathlib import Path, PurePosixPath
import datetime
import hashlib
import json
import re
import shutil
import zipfile
ROOT = Path(__file__).resolve().parent / 'native-repair-union-33e30c1-r2'
NAME = 'ArcadiaStudio-0.2.0-preview.canvas-repair.20260912-x86_64-pc-windows-gnullvm'
SOURCE = '33e30c1cd7a6c99513a0ebd02ba68fccbad8f58d'
def require(condition, message):
if not condition:
raise RuntimeError(message)
def sha(path):
with path.open('rb') as stream:
return hashlib.file_digest(stream, 'sha256').hexdigest()
def write_new(path, data):
with path.open('x', encoding='utf-8', newline='\n') as stream:
json.dump(data, stream, indent=2)
stream.write('\n')
def main():
package = json.loads((ROOT / 'package-result.json').read_text(encoding='utf-8-sig'))
require(package['exit'] == 0 and package['source_commit'] == SOURCE, 'No accepted producer result')
result = package['result']
archive = Path(result['Archive'])
require(archive.resolve() == (ROOT / 'dist' / (NAME + '.zip')).resolve(), 'Unexpected archive path')
expected = result['SHA256']
require(re.fullmatch('[0-9a-f]{64}', expected) is not None, 'Invalid archive hash')
checksum = Path(str(archive) + '.sha256').read_text(encoding='utf-8-sig')
require(checksum == f'{expected} {NAME}.zip\n', 'Checksum file disagrees with producer')
require(sha(archive) == expected, 'Archive hash mismatch')
destination = ROOT / 'extracted'
receipt = ROOT / 'extraction-readback.json'
require(not destination.exists() and not receipt.exists(), 'Use a fresh extraction location')
started = datetime.datetime.now(datetime.timezone.utc).isoformat()
# Exclusive claim prevents concurrent extraction attempts; preserved on failure.
with (ROOT / 'extraction.claim').open('x') as claim:
claim.write(started + '\n')
try:
with zipfile.ZipFile(archive) as bundle:
entries = bundle.infolist()
require(len(entries) == result['Files'], 'Producer archive count mismatch')
names = set()
for entry in entries:
path = PurePosixPath(entry.filename)
require(path.parts[0] == NAME and len(path.parts) > 1 and not path.is_absolute()
and '..' not in path.parts and '\\' not in entry.filename
and ':' not in entry.filename and not entry.is_dir(), 'Unsafe archive member')
require(all(part == part.rstrip(' .') for part in path.parts), 'Ambiguous Windows path')
require(entry.filename.casefold() not in names, 'Case-insensitive duplicate member')
names.add(entry.filename.casefold())
destination.mkdir()
records = []
for entry in entries:
target = destination.joinpath(*PurePosixPath(entry.filename).parts)
target.parent.mkdir(parents=True, exist_ok=True)
with bundle.open(entry) as source, target.open('xb') as output:
shutil.copyfileobj(source, output)
with bundle.open(entry) as source:
expected_file = hashlib.file_digest(source, 'sha256').hexdigest()
actual = sha(target)
require(actual == expected_file and target.stat().st_size == entry.file_size,
f'Extraction changed file: {entry.filename}')
records.append({'path': entry.filename, 'bytes': entry.file_size, 'sha256': actual})
actual_names = {p.relative_to(destination).as_posix().casefold() for p in destination.rglob('*') if p.is_file()}
require(actual_names == names, 'Extracted inventory differs')
package_dir = destination / NAME
sums = {}
for line in (package_dir / 'SHA256SUMS.txt').read_text(encoding='utf-8-sig').splitlines():
expected_file, relative = line.split(' ', 1)
require(relative not in sums, 'Duplicate checksum member')
sums[relative] = expected_file
actual_sums = {r['path'][len(NAME) + 1:]: r['sha256'] for r in records
if r['path'] != f'{NAME}/SHA256SUMS.txt'}
require(sums == actual_sums, 'Extracted checksum inventory disagrees with actual files')
require(sha(archive) == expected, 'Archive changed during extraction')
record = {'started_utc': started, 'completed_utc': datetime.datetime.now(datetime.timezone.utc).isoformat(),
'exit': 0, 'source_commit': SOURCE, 'archive': str(archive), 'archive_sha256': expected,
'package_directory': str(package_dir), 'files': records}
write_new(receipt, record)
print(json.dumps({'exit': 0, 'files': len(records), 'archive_sha256': expected,
'package_directory': str(package_dir)}))
except Exception as error:
write_new(ROOT / 'extraction-failure.json', {'started_utc': started, 'exit': 1,
'error': str(error), 'type': type(error).__name__})
raise
if __name__ == '__main__':
main()