master
py 101 lines 2.77 KB
Raw
1 #!/usr/bin/env python
2
3 '''Fetch the MSYS2 installer.'''
4
5 from __future__ import annotations
6
7 import hashlib
8 import json
9 import shutil
10 import sys
11
12 from pathlib import Path
13 from tempfile import TemporaryDirectory
14 from typing import Final
15 from urllib.request import Request, urlopen
16
17 REPO: Final = 'msys2/msys2-installer'
18
19
20 def get_latest_release() -> tuple[str, str]:
21 '''Get the latest release for the repo.'''
22 REQUEST: Final = Request(
23 url=f'https://api.github.com/repos/{REPO}/releases',
24 headers={
25 'Accept': 'application/vnd.github+json',
26 'X-GitHub-API-Version': '2022-11-28',
27 },
28 method='GET',
29 )
30
31 print('>>> Fetching release list')
32
33 with urlopen(REQUEST, timeout=15) as response:
34 if response.status != 200:
35 print(f'!!! Failed to fetch release list, status={response.status}')
36 sys.exit(1)
37
38 data = json.load(response)
39
40 data = list(filter(lambda x: x['name'] != 'Nightly Installer Build', data))
41
42 name = data[0]['name']
43 version = data[0]['tag_name'].replace('-', '')
44
45 return name, version
46
47
48 def fetch_release_asset(tmpdir: Path, name: str, file: str) -> Path:
49 '''Fetch a specific release asset.'''
50 REQUEST: Final = Request(
51 url=f'https://github.com/{REPO}/releases/download/{name}/{file}',
52 method='GET',
53 )
54 TARGET: Final = tmpdir / file
55
56 print(f'>>> Downloading {file}')
57
58 with urlopen(REQUEST, timeout=15) as response:
59 if response.status != 200:
60 print(f'!!! Failed to fetch {file}, status={response.status}')
61 sys.exit(1)
62
63 TARGET.write_bytes(response.read())
64
65 return TARGET
66
67
68 def main() -> None:
69 '''Core program logic.'''
70 if len(sys.argv) != 2:
71 print(f'{__file__} must be run with exactly one argument.')
72
73 target = Path(sys.argv[1])
74 tmp_target = target.with_name(f'.{target.name}.tmp')
75
76 name, version = get_latest_release()
77
78 with TemporaryDirectory() as tmpdir:
79 tmppath = Path(tmpdir)
80
81 installer = fetch_release_asset(tmppath, name, f'msys2-base-x86_64-{version}.tar.zst')
82 checksums = fetch_release_asset(tmppath, name, f'msys2-base-x86_64-{version}.tar.zst.sha256')
83
84 print('>>> Verifying SHA256 checksum')
85 expected_checksum = checksums.read_text().partition(' ')[0].casefold()
86 actual_checksum = hashlib.sha256(installer.read_bytes()).hexdigest().casefold()
87
88 if expected_checksum != actual_checksum:
89 print('!!! Checksum mismatch')
90 print(f'!!! Expected: {expected_checksum}')
91 print(f'!!! Actual: {actual_checksum}')
92 sys.exit(1)
93
94 print(f'>>> Copying to {target}')
95
96 shutil.copy(installer, tmp_target)
97 tmp_target.replace(target)
98
99
100 if __name__ == '__main__':
101 main()