File size: 1,743 Bytes
f592f80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"""Sign an existing, prepared AFFECTOR release copy from the inside out."""
from pathlib import Path
import argparse,subprocess
p=argparse.ArgumentParser(description=__doc__);p.add_argument('--app',type=Path,required=True);p.add_argument('--identity',required=True);a=p.parse_args();app=a.app.resolve()
if not (app/'Contents/Info.plist').is_file():raise SystemExit('Expected an existing .app bundle')
framework=app/'Contents/Resources/Python.framework'
for name,target in {'Versions/Current':'3.14','Python':'Versions/Current/Python','Resources':'Versions/Current/Resources','Headers':'Versions/Current/Headers'}.items():
 link=framework/name
 if not link.exists() and not link.is_symlink():link.symlink_to(target)
magic={bytes.fromhex(s) for s in ('cffaedfe','cefaedfe','feedfacf','feedface','cafebabe','cafebabf','bebafeca','bfbafeca')}
def macho(path):
 if path.is_symlink() or not path.is_file():return False
 with path.open('rb') as f:return f.read(4) in magic

def sign(path):
 r=subprocess.run(['codesign','--force','--sign',a.identity,'--timestamp','--options','runtime',str(path)],capture_output=True,text=True)
 if r.returncode:raise RuntimeError(str(path)+'\n'+r.stderr)
binaries=sorted((x for x in app.rglob('*') if macho(x)),key=lambda x:len(x.parts),reverse=True)
print('Signing',len(binaries),'native binaries',flush=True)
for i,b in enumerate(binaries):
 sign(b)
 if (i+1)%25==0:print(i+1,'signed',flush=True)
for b in sorted((x for x in app.rglob('*') if x.is_dir() and not x.is_symlink() and x.suffix in ('.app','.framework','.xpc','.appex')),key=lambda x:len(x.parts),reverse=True):sign(b)
sign(app);subprocess.run(['codesign','--verify','--deep','--strict',str(app)],check=True)
print('Signed and verified',app,flush=True)