Skip to content

Commit b50b562

Browse files
selstaMalineroauthjpk68
committed
Migrate to Qt6
Co-authored-by: malinero <malinero@protonmail.com> Co-authored-by: auth <auth@waifu.club> Co-authored-by: jpk68 <jpk68@tutanota.com>
1 parent 26b6902 commit b50b562

149 files changed

Lines changed: 2402 additions & 2453 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
*
2+
!.github/
3+
!.github/qt_helper.py

.github/qt_helper.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import fnmatch
4+
import hashlib
5+
import pathlib
6+
import subprocess
7+
import urllib.parse
8+
import urllib.request
9+
import xml.etree.ElementTree as ET
10+
11+
MAX_TRIES = 32
12+
MAX_XML_SIZE = 1024 * 1024 * 1024
13+
MIRROR = 'download.qt.io'
14+
15+
16+
def fetch_links_to_archives(host_os, target, major, minor, patch, toolchain, packages):
17+
qt_dir = f'qt{major}_{major}{minor}{patch}'
18+
base_url = f'https://{MIRROR}/online/qtsdkrepository/{host_os}/{target}/{qt_dir}/{qt_dir}'
19+
url = f'{base_url}/Updates.xml'
20+
print('fetching', url, flush=True)
21+
22+
for _ in range(MAX_TRIES):
23+
try:
24+
with urllib.request.urlopen(url, timeout=30) as response:
25+
resp = response.read(MAX_XML_SIZE + 1)
26+
if len(resp) > MAX_XML_SIZE:
27+
raise RuntimeError(f'{url} exceeds the {MAX_XML_SIZE}-byte size limit')
28+
update_xml = ET.fromstring(resp)
29+
break
30+
except KeyboardInterrupt:
31+
raise
32+
except Exception as e:
33+
print('error', e, flush=True)
34+
else:
35+
raise RuntimeError(f'Failed to fetch {url} after {MAX_TRIES} attempts')
36+
37+
package_prefix = f'qt.qt{major}.{major}{minor}{patch}'
38+
package_names = {
39+
f'{package_prefix}.{package}.{toolchain}' if package else f'{package_prefix}.{toolchain}'
40+
for package in packages
41+
}
42+
43+
found_packages = set()
44+
for pkg in update_xml.findall('./PackageUpdate'):
45+
name = pkg.find('.//Name')
46+
if name is None:
47+
continue
48+
if name.text not in package_names:
49+
continue
50+
found_packages.add(name.text)
51+
version = pkg.find('.//Version')
52+
if version is None:
53+
continue
54+
archives = pkg.find('.//DownloadableArchives')
55+
if archives is None or archives.text is None:
56+
continue
57+
for archive in archives.text.split(', '):
58+
archive = archive.strip()
59+
if not archive:
60+
continue
61+
url = f'{base_url}/{name.text}/{version.text}{archive}'
62+
file_name = pathlib.Path(urllib.parse.urlparse(url).path).name
63+
yield {'name': file_name, 'url': url, 'archive': archive}
64+
65+
missing_packages = package_names - found_packages
66+
if missing_packages:
67+
raise RuntimeError(f'Qt packages not found: {", ".join(sorted(missing_packages))}')
68+
69+
70+
def download(links):
71+
metalink = ET.Element('metalink', xmlns='urn:ietf:params:xml:ns:metalink')
72+
for link in links:
73+
file = ET.SubElement(metalink, 'file', name=link['name'])
74+
ET.SubElement(file, 'url').text = link['url']
75+
76+
data = ET.tostring(metalink, encoding='UTF-8', xml_declaration=True)
77+
78+
for _ in range(MAX_TRIES):
79+
result = subprocess.run([
80+
'aria2c',
81+
'--connect-timeout=8',
82+
'--console-log-level=warn',
83+
'--continue',
84+
'--follow-metalink=mem',
85+
'--max-concurrent-downloads=100',
86+
'--max-connection-per-server=16',
87+
'--max-file-not-found=100',
88+
'--max-tries=100',
89+
'--min-split-size=1MB',
90+
'--retry-wait=1',
91+
'--split=100',
92+
'--summary-interval=0',
93+
'--timeout=8',
94+
'--user-agent=',
95+
'--metalink-file=-',
96+
], input=data, check=False)
97+
if result.returncode == 0:
98+
return True
99+
100+
return False
101+
102+
103+
def file_hash(path):
104+
digest = hashlib.sha256()
105+
with open(path, 'rb') as file:
106+
for chunk in iter(lambda: file.read(1024 * 1024), b''):
107+
digest.update(chunk)
108+
return digest.digest()
109+
110+
111+
def calc_hash_sum(files):
112+
digest = hashlib.sha256()
113+
for path in files:
114+
digest.update(file_hash(path))
115+
return digest.hexdigest()
116+
117+
118+
def extract_archives(files, out='.', targets=()):
119+
for path in files:
120+
print('extracting', path, flush=True)
121+
result = subprocess.run(
122+
['bsdtar', '-xf', path, '-C', out, *targets],
123+
stdout=subprocess.DEVNULL,
124+
check=False,
125+
)
126+
if result.returncode != 0:
127+
return False
128+
return True
129+
130+
131+
def main():
132+
parser = argparse.ArgumentParser()
133+
parser.add_argument('os')
134+
parser.add_argument('target')
135+
parser.add_argument('version')
136+
parser.add_argument('toolchain')
137+
parser.add_argument('expect')
138+
parser.add_argument('--add-package', action='append', default=[],
139+
help='additional package below qt.qt<major>.<version>, such as addons.qtshadertools')
140+
parser.add_argument('--archive', action='append', default=[],
141+
help='fnmatch pattern selecting archives from the requested packages')
142+
args = parser.parse_args()
143+
144+
host_os, target, version, toolchain, expect = (
145+
args.os, args.target, args.version, args.toolchain, args.expect
146+
)
147+
major, minor, patch = version.split('.')
148+
149+
packages = [''] + args.add_package
150+
links = list(fetch_links_to_archives(
151+
host_os, target, major, minor, patch, toolchain, packages
152+
))
153+
if args.archive:
154+
links = [
155+
link for link in links
156+
if any(fnmatch.fnmatch(link['archive'], pattern) for pattern in args.archive)
157+
]
158+
if not links:
159+
raise RuntimeError('No Qt archives matched')
160+
print(*(link['url'] for link in links), sep='\n', flush=True)
161+
162+
if not download(links):
163+
raise RuntimeError('Failed to download Qt archives')
164+
165+
archive_names = [link['name'] for link in links]
166+
result = calc_hash_sum(archive_names)
167+
print('result', result, 'expect', expect, flush=True)
168+
if expect != '-' and result != expect:
169+
raise RuntimeError(f'Qt archive hash mismatch: expected {expect}, got {result}')
170+
171+
if not extract_archives(archive_names):
172+
raise RuntimeError('Failed to extract Qt archives')
173+
174+
for archive_name in archive_names:
175+
pathlib.Path(archive_name).unlink()
176+
177+
178+
if __name__ == '__main__':
179+
main()

0 commit comments

Comments
 (0)