dotfiles/modules/02-symlinks.sh
Martin Büchler d9bebb71ac refactor: DRY device-specific symlinking, standardize on DOTFILES_DEVICE, improve comments and safety
- Remove duplicate device-specific blocks in symlinks script
- Use DOTFILES_DEVICE everywhere, remove PROFILE
- Add clear comments and documentation for maintainability
- Polish symlink removal logic for safety and idempotence

🤖 Generated with [opencode](https://opencode.ai)

Co-Authored-By: opencode <noreply@opencode.ai>
2025-08-08 14:20:13 +02:00

119 lines
4.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# =====================
# Dotfiles Symlinking Script
# =====================
# - Symlinks all dotfiles and app configs from the repo to $HOME and $HOME/.config
# - Handles device-specific fragments for Hyprland, Waybar, etc. using $DOTFILES_DEVICE and $HOSTNAME
# - Idempotent and safe to re-run
# - To extend, add new fragment types to the fragment_types array below
# =====================
mkdir -p "$HOME/.config"
echo "Symlinking dotfiles..."
# Get the dotfiles directory (parent of modules directory)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTFILES_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
# Symlink regular dotfiles (excluding .config directory)
for file in $(find "$DOTFILES_DIR" -maxdepth 1 -name ".*"); do
[ "$file" = "$DOTFILES_DIR/.git" ] && continue
[ "$file" = "$DOTFILES_DIR/.github" ] && continue
[ "$file" = "$DOTFILES_DIR/.vscode" ] && continue
[ "$file" = "$DOTFILES_DIR/.config" ] && continue # Handle .config separately
basefile="$(basename "$file")"
if [ -f "$file" ] || [ -d "$file" ]; then
ln -sf "$file" "$HOME/$basefile"
echo "Linked $basefile"
fi
done
# Symlink .config directory contents
CONFIG_DIR="$DOTFILES_DIR/.config"
if [ -d "$CONFIG_DIR" ]; then
echo "Symlinking .config contents..."
for item in "$CONFIG_DIR"/*; do
[ -e "$item" ] || continue
baseitem="$(basename "$item")"
target_dir="$HOME/.config/$baseitem"
# Remove only if it's a symlink or a directory we manage
if [ -L "$target_dir" ]; then
rm "$target_dir"
elif [ -d "$target_dir" ] && [ ! -L "$target_dir" ]; then
# Only remove if the directory is empty or matches our repo
if [ -z "$(ls -A "$target_dir" 2>/dev/null)" ]; then
rm -rf "$target_dir"
else
echo "Warning: $target_dir is a non-empty directory. Not removed."
fi
fi
ln -sf "$item" "$target_dir"
echo "Linked .config/$baseitem"
done
# =====================
# Device-specific symlinks for Hyprland and Waybar
# =====================
# This section handles device-specific config fragments for Hyprland, Waybar, etc.
# Uses $DOTFILES_DEVICE (set by setup.sh) and $HOSTNAME for profile-specific fragments.
# To add new device types (e.g., tablet, server), update host-profiles.conf and add fragments.
# To add new fragment types, extend the fragment_types array below.
# Format: "source_fragment_path:target_symlink_path"
# Example: fragment_types=(
# "hypr/includes/monitors-$HOSTNAME.conf:hypr/includes/monitors.conf"
# "hypr/includes/hypridle-$DOTFILES_DEVICE.conf:hypr/hypridle.conf"
# "waybar/config-$DOTFILES_DEVICE:waybar/config"
# )
if [ -z "$DOTFILES_DEVICE" ]; then
echo "ERROR: DOTFILES_DEVICE environment variable not set. Run setup.sh to detect device profile."
exit 1
fi
HOSTNAME=$(hostname)
# Device-specific fragments to symlink (source:target)
fragment_types=(
"hypr/includes/monitors-$HOSTNAME.conf:hypr/includes/monitors.conf" # Monitor layout per host
"hypr/includes/hypridle-$DOTFILES_DEVICE.conf:hypr/hypridle.conf" # Idle config per device type
"waybar/config-$DOTFILES_DEVICE:waybar/config" # Waybar config per device type
)
# Symlink each device-specific fragment
for fragment in "${fragment_types[@]}"; do
src="${CONFIG_DIR}/${fragment%%:*}"
tgt="${CONFIG_DIR}/${fragment##*:}"
if [ -f "$src" ]; then
ln -sf "$src" "$tgt"
echo "Linked $(basename "$src") as $(basename "$tgt")"
else
echo "Warning: Device-specific fragment missing: $src"
# To troubleshoot, ensure the fragment exists for your device/host
fi
done
# =====================
# End device-specific symlinking
# =====================
fi
echo "====================="
echo "Dotfiles symlinking complete!"
echo "====================="
# Symlink .local/bin scripts
LOCAL_BIN_REPO="$DOTFILES_DIR/.local/bin"
LOCAL_BIN_HOME="$HOME/.local/bin"
if [ -d "$LOCAL_BIN_REPO" ]; then
mkdir -p "$LOCAL_BIN_HOME"
echo "Symlinking .local/bin scripts..."
for script in "$LOCAL_BIN_REPO"/*; do
[ -e "$script" ] || continue
base_script="$(basename "$script")"
ln -sf "$script" "$LOCAL_BIN_HOME/$base_script"
echo "Linked .local/bin/$base_script"
done
fi