#!/bin/bash set -euo pipefail DOTFILES_REPO="https://gitea.purpleraft.com/ryan/dotfiles" DOTFILES_DIR="$HOME/.dotfiles" # Function to install packages from a file install_packages() { local package_file="$1" local description="$2" if [ -f "$package_file" ]; then echo "📦 Installing $description..." # Read packages into array, skipping comments and empty lines packages=() while IFS= read -r line; do # Skip comments and empty lines [[ "$line" =~ ^[[:space:]]*# ]] && continue [[ -z "${line// }" ]] && continue packages+=("$line") done < "$package_file" if [ ${#packages[@]} -eq 0 ]; then echo " No packages found in $package_file" return fi # Detect package manager and install packages if command -v apt &> /dev/null; then # Debian/Ubuntu sudo apt update && sudo apt install -y "${packages[@]}" elif command -v yum &> /dev/null; then # RHEL/CentOS sudo yum install -y "${packages[@]}" elif command -v dnf &> /dev/null; then # Fedora sudo dnf install -y "${packages[@]}" elif command -v pacman &> /dev/null; then # Arch Linux sudo pacman -S --noconfirm "${packages[@]}" elif command -v brew &> /dev/null; then # macOS brew install "${packages[@]}" else echo "⚠️ No supported package manager found. Please install packages manually from $package_file" fi fi } # Check if stow is installed if ! command -v stow &> /dev/null; then echo "❌ GNU Stow is not installed. Please install it first:" echo " Ubuntu/Debian: sudo apt install stow" echo " macOS: brew install stow" echo " Or use the alias: install_stow" exit 1 fi # Clone or update the repo if [ -d "$DOTFILES_DIR/.git" ]; then echo "🔄 Updating existing dotfiles repo..." git -C "$DOTFILES_DIR" pull --quiet else echo "📥 Cloning dotfiles into $DOTFILES_DIR..." git clone "$DOTFILES_REPO" "$DOTFILES_DIR" fi cd "$DOTFILES_DIR" # Install packages (with user confirmation) echo "" echo "Package installation options:" echo "1. Base packages (MUST HAVE) - curl, git, stow, vim, etc." echo "2. CLI tools (Nice-to-haves) - bat, fzf, ripgrep, etc." echo "3. Development tools - nodejs, python, docker, etc." echo "4. GUI applications - firefox, code, vlc, etc." echo "5. Skip package installation" echo "" read -p "Choose packages to install (1-5, or comma-separated like 1,2): " package_choice # Install selected packages if [[ "$package_choice" == *"1"* ]]; then install_packages "packages/base.txt" "base packages" fi if [[ "$package_choice" == *"2"* ]]; then install_packages "packages/cli-tools.txt" "CLI tools" fi if [[ "$package_choice" == *"3"* ]]; then install_packages "packages/dev.txt" "development tools" fi if [[ "$package_choice" == *"4"* ]]; then install_packages "packages/gui.txt" "GUI applications" fi # Backup existing files that would conflict with stow echo "" echo "🔗 Setting up dotfile symlinks..." for config_dir in stow/*/; do if [ -d "$config_dir" ]; then config_name=$(basename "$config_dir") echo " Checking for conflicts with $config_name config..." # Find all files that would be stowed and backup if they exist find "$config_dir" -type f | while read -r file; do relative_file="${file#$config_dir}" target_file="$HOME/$relative_file" if [ -f "$target_file" ] && [ ! -L "$target_file" ]; then echo " ⚠️ Backing up existing file: $target_file -> ${target_file}.bak" mv "$target_file" "${target_file}.bak" fi done fi done # Use stow to create symlinks for each configuration cd stow for config_dir in */; do if [ -d "$config_dir" ]; then config_name=$(basename "$config_dir") echo " 🔗 Stowing $config_name configuration..." if ! stow -t "$HOME" "$config_name" 2>/dev/null; then echo " ⚠️ Stow failed for $config_name, trying with --adopt..." stow --adopt -t "$HOME" "$config_name" fi fi done # Optionally source the new bashrc if [[ $- == *i* ]] && [ -f "$HOME/.bashrc" ]; then echo "🔄 Reloading Bash config..." source ~/.bashrc fi echo "" echo "✅ Dotfiles install complete!" echo "💡 Use 'dotpull' alias to update your dotfiles in the future."