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
30 changes: 30 additions & 0 deletions bin/install/rust.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash

# Rust installation script (bash version)
# Installs Rust toolchain using rustup if not already installed

# shellcheck disable=SC1091 # Don't follow sourced files

set -euo pipefail

# Load Rust utilities
source "${DOTFILES:-$HOME/Repos/ooloth/dotfiles}/lib/rust-utils.bash"

main() {
# Check if Rust is already installed
if rust_installed; then
echo "πŸ¦€ Rust is already installed"
return 0
fi

# Set up environment variables
setup_rust_environment

# Install Rust toolchain
install_rust_toolchain
}

# Only run main if script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
27 changes: 27 additions & 0 deletions lib/rust-utils.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash

# Rust installation utilities
# Provides functions for detecting and installing Rust toolchain

set -euo pipefail

# Check if Rust is already installed
rust_installed() {
command -v rustup &>/dev/null
}

# Set up Rust environment variables
setup_rust_environment() {
export CARGO_HOME="$HOME/.config/cargo"
export RUSTUP_HOME="$HOME/.config/rustup"
}

# Install Rust toolchain using rustup
install_rust_toolchain() {
echo "πŸ¦€ Installing Rust toolchain..."

# Download and run rustup installer
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

echo "πŸš€ Finished installing rustup, rustc and cargo."
}
103 changes: 103 additions & 0 deletions test/install/test-rust-installation.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bats

# Test Rust installation script

setup() {
# Create temporary directory for each test
export TEST_TEMP_DIR
TEST_TEMP_DIR="$(mktemp -d)"

# Save original environment
export ORIGINAL_HOME="$HOME"
export ORIGINAL_DOTFILES="${DOTFILES:-}"
export ORIGINAL_PATH="$PATH"

# Set up test environment
export HOME="$TEST_TEMP_DIR/fake_home"
export DOTFILES="$TEST_TEMP_DIR/fake_dotfiles"

# Create fake dotfiles structure
mkdir -p "$DOTFILES/lib"
cp "lib/rust-utils.bash" "$DOTFILES/lib/"

# Create mock bin directory
export MOCK_BIN="$TEST_TEMP_DIR/bin"
mkdir -p "$MOCK_BIN"
}

teardown() {
# Restore original environment
export HOME="$ORIGINAL_HOME"
export PATH="$ORIGINAL_PATH"

if [[ -n "${ORIGINAL_DOTFILES}" ]]; then
export DOTFILES="$ORIGINAL_DOTFILES"
else
unset DOTFILES
fi

# Clean up temporary directory
if [[ -n "${TEST_TEMP_DIR:-}" && -d "$TEST_TEMP_DIR" ]]; then
rm -rf "$TEST_TEMP_DIR"
fi
}

@test "rust.bash exists and is executable" {
[ -f "$(pwd)/bin/install/rust.bash" ]
[ -x "$(pwd)/bin/install/rust.bash" ]
}

@test "rust.bash skips installation when rust is already installed" {
# Create mock rustup command
cat > "$MOCK_BIN/rustup" << 'EOF'
#!/bin/bash
echo "rustup 1.26.0"
EOF
chmod +x "$MOCK_BIN/rustup"

# Add mock bin to PATH
PATH="$MOCK_BIN:$PATH"

# Run rust installation
run bash "$(pwd)/bin/install/rust.bash"

# Should indicate rust is already installed
[[ "$output" =~ "Rust is already installed" ]]
[ "$status" -eq 0 ]
}

