69 lines
4 KiB
Python
69 lines
4 KiB
Python
"""Reconstruct the complete pinned consumer with all reviewed source candidates."""
|
|
from pathlib import Path
|
|
import hashlib
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import tarfile
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
BASE = HERE.parent
|
|
INPUTS = Path('/tmp/custodian-forgejo-successor')
|
|
WORK = Path('/tmp/custodian-forgejo-successor-attempt2')
|
|
WORK.mkdir(exist_ok=False)
|
|
SOURCE = WORK / 'source'
|
|
assert not SOURCE.exists()
|
|
for name, pin in [('forgejo-v11.0.3.tar.gz', '1ddd8c926ca07d40436897971458ace7dcf1d3496a0813ab9e0d869edef2365c'),
|
|
('go1.24.3.tar.gz', '3333f6ea53afa971e9078895eaa4ac7204a8c6b5c68c10e6bc9a33e8e391bdd8')]:
|
|
assert hashlib.sha256((INPUTS / name).read_bytes()).hexdigest() == pin, name
|
|
with tarfile.open(INPUTS / name) as archive:
|
|
archive.extractall(WORK, filter='data')
|
|
(WORK / 'forgejo').rename(SOURCE)
|
|
# The interrupted packet's context snapshots are empty, but its frozen patch
|
|
# and inventory retain the exact source. Recover only if both hashes match.
|
|
operation = BASE / 'apps-operation-backend-r1'
|
|
row = next(row for row in json.loads((operation / 'source-inventory.json').read_text())['paths'] if row['path'] == 'models/db/context.go')
|
|
target = SOURCE / row['path']
|
|
assert hashlib.sha256(target.read_bytes()).hexdigest() == row['before_sha256']
|
|
original_context = target.read_bytes()
|
|
patch = (operation / 'forgejo-operation-source.patch').read_text()
|
|
start = patch.index('--- a/models/db/context.go\n')
|
|
end = patch.index('--- /dev/null\n', start)
|
|
subprocess.run(['patch', '--fuzz=0', '-p1'], input=patch[start:end], text=True, cwd=SOURCE, check=True, capture_output=True)
|
|
assert hashlib.sha256(target.read_bytes()).hexdigest() == row['after_sha256']
|
|
recovered = HERE / 'recovered-source/models/db/context.go'
|
|
recovered.parent.mkdir(parents=True, exist_ok=True)
|
|
recovered.write_bytes(target.read_bytes())
|
|
target.write_bytes(original_context)
|
|
applied = []
|
|
for packet, before, after in [
|
|
(BASE / 'forgejo-required-claim-values-r1', 'preimages', 'postimages'),
|
|
(BASE / 'forgejo-private-input-r1', 'preimages/forgejo', 'postimages/forgejo'),
|
|
(BASE / 'forgejo-private-input-r1', 'preimages/shared', 'postimages/shared'),
|
|
(BASE / 'apps-operation-backend-r1', 'preimages', 'postimages'),
|
|
(HERE, 'preimages/forgejo', 'forgejo-source'),
|
|
]:
|
|
for item in (packet / after).rglob('*'):
|
|
if not item.is_file():
|
|
continue
|
|
name = item.relative_to(packet / after)
|
|
target = SOURCE / name
|
|
original = packet / before / name
|
|
if packet == operation and str(name) == 'models/db/context.go':
|
|
item = recovered
|
|
assert hashlib.sha256(target.read_bytes()).hexdigest() == row['before_sha256']
|
|
original = target
|
|
if original.exists() and target.exists() and original.read_bytes() != target.read_bytes():
|
|
# Shared SQL redaction was already composed from the same source.
|
|
identical_shared = name.as_posix().startswith('models/db/') and item.read_bytes() == target.read_bytes()
|
|
expanded_hook_test = (packet == operation and str(name) == 'models/db/sensitive_sql_test.go'
|
|
and hashlib.sha256(target.read_bytes()).hexdigest() == 'f0f74c09a9e96a6529db7b9ce459a2ea37e204de38c5ad01855b80c9a992a769'
|
|
and hashlib.sha256(item.read_bytes()).hexdigest() == 'de6353c955047c3311747e4777b9f9b2195e9efb19160b971dd758dfc94cf31b')
|
|
assert identical_shared or expanded_hook_test, str(name)
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copyfile(item, target)
|
|
applied.append({'packet': packet.name, 'path': str(name), 'sha256': hashlib.sha256(item.read_bytes()).hexdigest()})
|
|
shutil.copytree(HERE / 'access-engine-source/adapters/go/decisionpep', SOURCE / 'third_party/access-engine-pep')
|
|
(WORK / 'home').mkdir()
|
|
(HERE / 'consumer-reconstruction.json').write_text(json.dumps({'workspace': str(WORK), 'inputs_verified': True, 'paths': applied}, indent=2) + '\n')
|
|
print(json.dumps({'workspace': str(WORK), 'composed_paths': len(applied)}))
|