mirror of
https://github.com/signalapp/libsignal.git
synced 2024-09-20 12:02:18 +02:00
80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
#
|
||
|
# Copyright 2023 Signal Messenger, LLC
|
||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||
|
#
|
||
|
|
||
|
# This script is based on RingRTC's fetch-artifact.py,
|
||
|
# but simplified for using only as a helper for LibSignalClient.podspec.
|
||
|
|
||
|
import argparse
|
||
|
import hashlib
|
||
|
import os
|
||
|
import sys
|
||
|
import urllib.request
|
||
|
|
||
|
from typing import BinaryIO
|
||
|
|
||
|
UNVERIFIED_DOWNLOAD_NAME = "unverified.tmp"
|
||
|
|
||
|
|
||
|
def build_argument_parser() -> argparse.ArgumentParser:
|
||
|
parser = argparse.ArgumentParser(
|
||
|
description='Download and verify a build artifact archive.')
|
||
|
parser.add_argument('-u', '--url',
|
||
|
required=True,
|
||
|
help='URL of an artifact archive')
|
||
|
parser.add_argument('-c', '--checksum',
|
||
|
required=True,
|
||
|
help='sha256sum of the unexpanded artifact archive')
|
||
|
parser.add_argument('-o', '--output-dir',
|
||
|
required=True,
|
||
|
help='Directory to store the archives in')
|
||
|
return parser
|
||
|
|
||
|
|
||
|
def download_if_needed(archive_file: str, url: str, checksum: str) -> BinaryIO:
|
||
|
try:
|
||
|
f = open(archive_file, 'rb')
|
||
|
digest = hashlib.sha256()
|
||
|
chunk = f.read1()
|
||
|
while chunk:
|
||
|
digest.update(chunk)
|
||
|
chunk = f.read1()
|
||
|
if digest.hexdigest() == checksum.lower():
|
||
|
return f
|
||
|
print("existing file '{}' has non-matching checksum {}; re-downloading...".format(archive_file, digest.hexdigest()), file=sys.stderr)
|
||
|
except FileNotFoundError:
|
||
|
pass
|
||
|
|
||
|
print("downloading {}...".format(archive_file), file=sys.stderr)
|
||
|
try:
|
||
|
with urllib.request.urlopen(url) as response:
|
||
|
digest = hashlib.sha256()
|
||
|
f = open(UNVERIFIED_DOWNLOAD_NAME, 'w+b')
|
||
|
chunk = response.read1()
|
||
|
while chunk:
|
||
|
digest.update(chunk)
|
||
|
f.write(chunk)
|
||
|
chunk = response.read1()
|
||
|
assert digest.hexdigest() == checksum.lower(), "expected {}, actual {}".format(checksum.lower(), digest.hexdigest())
|
||
|
os.replace(UNVERIFIED_DOWNLOAD_NAME, archive_file)
|
||
|
return f
|
||
|
except urllib.error.HTTPError as e:
|
||
|
print(e, e.filename, file=sys.stderr)
|
||
|
sys.exit(1)
|
||
|
|
||
|
|
||
|
def main() -> None:
|
||
|
parser = build_argument_parser()
|
||
|
args = parser.parse_args()
|
||
|
os.makedirs(os.path.abspath(args.output_dir), exist_ok=True)
|
||
|
os.chdir(args.output_dir)
|
||
|
|
||
|
archive_file = os.path.basename(args.url)
|
||
|
download_if_needed(archive_file, args.url, args.checksum)
|
||
|
|
||
|
|
||
|
main()
|