21 lines
2.5 KiB
Python
21 lines
2.5 KiB
Python
from pathlib import Path
|
|
import json,gzip,hashlib,tarfile,shutil
|
|
r=Path('/Users/korizatou114/Projects/とりにく工房ゲーム制作部');base=r/'docs/plans/original-completion-2026-10-02/execution';e=base/'drive-offload-p18-review-r08-20261015';c=json.loads(gzip.decompress((e/'COVERAGE_PRECHECK.json.gz').read_bytes()));tmp=Path('/private/tmp/thetree-p18-cold-r08');tmp.mkdir(exist_ok=False);archive=tmp/'new-objects-r08.tar.gz';needed=c['uncovered_unique_objects'];assert sum(x['bytes']for x in needed.values())<50*1024**2
|
|
with tarfile.open(archive,'w:gz')as t:
|
|
for h,x in sorted(needed.items()):
|
|
p=Path(x['path']);assert p.stat().st_size==x['bytes']
|
|
with p.open('rb')as f:assert hashlib.file_digest(f,'sha256').hexdigest()==h
|
|
info=tarfile.TarInfo('objects/'+h);info.size=x['bytes'];info.mode=0o600
|
|
with p.open('rb')as f:t.addfile(info,f)
|
|
newhash=hashlib.sha256(archive.read_bytes()).hexdigest();archives={}
|
|
for batch in sorted({x.get('existing_cloud_batch')for x in c['members']if x['type']=='file'and x.get('existing_cloud_batch')}):
|
|
p=base/batch;v=json.loads((p/'CLOUD_ARCHIVE_VERIFIED.json').read_text());archives[batch]={'sha256':v['whole_archive_sha256'],'cloud_parts':json.loads((p/'CLOUD_PARTS.json').read_text()),'prior_actual_cloud_readback':v}
|
|
archives['r08-new']={'sha256':newhash,'cloud_url':None,'bytes':archive.stat().st_size}
|
|
rows=[]
|
|
root=Path(c['source']);s=root.stat();rows.append({'path':'.review-material','type':'directory','mode':s.st_mode&0o777,'mtime_ns':s.st_mtime_ns})
|
|
for x in c['members']:
|
|
v={k:val for k,val in x.items()if k!='existing_cloud_batch'};v['path']='.review-material/'+x['path']
|
|
if x['type']=='file':v['archive']=x['existing_cloud_batch']or'r08-new'
|
|
rows.append(v)
|
|
m={'source_root':c['source'],'restore_base':str(root.parent),'candidate':c['candidate'],'backend_completed':True,'members':rows,'files':c['file_count'],'logical_bytes':c['logical_bytes'],'archives':archives,'scope':'Closed independent backend review material only; source worktree/current canonical native proof and all formal run/traceability records stay local','formal_credit':0};(e/'MANIFEST.pending.json').write_text(json.dumps(m,ensure_ascii=False,indent=2)+'\n');(e/'NEW_OBJECTS_PREPARED.json').write_text(json.dumps({'path':str(archive),'sha256':newhash,'bytes':archive.stat().st_size,'objects':len(needed),'raw_unique_bytes':c['uncovered_unique_bytes'],'prior_logical_bytes_reused':c['logical_bytes']-c['uncovered_unique_bytes']},indent=2)+'\n');print({'new_archive_bytes':archive.stat().st_size,'new_objects':len(needed),'original_files':c['file_count']})
|