Skip to content

Instantly share code, notes, and snippets.

@FalconNL93
Created June 6, 2025 06:54
Show Gist options
  • Save FalconNL93/7b243e2daeac66c8edc9755114a94b76 to your computer and use it in GitHub Desktop.
Save FalconNL93/7b243e2daeac66c8edc9755114a94b76 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -e
# Constants
DOTNET_DIR="$HOME/.dotnet"
INSTALL_SCRIPT="$HOME/dotnet-install.sh"
DEPENDENCIES_MARKER="$HOME/.dotnet_deps_installed"
# Ensure the "dialog" package is installed
ensure_dialog_installed() {
if ! command -v dialog &> /dev/null; then
echo "The 'dialog' package is not installed. Installing it now..."
if [ -f /etc/os-release ]; then
. /etc/os-release
if [[ "$ID" =~ ^(ubuntu|debian)$ || "$ID_LIKE" == *"debian"* || "$ID_LIKE" == *"ubuntu"* ]]; then
sudo apt update && sudo apt install -y dialog
elif [[ "$ID" =~ ^(fedora|rhel|centos)$ || "$ID_LIKE" == *"rhel"* || "$ID_LIKE" == *"fedora"* ]]; then
sudo dnf install -y dialog
elif [[ "$ID" == "arch" || "$ID_LIKE" == *"arch"* ]]; then
sudo pacman -Sy --noconfirm dialog
else
echo "Unsupported OS. Please install 'dialog' manually."
exit 1
fi
else
echo "Unable to detect OS. Please install 'dialog' manually."
exit 1
fi
fi
}
# Install required dependencies
install_dependencies() {
[ -f "$DEPENDENCIES_MARKER" ] && return
echo "Installing required system dependencies..."
if [ -f /etc/os-release ]; then
. /etc/os-release
if [[ "$ID" =~ ^(ubuntu|debian)$ || "$ID_LIKE" == *"debian"* || "$ID_LIKE" == *"ubuntu"* ]]; then
sudo apt update && sudo apt install -y --no-install-recommends \
libc6 libgcc1 libgssapi-krb5-2 libicu70 libssl3 libstdc++6 \
zlib1g libcurl4 libkrb5-3 libunwind8
elif [[ "$ID" =~ ^(fedora|rhel|centos)$ || "$ID_LIKE" == *"rhel"* || "$ID_LIKE" == *"fedora"* ]]; then
sudo dnf install -y \
glibc libgcc krb5-libs libicu openssl libstdc++ zlib libcurl libunwind
elif [[ "$ID" == "arch" || "$ID_LIKE" == *"arch"* ]]; then
sudo pacman -Sy --noconfirm \
glibc gcc krb5 icu openssl libstdc++ zlib curl libunwind
else
echo "Unsupported OS. Please install dependencies manually."
exit 1
fi
else
echo "Unable to detect OS. Please install dependencies manually."
exit 1
fi
touch "$DEPENDENCIES_MARKER"
}
# Retrieve all major .NET SDK versions dynamically, including preview versions
get_dotnet_versions() {
curl -s https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json \
| grep -oP '"channel-version":\s*"\K[0-9]+\.[0-9]+(\.[0-9]+(-[a-zA-Z0-9.]+)?)?' \
| sort -uV
}
# Display the latest release per channel from releases-index.json
show_versions() {
echo "Fetching the latest .NET SDK releases per channel..."
curl -s https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/releases-index.json | \
jq -r '."releases-index"[] | "\(.["channel-version"]): \(.["latest-release"])"'
exit 0
}
# Select .NET SDK versions to install
select_versions() {
if [ "$UPDATE_ALL" = true ]; then return; fi
echo "Select the .NET SDK versions you want to install:"
echo "(Use arrow keys and space to select, enter to confirm.)"
# Get already installed full versions
INSTALLED=$(ls "$DOTNET_DIR/sdk" | awk -F. '{print $1"."$2}' | sort -u)
# Build dialog checklist options: version "on"/"off"
OPTIONS=()
for version in "${VERSIONS[@]}"; do
if echo "$INSTALLED" | grep -qx "$version"; then
OPTIONS+=("$version" "$version" "on")
else
OPTIONS+=("$version" "$version" "off")
fi
done
TMPFILE=$(mktemp)
dialog --clear --no-tags --checklist "Select .NET SDK versions to install:" 20 60 10 \
"${OPTIONS[@]}" 2> "$TMPFILE"
if [ $? -ne 0 ]; then
echo "No versions selected. Exiting."
rm -f "$TMPFILE"
exit 1
fi
SELECTED=$(cat "$TMPFILE" | tr -d '"')
rm -f "$TMPFILE"
if [ -z "$SELECTED" ]; then
echo "No versions selected. Exiting."
exit 1
fi
SELECTED_VERSIONS=($SELECTED)
# Uninstall deselected versions
for full_version in $(ls "$DOTNET_DIR/sdk"); do
major_minor=$(echo "$full_version" | awk -F. '{print $1"."$2}')
if ! echo "${SELECTED_VERSIONS[@]}" | grep -qw "$major_minor"; then
echo "Uninstalling .NET SDK version $full_version..."
SDK_DIR="$DOTNET_DIR/sdk/$full_version"
if [ -d "$SDK_DIR" ]; then
rm -rf "$SDK_DIR"
echo "Removed $SDK_DIR"
else
echo "SDK version $full_version not found in $DOTNET_DIR/sdk"
fi
fi
done
}
# Download the dotnet-install.sh script
download_install_script() {
[ -f "$INSTALL_SCRIPT" ] && return
echo "Downloading dotnet-install.sh..."
curl -SL https://dot.net/v1/dotnet-install.sh -o "$INSTALL_SCRIPT"
chmod +x "$INSTALL_SCRIPT"
}
# Install or update selected .NET SDK versions
install_dotnet_sdks() {
mkdir -p "$DOTNET_DIR"
for version in "${SELECTED_VERSIONS[@]}"; do
echo "Installing or updating .NET SDK version $version..."
"$INSTALL_SCRIPT" --channel "$version" --install-dir "$DOTNET_DIR"
done
}
# Update PATH permanently
update_path() {
if ! grep -q 'DOTNET_ROOT' "$HOME/.bashrc" && ! grep -q 'DOTNET_ROOT' "$HOME/.zshrc"; then
echo "Updating shell configuration files..."
{
echo -e "\n# .NET SDK setup"
echo "export DOTNET_ROOT=\"$DOTNET_DIR\""
echo "export PATH=\"$DOTNET_DIR:\$HOME/.dotnet/tools:\$PATH\""
} >> "$HOME/.bashrc"
{
echo -e "\n# .NET SDK setup"
echo "export DOTNET_ROOT=\"$DOTNET_DIR\""
echo "export PATH=\"$DOTNET_DIR:\$HOME/.dotnet/tools:\$PATH\""
} >> "$HOME/.zshrc"
fi
# Ensure $HOME/.dotnet/tools is in PATH for the current session
if ! echo "$PATH" | grep -q "$HOME/.dotnet/tools"; then
export PATH="$HOME/.dotnet/tools:$PATH"
fi
}
# Main execution
if [[ "$1" == "versions" ]]; then
show_versions
fi
ensure_dialog_installed
VERSIONS=($(get_dotnet_versions))
SELECTED_VERSIONS=("${VERSIONS[@]}")
select_versions
install_dependencies
download_install_script
install_dotnet_sdks
update_path
echo -e "\nAll requested .NET SDKs have been installed or updated successfully!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment