Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated MSYS2 API endpoints to expose more types of installers and archives for download #514

Merged
merged 4 commits into from
Mar 27, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 23 additions & 46 deletions src/murfey/server/api/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@

# Variables used by the MSYS2 functions below
msys2_url = "https://repo.msys2.org"
msys2_setup_file = "msys2-x86_64-latest.exe"
msys2_file_ext = (".exe", ".sig", ".tar.xz", "tar.zst")
valid_envs = (
# Tuple of systems and supported libraries/compilers/architectures within
(
Expand Down Expand Up @@ -289,15 +289,25 @@
)


@msys2.get("/setup-x86_64.exe", response_class=Response)
def get_msys2_setup():
@msys2.get("/distrib/{setup_file}", response_class=Response)
def get_msys2_setup(setup_file: str):
"""
Obtain and pass through an MSYS2 installer from an official source.
This is used during client bootstrapping, and can download and install the
MSYS2 distribution that then remains on the client machines.
"""

installer = requests.get(f"{msys2_url}/distrib/{msys2_setup_file}")
# Validate characters in sent path
if not bool(re.fullmatch(r"^[\w\.\-]+$", setup_file)):
raise ValueError("Unallowed characters present in requested setup file")

Check warning on line 302 in src/murfey/server/api/bootstrap.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/bootstrap.py#L302

Added line #L302 was not covered by tests

# Allow only '.exe', 'tar.xz', 'tar.zst', or '.sig' files
if not setup_file.startswith("msys2") and not any(
setup_file.endswith(ext) for ext in (msys2_file_ext)
):
raise ValueError(f"{setup_file!r} is not a valid executable")

Check warning on line 308 in src/murfey/server/api/bootstrap.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/bootstrap.py#L308

Added line #L308 was not covered by tests

installer = requests.get(f"{msys2_url}/distrib/{setup_file}")

Check warning on line 310 in src/murfey/server/api/bootstrap.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/bootstrap.py#L310

Added line #L310 was not covered by tests
return Response(
content=installer.content,
media_type=installer.headers.get("Content-Type"),
Expand All @@ -314,24 +324,6 @@
from the main MSYS2 repository.
"""

def get_msys2_setup_html():
"""
Returns the HTML line for the latest MSYS2 installer for Windows from an official
source.
"""
url = f"{msys2_url}/distrib"
index = requests.get(url)
content: bytes = index.content
content_text: str = content.decode("latin1")

for line in content_text.splitlines():
if line.startswith("<a href="):
if f'"{msys2_setup_file}"' in line:
return line
else:
pass
return None

def _rewrite_url(match):
"""
Use regular expression matching to rewrite the package URLs and point them
Expand All @@ -358,35 +350,15 @@
content_text_list = []
for line in content_text.splitlines():
if line.startswith("<a href"):
# Mirror only lines related to MSYS2 environments
if any(env[0] in line for env in valid_envs):
# Mirror only lines related to MSYS2 environments or the distribution folder
if any(env[0] in line for env in valid_envs) or "distrib" in line:
line_new = re.sub(
'^<a href="([^">]*)">([^<]*)</a>', # Regex search criteria
_rewrite_url, # Function to apply search criteria to
line,
)
content_text_list.append(line_new)

# Replace the "distrib/" hyperlink with one to the setup file
elif "distrib" in line:
# Set up URL to be requested on the Murfey server
mirror_file_name = "setup-x86_64.exe"
setup_url = f"{base_path}/{mirror_file_name}"

# Get request from the "distrib" page and rewrite it
setup_html = get_msys2_setup_html()
if setup_html is None:
# Skip showing the setup file link if it fails to find it
continue

line_new = " ".join( # Adjust spaces to align columns
re.sub(
'^<a href="([^">]*)">([^"<]*)</a>',
f'<a href="{setup_url}">{mirror_file_name}</a>',
setup_html,
).split(" ", 1)
)
content_text_list.append(line_new)
# Other URLs don't need to be mirrored
else:
pass
Expand Down Expand Up @@ -430,8 +402,8 @@
path = request.url.path.strip("/")
base_path = f"{base_url}/{path}"

# Validate provided system
if any(system in env[0] for env in valid_envs) is False:
# Validate provided system; use this endpoint to display 'distrib' folder too
if not (any(system in env[0] for env in valid_envs) or system == "distrib"):
raise ValueError(f"{system!r} is not a valid msys2 environment")

# Construct URL to main MSYS repo and get response
Expand All @@ -444,6 +416,11 @@
content_text_list = []
for line in content_text.splitlines():
if line.startswith("<a href="):
# Skip non-executable files when querying 'distrib' repo
if system == "distrib":
if not any(ext in line for ext in msys2_file_ext):
continue

Check warning on line 422 in src/murfey/server/api/bootstrap.py

View check run for this annotation

Codecov / codecov/patch

src/murfey/server/api/bootstrap.py#L422

Added line #L422 was not covered by tests

# Rewrite URL to point explicitly to current server
line_new = re.sub(
'^<a href="([^">]*)">([^<]*)</a>', # Regex search criteria
Expand Down