-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathcollect_executables.py
executable file
·226 lines (189 loc) · 7.4 KB
/
collect_executables.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
"""Get the link to download Fx or Geckodriver, for any supported platform.
Use -g to get geckodriver, otherwise you will get Fx. Use -n to just get the Fx version number.
Set env var FX_CHANNEL to get non-beta, blank string for Release.
Set env var FX_LOCALE to get a different locale build.
Set env var FX_PLATFORM to get a platform other than current system."""
import logging
from os import environ
from platform import uname
from sys import argv, exit
from time import sleep
import requests
from bs4 import BeautifulSoup
GECKO_API_URL = "https://api.github.com/repos/mozilla/geckodriver/releases/latest"
BACKSTOP = "135.0b9"
NUMBER_ONLY = False
def get_fx_platform():
u = uname()
_system = environ.get("FX_PLATFORM") or u.system
if _system == "Darwin":
return "mac"
if _system == "Linux":
# ARM specifications in uname().machine don't have 32/64
if "64" in u.machine:
return "linux-x86_64"
elif "arm" in u.machine.lower():
return "linux-aarch64"
return "linux-i686"
if _system == "Windows":
if "arm" in u.machine.lower():
return "win64-aarch64"
elif "64" in u.machine:
return "win64"
return "win32"
def get_fx_executable_extension():
u = uname()
_system = environ.get("FX_PLATFORM") or u.system
if _system == "Darwin":
return "dmg"
if _system == "Linux":
return "xz"
if _system == "Windows":
return "exe"
def get_gd_platform():
u = uname()
_system = environ.get("FX_PLATFORM") or u.system
if _system == "Darwin":
return "macos"
if _system == "Linux":
if u.machine == "AMD64":
return "linux-aarch64"
if "64" in u.machine:
return "linux64"
return "linux32"
if _system == "Windows":
if u.machine == "AMD64" and not environ.get("GITHUB_ACTIONS"):
return "win-aarch64"
if "64" in u.machine:
return "win64"
return "win32"
if "-g" in argv:
gecko_rs_obj = requests.get(GECKO_API_URL).json()
# In mac, sometimes this request fails to produce a link
for _ in range(4):
if gecko_rs_obj:
break
sleep(2)
gecko_rs_obj = requests.get(GECKO_API_URL).json()
# If we failed, just dump any old link, maybe update this on new gecko release
if not gecko_rs_obj.get("assets"):
gd_platform = get_gd_platform()
ext = "zip" if "win" in gd_platform else "tar.gz"
print(
f"https://github.com/mozilla/geckodriver/releases/download/v0.35.0/geckodriver-v0.35.0-{gd_platform}.{ext}"
)
exit()
urls = [
a.get("browser_download_url")
for a in gecko_rs_obj.get("assets")
if not a.get("browser_download_url").endswith(".asc")
]
gecko_download_url = [u for u in urls if get_gd_platform() in u][0]
print(gecko_download_url)
else:
if "-n" in argv:
NUMBER_ONLY = True
channel = environ.get("FX_CHANNEL")
# if channel doesn't exist use beta, if blank leave blank (for Release)
# ...otherwise prepend hyphen
if channel is None:
channel = "-beta"
elif channel:
channel = f"-{channel.lower()}"
language = environ.get("FX_LOCALE")
if not language:
language = "en-US"
if channel == "-devedition":
# Devedition has special requirements as it's testing a release
this_devedition = BACKSTOP
fx_download_dir_url = (
"https://archive.mozilla.org/pub/devedition/releases/135.0b5/"
)
while True:
(major, _) = this_devedition.split(".")
major = int(major)
this_devedition = f"{major + 1}.0b5"
next_candidate = f"https://archive.mozilla.org/pub/devedition/releases/{this_devedition}/"
rs = requests.get(next_candidate)
if rs.status_code > 399:
break
fx_download_dir_url = next_candidate
devedition_version = fx_download_dir_url.split("/")[-2]
fx_download_dir_url = f"{fx_download_dir_url}{get_fx_platform()}/{language}/"
else:
# Anything but devedition
candidate_exists = True
this_beta = BACKSTOP
while candidate_exists:
(major, minor_beta) = this_beta.split(".")
(minor, beta) = minor_beta.split("b")
major = int(major)
minor = int(minor)
beta = int(beta)
next_major = f"{major + 1}.0b1"
fx_download_dir_url = f"https://archive.mozilla.org/pub/firefox/candidates/{next_major}-candidates/build1/"
rs = requests.get(fx_download_dir_url)
if rs.status_code < 300:
latest_beta_ver = next_major
this_beta = next_major
continue
next_minor = f"{major}.{minor + 1}b1"
fx_download_dir_url = f"https://archive.mozilla.org/pub/firefox/candidates/{next_minor}-candidates/build1/"
rs = requests.get(fx_download_dir_url)
if rs.status_code < 300:
latest_beta_ver = next_minor
this_beta = next_minor
continue
next_beta = f"{major}.{minor}b{beta + 1}"
fx_download_dir_url = f"https://archive.mozilla.org/pub/firefox/candidates/{next_beta}-candidates/build1/"
rs = requests.get(fx_download_dir_url)
if rs.status_code < 300:
latest_beta_ver = next_beta
this_beta = next_beta
continue
candidate_exists = False
status = 200
build = 0
while status < 400 and build < 20:
build += 1
fx_download_dir_url = f"https://archive.mozilla.org/pub/firefox/candidates/{latest_beta_ver}-candidates/build{build}/"
# Fetch the page
response = requests.get(fx_download_dir_url)
status = response.status_code
# Correct build is the last one that didn't 404
build -= 1
fx_download_dir_url = f"https://archive.mozilla.org/pub/firefox/candidates/{latest_beta_ver}-candidates/build{build}/{get_fx_platform()}/{language}/"
response = requests.get(fx_download_dir_url)
status = response.status_code
response_text = None
for _ in range(3):
if status < 300:
response_text = response.text
else:
sleep(3)
response = requests.get(fx_download_dir_url)
status = response.status_code
logging.warning(f"Collecting executable at {fx_download_dir_url}")
if response_text is None:
exit(f"Could not find build at {fx_download_dir_url}.")
# Parse the HTML content
soup = BeautifulSoup(response_text, "html.parser")
executable_name = ""
# Extract the text of each line
for line in soup.find_all("a"):
line_text = line.getText().split(".")
if not line_text[0]:
continue
# Get the executable name
if line_text[-1] == get_fx_executable_extension():
executable_name = line.getText().replace(" ", "%20")
fx_download_executable_url = rf"{fx_download_dir_url}{executable_name}"
if NUMBER_ONLY:
if channel == "-devedition":
print(devedition_version)
else:
number_cand = fx_download_dir_url.split("/")[6]
number = number_cand.split("-")[0]
print(f"{number}-build{build}")
else:
print(fx_download_executable_url)