29 lines
1.3 KiB
Python
29 lines
1.3 KiB
Python
"""Reproduce the frozen candidate context from the versioned application sources.
|
|
|
|
No Docker/runtime/secret reads. Existing output is verified, never silently replaced.
|
|
"""
|
|
from pathlib import Path
|
|
import hashlib,json,shutil
|
|
|
|
PACKAGE=Path(__file__).resolve().parent
|
|
ROOT=PACKAGE.parents[1]
|
|
|
|
def build():
|
|
manifest=json.loads((PACKAGE/'RELEASE.json').read_text())
|
|
context=PACKAGE/'context'
|
|
for name,v in manifest['files'].items():
|
|
if Path(name).is_absolute() or '..' in Path(name).parts:raise ValueError('Unsafe source path')
|
|
source=ROOT/name;target=context/name
|
|
if source.is_symlink() or not source.is_file() or hashlib.sha256(source.read_bytes()).hexdigest()!=v['after']:
|
|
raise ValueError('Checked-out source does not match release: '+name)
|
|
if target.is_symlink():raise ValueError('Target symlink refused')
|
|
if target.exists() and hashlib.sha256(target.read_bytes()).hexdigest()!=v['after']:
|
|
raise ValueError('Existing context differs: '+name)
|
|
for name in manifest['files']:
|
|
target=context/name
|
|
if target.exists():continue
|
|
target.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(ROOT/name,target);target.chmod(0o644)
|
|
print('Frozen build context verified:',len(manifest['files']),'source files; no installation.')
|
|
|
|
if __name__=='__main__':build()
|