"""Atomic content-addressed JSON and source artifact storage.""" import hashlib import json import os from pathlib import Path import tempfile def canonical(value): return json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=False, allow_nan=False).encode('utf-8') def atomic(path, data, immutable=False): path = Path(path) path.parent.mkdir(parents=True, exist_ok=True) fd, name = tempfile.mkstemp(dir=path.parent, prefix='.write-') try: with os.fdopen(fd, 'wb') as stream: stream.write(data) stream.flush() os.fsync(stream.fileno()) if immutable: try: os.link(name, path) except FileExistsError: if path.read_bytes() != data: raise ValueError(f'immutable content mismatch: {path}') from None else: os.replace(name, path) finally: Path(name).unlink(missing_ok=True) def put(root, kind, value): content = canonical(value) ident = hashlib.sha256(content).hexdigest() atomic(Path(root) / 'data' / kind / f'{ident}.json', content + b'\n', immutable=True) return ident def get(root, kind, ident): if len(ident) != 64 or any(c not in '0123456789abcdef' for c in ident): raise ValueError('invalid content ID') value = json.loads((Path(root) / 'data' / kind / f'{ident}.json').read_text()) if hashlib.sha256(canonical(value)).hexdigest() != ident: raise ValueError(f'integrity mismatch: {kind}/{ident}') return value def all_records(root, kind): return [(p.stem, get(root, kind, p.stem)) for p in sorted((Path(root) / 'data' / kind).glob('*.json'))]