Skip to content

Commit ad0dd91

Browse files
committed
handle platform negotiation
1 parent 4853d79 commit ad0dd91

File tree

1 file changed

+60
-8
lines changed

1 file changed

+60
-8
lines changed

src/dotnet-install.py

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import json
55
import requests
66
import hashlib
7+
import platform
8+
from dataclasses import dataclass
9+
from typing import Optional
710

811
class Channel:
912
def __init__(self, kind: str) -> None:
@@ -35,6 +38,45 @@ def __str__(self) -> str:
3538
return self.channel_version
3639
return f"{self.channel_version}.{self.feature_band.replace('0', 'x')}"
3740

41+
# TODO: platform.system() doesn't handle musl - need separate detection
42+
def compute_platform_part(platform: str) -> str:
43+
lower = platform.lower()
44+
match lower:
45+
case "osx" | "freebsd" | "rhel.6" | "linux-musl" | "linux":
46+
return lower
47+
case "macos":
48+
return "osx"
49+
case "win" | "windows":
50+
return "win"
51+
52+
def compute_arch_part(architecture: str) -> str:
53+
match architecture:
54+
case "arm64" | "aarch64":
55+
return "arm64"
56+
case "s390x" | "ppc64le" | "loongarch64":
57+
return architecture
58+
case _:
59+
return "x64"
60+
61+
def compute_runtime_identifier(platform: str, architecture: str) -> str:
62+
platform_part = compute_platform_part(platform)
63+
arch_part = compute_arch_part(architecture)
64+
if platform_part is None or arch_part is None:
65+
raise Exception(f"Unable to compute runtime identifier for {platform}/{architecture}")
66+
return f"{platform_part}-{arch_part}"
67+
68+
69+
@dataclass
70+
class InstallRequest:
71+
channel: Channel
72+
runtime: Optional[str]
73+
architecture: str
74+
os: str
75+
76+
@property
77+
def rid(self):
78+
return compute_runtime_identifier(self.os, self.architecture)
79+
3880
def download_releases_index() -> json:
3981
return requests.get("https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json", ).json()
4082

@@ -96,32 +138,42 @@ def download_file(url: str, hash: str):
96138

97139
return local_filename
98140

99-
def install_sdk(desired_channel: Channel, runtime_identifier: str):
141+
142+
143+
def install_sdk(request: InstallRequest):
100144
index = download_releases_index()
101145
if index is None:
102146
raise Exception("Releases index could not be downloaded")
103147
channels: list = index["releases-index"]
104-
channel_information = pick_best_channel(channels, desired_channel)
148+
channel_information = pick_best_channel(channels, request.channel)
105149
channel_version = channel_information["channel-version"]
106150
if channel_information is None:
107151
raise Exception(f"No matching channel could be found for desired channel '{channel_version}'")
108152
channel_releases = download_releases_for_channel(channel_information)
109153
if channel_releases is None:
110154
raise Exception(f"No releases found for channel '{channel_version}'")
111-
release_information = pick_best_release(channel_releases, desired_channel)
155+
release_information = pick_best_release(channel_releases, request.channel)
112156
if release_information is None:
113157
raise Exception(f"No best release found in channel '{channel_version}'")
114158
release_version = release_information['release-version']
115-
sdk_information = pick_matching_sdk(release_information['sdks'], desired_channel)
159+
sdk_information = pick_matching_sdk(release_information['sdks'], request.channel)
116160
if sdk_information is None:
117161
raise Exception(f"No matching SDK found in release '{release_version}'")
118-
file_to_download = pick_file_to_download(sdk_information['files'], runtime_identifier)
162+
file_to_download = pick_file_to_download(sdk_information['files'], request.rid)
119163
if file_to_download is None:
120-
raise Exception(f"No matching file for runtime identifier {runtime_identifier} found in release '{release_version}'")
164+
raise Exception(f"No matching file for runtime identifier {request.rid} found in release '{release_version}'")
121165
download_file(file_to_download['url'], file_to_download['hash'])
122166

123167
if __name__ == "__main__":
124168
parser = argparse.ArgumentParser("dotnet-install.py", description="%(prog)s ia a simple command line interface for obtaining the .NET SDK and Runtime", add_help=True, exit_on_error=True)
125169
parser.add_argument("--channel", "-c", type=Channel, help="The release grouping to download from. Can have a variety of formats: sts, lts, two-part version number (8.0) or three-part version number in major.minor.patchxx format (8.0.2xx)")
126-
args = parser.parse_args()
127-
install_sdk(args.channel, 'win-x64')
170+
parser.add_argument("--runtime", help="Installs a shared runtime only, without the SDK", choices=["dotnet", "aspnetcore"])
171+
parser.add_argument("--architecture", help="Architecture of the .NET binaries to be installed, defaults to the current system.", default=platform.machine())
172+
parser.add_argument("--os", help="Specifies the operating system to be used when selecting the installer", default=platform.system())
173+
try:
174+
args = parser.parse_args()
175+
request = InstallRequest(args.channel, args.runtime, args.architecture, args.os)
176+
install_sdk(request)
177+
except:
178+
parser.print_help()
179+
exit(1)

0 commit comments

Comments
 (0)