189 lines
6.1 KiB
Bash
189 lines
6.1 KiB
Bash
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
DOTFILES_REPO="https://gitea.purpleraft.com/ryan/dotfiles"
|
|
DOTFILES_DIR="$HOME/.dotfiles"
|
|
|
|
# Handle branch selection
|
|
if [ $# -eq 0 ]; then
|
|
echo "🌿 Fetching available branches..."
|
|
|
|
# Get list of remote branches
|
|
branches=$(git ls-remote --heads "$DOTFILES_REPO" | sed 's/.*refs\/heads\///' | sort)
|
|
|
|
if [ -z "$branches" ]; then
|
|
echo "⚠️ Could not fetch branches, using default 'main'"
|
|
BRANCH="main"
|
|
else
|
|
echo "Available branches:"
|
|
branch_array=()
|
|
i=1
|
|
while IFS= read -r branch; do
|
|
echo "$i. $branch"
|
|
branch_array+=("$branch")
|
|
((i++))
|
|
done <<< "$branches"
|
|
|
|
echo "$i. Enter custom branch name"
|
|
echo ""
|
|
read -p "Choose branch (1-$i) [default: main]: " branch_choice
|
|
|
|
if [[ "$branch_choice" =~ ^[0-9]+$ ]] && [ "$branch_choice" -ge 1 ] && [ "$branch_choice" -lt "$i" ]; then
|
|
# Valid branch selection
|
|
BRANCH="${branch_array[$((branch_choice-1))]}"
|
|
elif [ "$branch_choice" -eq "$i" ]; then
|
|
# Custom branch name
|
|
read -p "Enter branch name: " custom_branch
|
|
BRANCH="$custom_branch"
|
|
else
|
|
# Default or invalid choice
|
|
if [[ " ${branch_array[*]} " =~ " main " ]]; then
|
|
BRANCH="main"
|
|
else
|
|
BRANCH="${branch_array[0]}" # Use first available branch
|
|
fi
|
|
echo "Using default branch: $BRANCH"
|
|
fi
|
|
fi
|
|
else
|
|
BRANCH="$1"
|
|
fi
|
|
|
|
# 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
|
|
|
|
echo "🚀 Installing dotfiles from branch: $BRANCH"
|
|
|
|
# Clone or update the repo
|
|
if [ -d "$DOTFILES_DIR/.git" ]; then
|
|
echo "🔄 Updating existing dotfiles repo..."
|
|
git -C "$DOTFILES_DIR" fetch --quiet
|
|
git -C "$DOTFILES_DIR" checkout "$BRANCH" --quiet
|
|
git -C "$DOTFILES_DIR" pull --quiet
|
|
else
|
|
echo "📥 Cloning dotfiles into $DOTFILES_DIR..."
|
|
git clone -b "$BRANCH" "$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."
|