1
0
Fork 0
mirror of https://github.com/SeriousBug/dotfiles synced 2025-12-06 21:12:08 -06:00
dotfiles/setup.sh
Kaan Barmore-Genc 3bf9ba3318 Add directory symlink support for fish functions
Allows setup.sh to symlink entire directories for cases where programs
create new files that should be tracked (e.g., fish's funcsave command).
Removes fish/functions from Dotter management in favor of direct symlink.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 01:12:54 -06:00

274 lines
7.4 KiB
Bash
Executable file

#!/usr/bin/env bash
set -eo pipefail
# Function to manage directory symlinks
# Usage: ensure_dir_symlink <source_dir> <target_link> <force_flag>
# Args:
# source_dir: The actual directory to symlink to (must be absolute path)
# target_link: The symlink location to create
# force_flag: true/false - whether to force replacement if exists
ensure_dir_symlink() {
local source_dir="$1"
local target_link="$2"
local force_flag="$3"
# Expand tilde in paths
target_link="${target_link/#\~/$HOME}"
source_dir="${source_dir/#\~/$HOME}"
# Check if target exists
if [[ -e "$target_link" || -L "$target_link" ]]; then
# Check if it's already a symlink pointing to the right place
if [[ -L "$target_link" ]]; then
local current_target
current_target="$(readlink "$target_link")"
if [[ "$current_target" == "$source_dir" ]]; then
echo "$target_link already symlinked correctly"
return 0
else
# Symlink exists but points to wrong location
if [[ "$force_flag" == true ]]; then
echo "Replacing symlink $target_link (currently points to $current_target)"
rm "$target_link"
else
echo "⚠ Warning: $target_link exists but points to $current_target (expected $source_dir)"
echo " Run with --force-deploy to replace it"
return 0
fi
fi
else
# Path exists but is not a symlink
if [[ "$force_flag" == true ]]; then
echo "Replacing $target_link with symlink (was a regular file/directory)"
rm -rf "$target_link"
else
echo "⚠ Warning: $target_link exists but is not a symlink"
echo " Run with --force-deploy to replace it"
return 0
fi
fi
fi
# Create parent directory if needed
local parent_dir
parent_dir="$(dirname "$target_link")"
if [[ ! -d "$parent_dir" ]]; then
echo "Creating parent directory: $parent_dir"
mkdir -p "$parent_dir"
fi
# Create the symlink
echo "Creating symlink: $target_link -> $source_dir"
ln -s "$source_dir" "$target_link"
echo "✓ Successfully created symlink"
}
# Parse command line arguments
RESET_CONFIG=false
FORCE_DEPLOY=false
SKIP_BREW=false
for arg in "$@"; do
case $arg in
--reset)
RESET_CONFIG=true
echo "Resetting configuration (will re-prompt for all variables)..."
;;
--force-deploy)
FORCE_DEPLOY=true
echo "Force deployment mode enabled..."
;;
--skip-brew)
SKIP_BREW=true
echo "Skipping Homebrew package installation..."
;;
*)
echo "Unknown option: $arg"
echo "Usage: $0 [--reset] [--force-deploy] [--skip-brew]"
exit 1
;;
esac
done
echo "Setting up dotfiles environment..."
# Detect OS
OS="$(uname -s)"
if [[ "$SKIP_BREW" == false ]]; then
# Check if Homebrew is installed
if ! command -v brew &> /dev/null; then
echo "Homebrew is not installed. Please install it first:"
echo "https://brew.sh"
exit 1
fi
echo "Updating Homebrew..."
brew update
# Install packages (available on both macOS and Linux)
PACKAGES=(
dotter
fish
dust
eza
gh
htop
go
jq
lazygit
neovim
asdf
bat
pandoc
ripgrep
zoxide
zellij
p7zip
)
echo "Installing packages..."
for package in "${PACKAGES[@]}"; do
if brew list "$package" &>/dev/null; then
echo "$package already installed"
else
echo "Installing $package..."
brew install "$package"
fi
done
# Install casks on macOS only
if [[ "$OS" == "Darwin" ]]; then
echo "Installing macOS-specific casks..."
CASKS=(
iterm2
font-fira-code-nerd-font
orbstack
rectangle-pro
maccy
)
for cask in "${CASKS[@]}"; do
if brew list --cask "$cask" &>/dev/null; then
echo "$cask already installed"
else
echo "Installing $cask..."
brew install --cask "$cask"
fi
done
else
echo "Skipping macOS-specific casks (not on macOS)"
fi
fi
# Set up GitHub CLI authentication
if command -v gh &> /dev/null; then
if ! gh auth status &>/dev/null; then
echo ""
echo "GitHub CLI is installed but not authenticated."
echo "Please log in to GitHub CLI:"
gh auth login
else
echo "✓ GitHub CLI already authenticated"
fi
fi
# Configure Dotter
echo ""
echo "Configuring Dotter..."
# Path to user variables file
USER_VARS_FILE=".dotter/user_vars.sh"
# Source existing variables if not resetting
if [[ "$RESET_CONFIG" == false && -f "$USER_VARS_FILE" ]]; then
echo "Loading existing configuration..."
source "$USER_VARS_FILE"
fi
# Prompt for missing variables
if [[ -z "$GIT_NAME" ]]; then
read -p "Enter your Git user name: " GIT_NAME
fi
if [[ -z "$GIT_EMAIL" ]]; then
read -p "Enter your Git email: " GIT_EMAIL
fi
# Detect Homebrew path if not set
if [[ -z "$BREW_PATH" ]]; then
if [[ "$OS" == "Darwin" ]]; then
if [[ -d "/opt/homebrew" ]]; then
BREW_PATH="/opt/homebrew"
else
BREW_PATH="/usr/local"
fi
else
BREW_PATH="/home/linuxbrew/.linuxbrew"
fi
echo "Detected Homebrew path: $BREW_PATH"
fi
# Save variables to file
echo "Saving configuration..."
cat > "$USER_VARS_FILE" << EOF
# Dotter user variables
# This file is sourced by setup.sh to avoid re-prompting for values
# To reset and re-prompt for all values, run: ./setup.sh --reset
GIT_NAME="$GIT_NAME"
GIT_EMAIL="$GIT_EMAIL"
BREW_PATH="$BREW_PATH"
EOF
# Generate local.toml
echo "Generating Dotter configuration..."
cat > .dotter/local.toml << EOF
# Machine-specific Dotter configuration
# This file is generated by setup.sh
packages = ["git", "nvim", "fish", "zellij", "htop", "asdf"]
[variables]
git_name = "$GIT_NAME"
git_email = "$GIT_EMAIL"
brew_path = "$BREW_PATH"
EOF
# Deploy dotfiles
echo ""
echo "Deploying dotfiles..."
if [[ "$FORCE_DEPLOY" == true ]]; then
if dotter deploy -f -v; then
echo "✓ Dotfiles deployed successfully (forced)!"
else
echo "⚠ Dotter deployment failed."
fi
else
if dotter deploy -v; then
echo "✓ Dotfiles deployed successfully!"
else
echo "⚠ Dotter deployment failed. You may need to run 'dotter deploy -f' to force deployment."
fi
fi
# Manage directory symlinks (not handled by Dotter)
echo ""
echo "Setting up directory symlinks..."
DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ensure_dir_symlink "$DOTFILES_DIR/fish/functions" "~/.config/fish/functions" "$FORCE_DEPLOY"
echo ""
echo "✓ Setup complete!"
echo ""
echo "Configuration saved to: $USER_VARS_FILE"
echo "To reconfigure, run: ./setup.sh --reset"
echo "To force deployment, run: ./setup.sh --force-deploy"
echo "To skip Homebrew packages, run: ./setup.sh --skip-brew"
echo ""
echo "Next steps:"
echo " 1. Consider setting fish as your default shell: chsh -s \$(which fish)"
echo " 2. Restart your terminal or source your new shell configuration"