2020-04-20 01:00:33 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import plistlib
|
|
|
|
import subprocess
|
|
|
|
import time
|
2022-06-22 21:56:35 +00:00
|
|
|
import os
|
|
|
|
import os.path
|
|
|
|
|
|
|
|
def bold_red(x):
|
|
|
|
return "\x1b[31;1m" + x + "\x1b[0m"
|
|
|
|
|
|
|
|
if not @notarize_py_is_sysext@:
|
|
|
|
print(bold_red("\nUnable to notarize: this lokinet is not built as a system extension\n"), file=sys.stderr)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if not all(("@MACOS_NOTARIZE_USER@", "@MACOS_NOTARIZE_PASS@", "@MACOS_NOTARIZE_ASC@")):
|
|
|
|
print(bold_red("\nUnable to notarize: one or more required notarization variable not set; see contrib/macos/README.txt\n") +
|
|
|
|
" Called with -DMACOS_NOTARIZE_USER=@MACOS_NOTARIZE_USER@\n"
|
|
|
|
" -DMACOS_NOTARIZE_PASS=@MACOS_NOTARIZE_PASS@\n"
|
|
|
|
" -DMACOS_NOTARIZE_ASC=@MACOS_NOTARIZE_ASC@\n",
|
|
|
|
file=sys.stderr)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
os.chdir("@PROJECT_BINARY_DIR@")
|
2022-08-29 15:53:08 +00:00
|
|
|
app = "@lokinet_app@"
|
|
|
|
zipfile = f"Lokinet.app.notarize.zip"
|
2022-08-12 22:57:00 +00:00
|
|
|
print(f"Creating {zipfile} from {app}")
|
2022-06-22 21:56:35 +00:00
|
|
|
if os.path.exists(zipfile):
|
|
|
|
os.remove(zipfile)
|
2022-08-12 22:57:00 +00:00
|
|
|
subprocess.run(['ditto', '-v', '-c', '-k', '--sequesterRsrc', '--keepParent', app, zipfile])
|
2020-04-20 01:00:33 +00:00
|
|
|
|
2020-04-21 00:51:24 +00:00
|
|
|
userpass = ('--username', "@MACOS_NOTARIZE_USER@", '--password', "@MACOS_NOTARIZE_PASS@")
|
2022-06-22 21:56:35 +00:00
|
|
|
print("Submitting {} for notarization; this may take a minute...".format(zipfile))
|
2020-04-20 01:00:33 +00:00
|
|
|
|
|
|
|
started = time.time()
|
2022-06-22 21:56:35 +00:00
|
|
|
command = [
|
2020-04-20 01:00:33 +00:00
|
|
|
'xcrun', 'altool',
|
|
|
|
'--notarize-app',
|
2022-06-22 21:56:35 +00:00
|
|
|
'--primary-bundle-id', 'org.lokinet.@PROJECT_VERSION@',
|
2020-04-20 01:00:33 +00:00
|
|
|
*userpass,
|
2020-04-21 00:51:24 +00:00
|
|
|
'--asc-provider', "@MACOS_NOTARIZE_ASC@",
|
2022-06-22 21:56:35 +00:00
|
|
|
'--file', zipfile,
|
2020-04-20 01:00:33 +00:00
|
|
|
'--output-format', 'xml'
|
2022-06-22 21:56:35 +00:00
|
|
|
]
|
|
|
|
print(command)
|
|
|
|
result = subprocess.run(command, stdout=subprocess.PIPE)
|
2020-04-20 01:00:33 +00:00
|
|
|
|
|
|
|
data = plistlib.loads(result.stdout)
|
|
|
|
if 'success-message' not in data or 'notarization-upload' not in data or 'RequestUUID' not in data['notarization-upload']:
|
|
|
|
print("Something failed, leaving you with this nice XML to figure out:\n{}".format(data))
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
uuid = data['notarization-upload']['RequestUUID']
|
|
|
|
elapsed = time.time() - started
|
|
|
|
mins, secs = int(elapsed // 60), elapsed % 60
|
|
|
|
print("Notarization submitted with request uuid = {} in {:d}m{:05.2f}s".format(uuid, mins, secs))
|
|
|
|
print(data['success-message'])
|
|
|
|
|
|
|
|
print("Begin polling for notarization result")
|
|
|
|
started_waiting = time.time()
|
|
|
|
done = False
|
|
|
|
success = False
|
|
|
|
while not done:
|
|
|
|
time.sleep(5)
|
|
|
|
result = subprocess.run([
|
|
|
|
'xcrun', 'altool',
|
|
|
|
'--notarization-info', uuid,
|
|
|
|
*userpass,
|
|
|
|
'--output-format', 'xml'
|
2022-07-13 22:34:09 +00:00
|
|
|
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if result.returncode == 1 and b'Gateway Timeout' in result.stderr:
|
|
|
|
status = "Apple's servers are trash (aka Gateway Timeout)"
|
2020-04-20 01:00:33 +00:00
|
|
|
else:
|
2022-07-13 22:34:09 +00:00
|
|
|
result.check_returncode()
|
|
|
|
data = plistlib.loads(result.stdout)
|
|
|
|
if 'notarization-info' not in data or 'Status' not in data['notarization-info']:
|
|
|
|
status = 'Request failed'
|
|
|
|
else:
|
|
|
|
status = data['notarization-info']['Status Message'] if 'Status Message' in data['notarization-info'] else ''
|
|
|
|
st = data['notarization-info']['Status']
|
|
|
|
if st == 'success':
|
|
|
|
success = True
|
|
|
|
done = True
|
|
|
|
elif st == 'invalid':
|
|
|
|
done = True
|
|
|
|
elif st == 'in progress' and len(status) == 0:
|
|
|
|
status = 'Notarization in progress'
|
|
|
|
|
|
|
|
if done and 'LogFileURL' in data['notarization-info']:
|
|
|
|
status += '\n\nlog file: {}'.format(data['notarization-info']['LogFileURL'])
|
2020-04-20 01:00:33 +00:00
|
|
|
|
|
|
|
elapsed = time.time() - started_waiting
|
|
|
|
mins, secs = int(elapsed // 60), int(elapsed % 60)
|
|
|
|
|
|
|
|
print("\033[1K\r(+{:d}m{:02d}s) {}: {}".format(mins, secs, st, status), end='', flush=True)
|
|
|
|
|
|
|
|
print("\n")
|
2020-04-21 03:57:53 +00:00
|
|
|
if not success:
|
|
|
|
sys.exit(42)
|
|
|
|
|
2022-06-22 21:56:35 +00:00
|
|
|
if os.path.exists(zipfile):
|
|
|
|
os.remove(zipfile)
|
|
|
|
|
|
|
|
print("Stapling {}...".format(app), end='')
|
|
|
|
result = subprocess.run(['xcrun', 'stapler', 'staple', app])
|
2020-04-21 03:57:53 +00:00
|
|
|
|
|
|
|
result.check_returncode()
|
2022-06-22 21:56:35 +00:00
|
|
|
|
2022-08-29 15:53:08 +00:00
|
|
|
with open("macos-notarized.stamp", 'w'):
|
|
|
|
pass
|
|
|
|
|
2022-06-22 21:56:35 +00:00
|
|
|
print(" success.\n")
|