Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 4 additions & 1 deletion src/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ Installs Rust, common Rust utilities, and their required dependencies

## OS Support

This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
This Feature should work on recent versions of Debian/Ubuntu, RedHat Enterprise Linux, Fedora, Alma, RockyLinux
and Mariner distributions with the `apt`, `yum`, `dnf`, `microdnf` and `tdnf` package manager installed.
Alpine is not supported because the rustup-init binary requires glibc to run, but Alpine Linux does not include `glibc`
by default. Instead, it uses musl libc, which is not binary-compatible with glibc.

`bash` is required to execute the `install.sh` script.

Expand Down
2 changes: 1 addition & 1 deletion src/rust/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "rust",
"version": "1.3.3",
"version": "1.3.4",
"name": "Rust",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/rust",
"description": "Installs Rust, common Rust utilities, and their required dependencies",
Expand Down
243 changes: 218 additions & 25 deletions src/rust/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,79 @@ UPDATE_RUST="${UPDATE_RUST:-"false"}"

set -e

# Clean up
if [ "$(ls -1 /var/lib/apt/lists/ | wc -l)" -gt -1 ]; then
rm -rf /var/lib/apt/lists/*
# Detect the Linux distribution and package manager
DISTRO=""
DISTRO_FAMILY=""
PKG_MANAGER=""

# Bring in ID, ID_LIKE, VERSION_ID, VERSION_CODENAME
. /etc/os-release
# Get an adjusted ID independent of distro variants
if [ "${ID}" = "debian" ] || [ "${ID_LIKE}" = "debian" ]; then
ADJUSTED_ID="debian"
elif [ "${ID}" = "alpine" ]; then
ADJUSTED_ID="alpine"
elif [[ "${ID}" = "rhel" || "${ID}" = "fedora" || "${ID}" = "mariner" || "${ID_LIKE}" = *"rhel"* || "${ID_LIKE}" = *"fedora"* || "${ID_LIKE}" = *"mariner"* ]]; then
ADJUSTED_ID="rhel"
VERSION_CODENAME="${ID}${VERSION_ID}"
else
echo "Linux distro ${ID} not supported."
exit 1
fi

if [ "${ADJUSTED_ID}" = "rhel" ] && [ "${VERSION_CODENAME-}" = "centos7" ]; then
# As of 1 July 2024, mirrorlist.centos.org no longer exists.
# Update the repo files to reference vault.centos.org.
sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo
sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo
sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo
fi


# Detect package manager
if command -v apt-get >/dev/null 2>&1; then
PKG_MANAGER="apt"
elif command -v dnf >/dev/null 2>&1; then
PKG_MANAGER="dnf"
elif command -v yum >/dev/null 2>&1; then
PKG_MANAGER="yum"
elif command -v microdnf >/dev/null 2>&1; then
PKG_MANAGER="microdnf"
elif command -v tdnf >/dev/null 2>&1; then
PKG_MANAGER="tdnf"
else
echo "No supported package manager found. Supported: apt, dnf, yum, microdnf, tdnf"
exit 1
fi

echo "Detected package manager: $PKG_MANAGER"

# Clean up based on package manager
clean_package_cache() {
case "$PKG_MANAGER" in
apt)
if [ "$(ls -1 /var/lib/apt/lists/ 2>/dev/null | wc -l)" -gt 0 ]; then
rm -rf /var/lib/apt/lists/*
fi
;;
dnf|yum|microdnf)
if command -v dnf >/dev/null 2>&1; then
dnf clean all
elif command -v yum >/dev/null 2>&1; then
yum clean all
elif command -v microdnf >/dev/null 2>&1; then
microdnf clean all
fi
;;
tdnf)
tdnf clean all
;;
esac
}

# Initial cleanup
clean_package_cache

if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
Expand Down Expand Up @@ -106,48 +174,174 @@ check_nightly_version_formatting() {

updaterc() {
if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/bash.bashrc
echo "Updating shell configuration files..."
local bashrc_file="/etc/bash.bashrc"

# Different distributions use different bashrc locations
if [ ! -f "$bashrc_file" ]; then
if [ -f "/etc/bashrc" ]; then
bashrc_file="/etc/bashrc"
elif [ -f "/etc/bash/bashrc" ]; then
bashrc_file="/etc/bash/bashrc"
fi
fi

if [ -f "$bashrc_file" ] && [[ "$(cat "$bashrc_file")" != *"$1"* ]]; then
echo -e "$1" >> "$bashrc_file"
fi

if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
fi
}

apt_get_update()
{
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
# Package update functions
pkg_mgr_update() {
case "$PKG_MANAGER" in
apt)
if [ "$(find /var/lib/apt/lists/* 2>/dev/null | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
;;
dnf)
dnf check-update || true
;;
yum)
yum check-update || true
;;
microdnf)
# microdnf doesn't have check-update
true
;;
tdnf)
tdnf makecache || true
;;
esac
}

# Check if package is installed
is_package_installed() {
local package=$1
case "$PKG_MANAGER" in
apt)
dpkg -s "$package" >/dev/null 2>&1
;;
dnf|yum|microdnf|tdnf)
rpm -q "$package" >/dev/null 2>&1
;;
esac
}

# Checks if packages are installed and installs them if not
# Unified package checking and installation function
check_packages() {
if ! dpkg -s "$@" >/dev/null 2>&1; then
apt_get_update
apt-get -y install --no-install-recommends "$@"
local packages=("$@")
local missing_packages=()

# Check if curl-minimal is installed and swap it with curl
if is_package_installed "curl-minimal"; then
echo "curl-minimal is installed. Swapping it with curl..."
case "$PKG_MANAGER" in
dnf|yum|microdnf)
${PKG_MANAGER} swap curl-minimal curl -y
;;
tdnf)
tdnf remove -y curl-minimal
tdnf install -y curl
;;
*)
echo "Package manager does not support swapping curl-minimal with curl. Please handle this manually."
;;
esac
fi

# Map package names based on distribution
for i in "${!packages[@]}"; do
case "$PKG_MANAGER" in
dnf|yum|microdnf|tdnf)
case "${packages[$i]}" in
"libc6-dev") packages[$i]="glibc-devel" ;;
"python3-minimal") packages[$i]="python3" ;;
"libpython3.*") packages[$i]="python3-devel" ;;
"gnupg2") packages[$i]="gnupg" ;;
esac
;;
esac
done

# Check which packages are missing
for package in "${packages[@]}"; do
if [ -n "$package" ] && ! is_package_installed "$package"; then
missing_packages+=("$package")
fi
done

# Install missing packages
if [ ${#missing_packages[@]} -gt 0 ]; then
pkg_mgr_update
case "$PKG_MANAGER" in
apt)
apt-get -y install --no-install-recommends "${missing_packages[@]}"
;;
dnf)
dnf install -y "${missing_packages[@]}"
;;
yum)
yum install -y "${missing_packages[@]}"
;;
microdnf)
microdnf install -y "${missing_packages[@]}"
;;
tdnf)
tdnf install -y "${missing_packages[@]}"
;;
esac
fi
}

export DEBIAN_FRONTEND=noninteractive

# Install curl, lldb, python3-minimal,libpython and rust dependencies if missing
if ! dpkg -s curl ca-certificates gnupg2 lldb python3-minimal gcc libc6-dev > /dev/null 2>&1; then
apt_get_update
apt-get -y install --no-install-recommends curl ca-certificates gcc libc6-dev
apt-get -y install lldb python3-minimal libpython3.?
echo "Installing required dependencies..."
check_packages curl ca-certificates gcc libc6-dev gnupg2 git

# Install optional dependencies (continue if they fail)
case "$PKG_MANAGER" in
apt)
check_packages lldb python3-minimal libpython3.? || true
;;
dnf|yum|microdnf)
check_packages lldb python3 python3-devel || true
;;
tdnf)
check_packages python3 python3-devel || true
# LLDB might not be available in Photon/Mariner
;;
esac

# Get architecture
if command -v dpkg >/dev/null 2>&1; then
architecture="$(dpkg --print-architecture)"
else
architecture="$(uname -m)"
# Convert common architectures to Debian equivalents
case ${architecture} in
x86_64)
architecture="amd64"
;;
aarch64)
architecture="arm64"
;;
esac
fi

architecture="$(dpkg --print-architecture)"
download_architecture="${architecture}"
case ${download_architecture} in
amd64)
amd64|x86_64)
download_architecture="x86_64"
;;
arm64)
arm64|aarch64)
download_architecture="aarch64"
;;
*) echo "(!) Architecture ${architecture} not supported."
Expand Down Expand Up @@ -225,7 +419,6 @@ EOF
chmod -R g+r+w "${RUSTUP_HOME}" "${CARGO_HOME}"

# Clean up
rm -rf /var/lib/apt/lists/*
clean_package_cache

echo "Done!"

16 changes: 16 additions & 0 deletions test/rust/rust_with_almalinux_8.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "cargo version" cargo --version
check "rustc version" rustc --version
check "correct rust version" rustup target list | grep aarch64-unknown-linux-gnu


# Report result
reportResults

16 changes: 16 additions & 0 deletions test/rust/rust_with_almalinux_9.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "cargo version" cargo --version
check "rustc version" rustc --version
check "correct rust version" rustup target list | grep aarch64-unknown-linux-gnu


# Report result
reportResults

16 changes: 16 additions & 0 deletions test/rust/rust_with_centos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "cargo version" cargo --version
check "rustc version" rustc --version
check "correct rust version" rustup target list | grep aarch64-unknown-linux-gnu


# Report result
reportResults

16 changes: 16 additions & 0 deletions test/rust/rust_with_fedora.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "cargo version" cargo --version
check "rustc version" rustc --version
check "correct rust version" rustup target list | grep aarch64-unknown-linux-gnu


# Report result
reportResults

16 changes: 16 additions & 0 deletions test/rust/rust_with_mariner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "cargo version" cargo --version
check "rustc version" rustc --version
check "correct rust version" rustup target list | grep aarch64-unknown-linux-gnu


# Report result
reportResults

Loading