31 lines
1.4 KiB
Python
31 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Validate the release asset set and the portable Windows executable."""
|
|
from pathlib import Path, PurePosixPath
|
|
import sys
|
|
import zipfile
|
|
|
|
|
|
def verify(directory, version):
|
|
required = {f"TTREE_{version}_universal.dmg", "TTREE_universal.app.tar.gz",
|
|
"TTREE_universal.app.tar.gz.sig", "latest.json", f"TTREE_{version}_windows_x64.zip"}
|
|
allowed = required | {"macos.sha256", "windows.sha256", "SHA256SUMS", "SHA256SUMS.sig"}
|
|
actual = {p.name for p in directory.iterdir()}
|
|
if not required <= actual or actual - allowed:
|
|
raise ValueError(f"unexpected release files: missing={required-actual}, extra={actual-allowed}")
|
|
for name in required:
|
|
if not (directory / name).is_file() or (directory / name).stat().st_size == 0:
|
|
raise ValueError(f"empty release asset: {name}")
|
|
with zipfile.ZipFile(directory / f"TTREE_{version}_windows_x64.zip") as archive:
|
|
if archive.testzip():
|
|
raise ValueError("damaged Windows ZIP")
|
|
for entry in archive.namelist():
|
|
if ".." in PurePosixPath(entry).parts or entry.startswith(("/", "\\")) or ":" in entry:
|
|
raise ValueError("unsafe Windows ZIP path")
|
|
with archive.open("TTREE/TTREE.exe") as executable:
|
|
if executable.read(2) != b"MZ":
|
|
raise ValueError("Windows executable is missing its PE header")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
verify(Path(sys.argv[1]), sys.argv[2])
|