@test "rust.bash installs rust when not present" {
# Create mock curl command that logs execution
local install_log="$TEST_TEMP_DIR/install.log"
cat > "$MOCK_BIN/curl" << EOF
#!/bin/bash
echo "curl executed with: \$@" > "$install_log"
# Mock the rustup script
cat << 'SCRIPT_EOF'
#!/bin/sh
echo "Mock rustup installer executed"
SCRIPT_EOF
EOF
chmod +x "$MOCK_BIN/curl"

# Create mock sh to capture installation
cat > "$MOCK_BIN/sh" << 'EOF'
#!/bin/bash
echo "sh executed with rustup installer"
EOF
chmod +x "$MOCK_BIN/sh"

# Override PATH to exclude system rustup but keep essential commands
PATH="$MOCK_BIN:/usr/bin:/bin"

# Run rust installation
run bash "$(pwd)/bin/install/rust.bash"

# Should indicate installation is happening
[[ "$output" =~ "Installing Rust toolchain" ]]
[[ "$output" =~ "Finished installing rustup" ]]
[ "$status" -eq 0 ]

# Verify curl was called
[[ -f "$install_log" ]]
}
110 changes: 110 additions & 0 deletions test/install/test-rust-utils.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env bats

# Test Rust utility functions

# Load the Rust utilities
load "../../lib/rust-utils.bash"

setup() {
# Create temporary directory for each test
export TEST_TEMP_DIR
TEST_TEMP_DIR="$(mktemp -d)"

# Save original environment
export ORIGINAL_PATH="$PATH"
export ORIGINAL_CARGO_HOME="${CARGO_HOME:-}"
export ORIGINAL_RUSTUP_HOME="${RUSTUP_HOME:-}"

# Create mock bin directory
export MOCK_BIN="$TEST_TEMP_DIR/bin"
mkdir -p "$MOCK_BIN"
}

teardown() {
# Restore original environment
export PATH="$ORIGINAL_PATH"

if [[ -n "$ORIGINAL_CARGO_HOME" ]]; then
export CARGO_HOME="$ORIGINAL_CARGO_HOME"
else
unset CARGO_HOME
fi

if [[ -n "$ORIGINAL_RUSTUP_HOME" ]]; then
export RUSTUP_HOME="$ORIGINAL_RUSTUP_HOME"
else
unset RUSTUP_HOME
fi

# Clean up temporary directory
if [[ -n "${TEST_TEMP_DIR:-}" && -d "$TEST_TEMP_DIR" ]]; then
rm -rf "$TEST_TEMP_DIR"
fi
}

@test "rust_installed returns false when rustup not found" {
# Ensure rustup is not in PATH
PATH="$MOCK_BIN"

run rust_installed
[ "$status" -eq 1 ]
}

@test "rust_installed returns true when rustup is found" {
# Create mock rustup command
cat > "$MOCK_BIN/rustup" << 'EOF'
#!/bin/bash
echo "rustup 1.26.0"
EOF
chmod +x "$MOCK_BIN/rustup"

# Add mock bin to PATH
PATH="$MOCK_BIN:$PATH"

run rust_installed
[ "$status" -eq 0 ]
}

@test "setup_rust_environment sets CARGO_HOME and RUSTUP_HOME" {
run setup_rust_environment
[ "$status" -eq 0 ]

# Source the function and check the variables
setup_rust_environment
[[ "$CARGO_HOME" == "$HOME/.config/cargo" ]]
[[ "$RUSTUP_HOME" == "$HOME/.config/rustup" ]]
}

@test "install_rust_toolchain uses curl to download rustup installer" {
# Create mock curl command that logs its arguments
local curl_log="$TEST_TEMP_DIR/curl.log"
cat > "$MOCK_BIN/curl" << EOF
#!/bin/bash
echo "curl called with: \$@" > "$curl_log"
# Mock the rustup script response
cat << 'SCRIPT_EOF'
#!/bin/sh
echo "Mock rustup installer executed"
SCRIPT_EOF
EOF
chmod +x "$MOCK_BIN/curl"

# Create mock sh command to capture script execution
cat > "$MOCK_BIN/sh" << 'EOF'
#!/bin/bash
echo "sh executed"
EOF
chmod +x "$MOCK_BIN/sh"

# Add mock bin to PATH
PATH="$MOCK_BIN:$PATH"

run install_rust_toolchain
[ "$status" -eq 0 ]

# Check that curl was called with correct arguments
[[ -f "$curl_log" ]]
local curl_args=$(cat "$curl_log")
[[ "$curl_args" =~ "--proto" ]]
[[ "$curl_args" =~ "https://sh.rustup.rs" ]]
}
Loading