from pathlib import Path
import json,hashlib,tarfile,shutil,html,re
r=Path(__file__).resolve().parents[1];p=r/'private/dm-package';frozen=json.load(open(r/'evidence/final-freeze.json'));e=r/'private/final-acceptance'
v=json.load(open(e/'values-result.json'));m=json.load(open(e/'metadata-result.json'));im=json.load(open(e/'import-result.json'));probe=json.load(open(e/'probe-result.json'));assert v['comparison']['equal'] and v['total_rows']==1442521 and m['failed']==0 and not m['unverified'] and m['passed']==11562 and im['total_rows']==1442521 and probe['passed'] and len(probe['clone_tests'])==94
archive=r/'private/final-release'/frozen['archive'];assert hashlib.sha256(archive.read_bytes()).hexdigest()==frozen['sha256']
expected={l.split('  ',1)[1]:l.split('  ',1)[0]for l in (p/'PAYLOAD.sha256').read_text().splitlines()};got={}
with tarfile.open(archive,'r:gz')as t:
 for f in t:
  if not f.isfile():continue
  stream=t.extractfile(f);h=hashlib.sha256()
  for b in iter(lambda:stream.read(1024*1024),b''):h.update(b)
  got['/'.join(f.name.split('/')[1:])]=h.hexdigest()
assert all(got[k]==h for k,h in expected.items())
md=(p/'INSTALL.md').read_text();ht=(p/'INSTALL.html').read_text();assert re.findall(r'```[^\n]*\n(.*?)\n```',md,re.S)==[html.unescape(x)for x in re.findall(r'<pre><code>(.*?)</code></pre>',ht,re.S)]
report={'status':'VERIFIED_OFFLINE_MIGRATION_PACKAGE','source_sha256':'fa3a82a129a8366535c3303c3eb92eda097b4f7685e77a2adf5fc83a4b188d3a','application_commit':'c40700715f8c23eb33eb855beec44b28dd19ec5b','source_no_new_data_confirmed_by_user':True,'tables':119,'columns':1392,'rows':1442521,'lob_files':705,'original_tables':97,'original_columns':1022,'source_unicode_hex_independently_verified':True,'original_field_differences':0,'dm_values_equal':True,'dm_value_differences':[],'dm_metadata_passed':11562,'dm_metadata_failed':0,'dm_metadata_unverified':0,'identity_clone_tests':94,'archive_sha256':frozen['sha256'],'archive_bytes':archive.stat().st_size,'archive_files':len(got),'payload_checksums_verified':len(expected),'markdown_html_command_blocks_equal':19,'python_tests':43,'first_rehearsal_counts_preserved':True,'first_production_modified':False,'rehearsal_build':'--03134284488-20260212-314192-20200','customer_build':'--03134284488-20260902-347071-20200 Pack30','customer_target_probe_required':True,'customer_import_done':False,'device_kind':'NULL pending actual device identification','final_patch_lineage':frozen,'remaining':['客户现场必须先跑本包probe，再导入验收','设备类型及真实设备上报属于现场验收，未猜填device_kind','本包不包含应用静态图片等文件迁移']}
(r/'evidence/final-acceptance.json').write_text(json.dumps(report,ensure_ascii=False,indent=2))
d=Path('/Users/wiscourper/Downloads/work/团餐项目/食安/中央网信办后期维护/中央网信办迁移1021/食安第二套数据库/达梦迁移交付包');history=d/'已撤回候选-禁止使用';history.mkdir(mode=0o700,exist_ok=True)
for f in list(d.iterdir()):
 if f.is_file() and ('.INVALID' in f.name or f.name.startswith('候选包')):f.rename(history/f.name)
shutil.copy2(archive,d/archive.name);(d/archive.name).chmod(0o600);(d/(archive.name+'.sha256')).write_text(frozen['sha256']+'  '+archive.name+'\n')
for n in ['INSTALL.md','INSTALL.html']:shutil.copy(p/n,d/n)
shutil.copy(r/'evidence/final-acceptance.json',d/'验收结果.json')
assert hashlib.sha256((d/archive.name).read_bytes()).hexdigest()==frozen['sha256']
(r/'evidence/local-delivery.json').write_text(json.dumps({'directory':str(d),'archive':archive.name,'bytes':archive.stat().st_size,'sha256':frozen['sha256'],'status':report['status']},ensure_ascii=False,indent=2))
print(json.dumps({'delivered':True,'archive_sha256':frozen['sha256'],'archive_files':len(got),'payload_checksums_verified':len(expected),'rows':v['total_rows'],'metadata_passed':m['passed']}))
