Skip to content
Merged
Show file tree
Hide file tree
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
7 changes: 6 additions & 1 deletion src/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ 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.


**Note:** 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.4.0",
"name": "Rust",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/rust",
"description": "Installs Rust, common Rust utilities, and their required dependencies",
Expand Down
241 changes: 216 additions & 25 deletions src/rust/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,77 @@ 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
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 +172,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 +417,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