mirror of
https://github.com/ForeverPyrite/dotfiles.git
synced 2025-12-10 01:08:06 +00:00
231 lines
8.5 KiB
Bash
Executable File
231 lines
8.5 KiB
Bash
Executable File
#!/bin/bash
|
||
#
|
||
# Dotfiles Bootstrap Script
|
||
#
|
||
# This script automates the setup of a high-performance, Rust-powered
|
||
# command-line environment. It uses a hybrid sequential/parallel approach.
|
||
#
|
||
# Flags:
|
||
# --extended: Performs a "desktop" setup: installs GUI fonts and changes the default shell.
|
||
# --docker: Installs Docker Engine.
|
||
|
||
set -e # Exit immediately if a command exits with a non-zero status.
|
||
|
||
# --- Helper Functions for Logging ---
|
||
info() { echo -e "\033[1;34m==> $1\033[0m"; }
|
||
success() { echo -e "\033[1;32m✅ $1\033[0m"; }
|
||
warn() { echo -e "\033[1;33m⚠️ $1\033[0m"; }
|
||
|
||
# --- Argument Parsing & Environment Setup ---
|
||
EXTENDED_INSTALL=false
|
||
DOCKER_INSTALL=false
|
||
[[ " $* " =~ " --extended " ]] && EXTENDED_INSTALL=true
|
||
[[ " $* " =~ " --docker " ]] && DOCKER_INSTALL=true
|
||
|
||
# Phased installation package lists
|
||
PREREQ_PACKAGES=(git stow)
|
||
SYSTEM_PACKAGES=(curl tmux btop fish)
|
||
RUST_PACKAGES=(
|
||
eza
|
||
bat
|
||
ripgrep
|
||
zoxide
|
||
starship
|
||
bob-nvim
|
||
atuin
|
||
dua-cli
|
||
cargo-cache
|
||
)
|
||
|
||
# Global variables for system context
|
||
SUDO_CMD=""
|
||
PM=""
|
||
OS_ID=""
|
||
|
||
# --- Prerequisite Functions (Unchanged) ---
|
||
detect_os_and_pm() {
|
||
info "Detecting OS and Package Manager..."
|
||
if [ -f /etc/os-release ]; then
|
||
. /etc/os-release
|
||
OS_ID=$ID
|
||
fi
|
||
|
||
if [[ "$(uname)" == "Darwin" ]]; then
|
||
PM="brew"
|
||
elif command -v apt-get &>/dev/null; then
|
||
PM="apt-get"
|
||
elif command -v dnf &>/dev/null; then
|
||
PM="dnf"
|
||
elif command -v pacman &>/dev/null; then
|
||
PM="pacman"
|
||
else
|
||
warn "Could not detect a supported package manager (apt-get, dnf, pacman, brew)."
|
||
exit 1
|
||
fi
|
||
info "Detected OS: ${OS_ID:-macOS}, Package Manager: $PM"
|
||
}
|
||
|
||
check_and_setup_sudo() {
|
||
info "Checking for root privileges and sudo..."
|
||
if [[ "$(id -u)" -eq 0 ]]; then
|
||
info "Running as root. 'sudo' is not required."
|
||
SUDO_CMD=""
|
||
if ! command -v sudo &>/dev/null; then
|
||
info "Sudo not found. Installing it for future convenience..."
|
||
case "$PM" in
|
||
apt-get) apt-get update && apt-get install -y sudo ;;
|
||
dnf) dnf install -y sudo ;;
|
||
pacman) pacman -S --noconfirm sudo ;;
|
||
esac
|
||
fi
|
||
else
|
||
if ! command -v sudo &>/dev/null; then
|
||
warn "This script requires 'sudo' to be installed for non-root users."
|
||
exit 1
|
||
fi
|
||
SUDO_CMD="sudo"
|
||
info "Running as non-root user. Using 'sudo' for privileged operations."
|
||
fi
|
||
}
|
||
|
||
install_build_tools() {
|
||
info "Installing essential build tools for Rust..."
|
||
case "$PM" in
|
||
apt-get) $SUDO_CMD apt-get install -y build-essential ;;
|
||
dnf) $SUDO_CMD dnf groupinstall -y "Development Tools" ;;
|
||
pacman) $SUDO_CMD pacman -S --noconfirm --needed base-devel ;;
|
||
esac
|
||
}
|
||
|
||
install_rust_toolchain() {
|
||
if command -v cargo &>/dev/null; then info "Rust toolchain is already installed."; else
|
||
info "Installing Rust and Cargo via rustup..."
|
||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||
fi
|
||
export PATH="$HOME/.cargo/bin:$PATH"
|
||
}
|
||
|
||
deploy_dotfiles() {
|
||
info "Cloning and deploying dotfiles..."
|
||
local dotfiles_repo="https://github.com/ForeverPyrite/dotfiles.git"
|
||
local dotfiles_dir="$HOME/dotfiles"
|
||
if [ ! -d "$dotfiles_dir" ]; then git clone "$dotfiles_repo" "$dotfiles_dir"; else info "Dotfiles directory already exists. Skipping clone."; fi
|
||
info "Backing up any conflicting default config files..."
|
||
local conflict_files=("$HOME/.bashrc" "$HOME/.profile" "$HOME/.bash_logout")
|
||
for file in "${conflict_files[@]}"; do
|
||
if [ -f "$file" ] && [ ! -L "$file" ]; then
|
||
mv "$file" "$file.bak"
|
||
info " -> Moved $file to $file.bak"
|
||
fi
|
||
done
|
||
info "Running 'stow' to link configurations..."
|
||
cd "$dotfiles_dir"
|
||
for dir in */; do [ -d "$dir" ] && stow "${dir%/}"; done
|
||
cd - >/dev/null
|
||
success "Dotfiles have been deployed."
|
||
}
|
||
|
||
# --- Parallel Installation Function ---
|
||
run_parallel_installs() {
|
||
info "Handing off to Tmux for parallel tool installation..."
|
||
local session_name="dotfiles"
|
||
|
||
# --- Command Definitions ---
|
||
local cargo_cmd="export PATH='$HOME/.cargo/bin:$PATH'; for pkg in ${RUST_PACKAGES[@]}; do cargo install --locked \$pkg; done && bob use stable && \
|
||
sudo ln -s ~/.local/share/bob/nvim-bob/nvim /usr/bin/nvim && \
|
||
cargo cache -a -y && \
|
||
echo '✅ Cargo packages installed, Neovim set up, and cache cleaned.'"
|
||
local fzf_cmd="git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf && ~/.fzf/install --all && echo '✅ fzf installed.'"
|
||
local tpm_cmd="git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm && echo '✅ Tmux Plugin Manager installed.'"
|
||
|
||
# --- Create Layout & Send Commands ---
|
||
# This robust method creates the entire layout first, then sends commands to the numbered panes.
|
||
tmux start-server
|
||
# Pane 0
|
||
tmux new-session -d -s "$session_name"
|
||
# Pane 1
|
||
tmux split-window -h -t "$session_name:1.1"
|
||
# Pane 2
|
||
tmux split-window -v -t "$session_name:1.2"
|
||
|
||
# Send commands to their respective panes
|
||
tmux send-keys -t "$session_name:1.1" "$cargo_cmd" C-m
|
||
tmux send-keys -t "$session_name:1.2" "$tpm_cmd" C-m
|
||
tmux send-keys -t "$session_name:1.3" "$fzf_cmd" C-m
|
||
|
||
# Handle optional installs in new windows
|
||
if [ "$DOCKER_INSTALL" = true ]; then
|
||
tmux new-window -t "$session_name" -n "Docker"
|
||
local docker_cmd="curl -fsSL https://get.docker.com | $SUDO_CMD sh && echo '✅ Docker installed.'"
|
||
tmux send-keys -t "$session_name:Docker" "$docker_cmd" C-m
|
||
fi
|
||
if [ "$EXTENDED_INSTALL" = true ]; then
|
||
tmux new-window -t "$session_name" -n "Desktop"
|
||
|
||
# Pane 1: Font Installation (your existing command)
|
||
local font_cmd="mkdir -p ~/.local/share/fonts && curl -fLo f.tar.xz https://github.com/ryanoasis/nerd-fonts/releases/download/v3.2.1/Hack.tar.xz && tar -xf f.tar.xz -C ~/.local/share/fonts && rm f.tar.xz && fc-cache -fv && echo '✅ Fonts installed.'"
|
||
tmux send-keys -t "$session_name:Desktop.1" "$font_cmd" C-m
|
||
|
||
# Split the window for the next commands
|
||
tmux split-window -h -t "$session_name:Desktop.1"
|
||
tmux split-window -v -t "$session_name:Desktop.2"
|
||
|
||
# Pane 2: Change Shell (your existing command)
|
||
local shell_cmd="FISH_PATH=\$(which fish); if ! grep -q \"\$FISH_PATH\" /etc/shells; then echo \"\$FISH_PATH\" | $SUDO_CMD tee -a /etc/shells; fi; $SUDO_CMD chsh -s \"\$FISH_PATH\" \"$USER\" && echo '✅ Shell changed.'"
|
||
tmux send-keys -t "$session_name:Desktop.2" "$shell_cmd" C-m
|
||
warn "The 'chsh' command inside tmux may require your password to complete."
|
||
|
||
# Pane 3: Install Alacritty
|
||
local alacritty_install_cmd
|
||
case "$PM" in
|
||
brew) alacritty_install_cmd="brew install --cask ${GUI_PACKAGES[*]}" ;;
|
||
apt-get) alacritty_install_cmd="$SUDO_CMD apt-get install -y ${GUI_PACKAGES[*]}" ;;
|
||
dnf) alacritty_install_cmd="$SUDO_CMD dnf install -y ${GUI_PACKAGES[*]}" ;;
|
||
pacman) alacritty_install_cmd="$SUDO_CMD pacman -S --noconfirm ${GUI_PACKAGES[*]}" ;;
|
||
esac
|
||
alacritty_install_cmd+=" && echo '✅ Alacritty installed.'"
|
||
tmux send-keys -t "$session_name:Desktop.3" "$alacritty_install_cmd" C-m
|
||
fi
|
||
success "Tmux session '$session_name' created. Attach with: tmux a -t $session_name"
|
||
}
|
||
|
||
# --- Main Execution ---
|
||
# Phase 0: System Detection & Prerequisite Installation
|
||
detect_os_and_pm
|
||
check_and_setup_sudo
|
||
info "Phase 0: Installing prerequisites (git, stow)..."
|
||
case "$PM" in
|
||
brew) brew install "${PREREQ_PACKAGES[@]}" ;;
|
||
apt-get) $SUDO_CMD apt-get update && $SUDO_CMD apt-get install -y "${PREREQ_PACKAGES[@]}" ;;
|
||
dnf)
|
||
if [[ "$OS_ID" == "ol" || "$OS_ID" == "almalinux" || "$OS_ID" == "rockylinux" || "$OS_ID" == "centos" ]]; then $SUDO_CMD dnf install -y epel-release --nogpgcheck; fi
|
||
$SUDO_CMD dnf install -y "${PREREQ_PACKAGES[@]}"
|
||
;;
|
||
pacman) $SUDO_CMD pacman -Syu --noconfirm "${PREREQ_PACKAGES[@]}" ;;
|
||
esac
|
||
success "Prerequisites installed."
|
||
|
||
# Phase 1: Deploy Configurations
|
||
deploy_dotfiles
|
||
|
||
# Phase 2: Core System Installation
|
||
info "Phase 2: Installing core system tools..."
|
||
case "$PM" in
|
||
brew) brew install "${SYSTEM_PACKAGES[@]}" ;; apt-get) $SUDO_CMD apt-get install -y "${SYSTEM_PACKAGES[@]}" ;;
|
||
dnf) $SUDO_CMD dnf install -y "${SYSTEM_PACKAGES[@]}" ;; pacman) $SUDO_CMD pacman -S --noconfirm "${SYSTEM_PACKAGES[@]}" ;;
|
||
esac
|
||
install_build_tools
|
||
install_rust_toolchain
|
||
success "Core system tools installed."
|
||
|
||
# Phase 3: Parallel Tool Installation
|
||
run_parallel_installs
|
||
|
||
# --- Final Message ---
|
||
echo ""
|
||
info "--------------------------------------------------------"
|
||
success "Bootstrap script finished!"
|
||
info "Monitor the rest of the installation inside tmux: tmux a -t dotfiles_setup"
|
||
info "Log out and log back in to apply all changes, especially the new shell."
|
||
info "--------------------------------------------------------"
|