- GNU Stow packages: kitty, fish, nvim, btop, fastfetch, starship, git, claude - install.sh with modular install, template rendering, fish plugins setup - uninstall.sh (stow -D) and scripts/doctor.sh for health checks - Brewfile (macOS) + Aptfile (Linux servers) - Claude Code hooks pipeline: settings.json.tpl, Obsidian session logging scripts - memory-compiler inline copy with env-var-based paths - Python scripts patched: os.environ.get() for OBSIDIAN_VAULT + PROJECTS_ROOT - fish/config.fish: platform-aware Homebrew PATH (macOS + Linuxbrew) - .env.example template for ~/.dotfiles.env Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
69 lines
3 KiB
Bash
69 lines
3 KiB
Bash
#!/usr/bin/env bash
|
|
# lib/helpers.sh — logging, OS detection, backup utilities
|
|
|
|
# ── Colors ────────────────────────────────────────────────────────────────
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'; BOLD='\033[1m'; RESET='\033[0m'
|
|
|
|
info() { echo -e "${BLUE}[INFO]${RESET} $*"; }
|
|
success() { echo -e "${GREEN}[OK]${RESET} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; }
|
|
error() { echo -e "${RED}[ERR]${RESET} $*" >&2; }
|
|
step() { echo -e "\n${BOLD}▶ $*${RESET}"; }
|
|
|
|
# ── OS Detection ──────────────────────────────────────────────────────────
|
|
is_macos() { [[ "$(uname -s)" == "Darwin" ]]; }
|
|
is_linux() { [[ "$(uname -s)" == "Linux" ]]; }
|
|
|
|
os_name() {
|
|
if is_macos; then echo "macOS"
|
|
elif is_linux; then echo "Linux"
|
|
else echo "unknown"; fi
|
|
}
|
|
|
|
# ── Backup helper ─────────────────────────────────────────────────────────
|
|
# backup_file TARGET_PATH — moves existing file/dir to ~/.dotfiles-backup/DATE/
|
|
backup_file() {
|
|
local target="$1"
|
|
local backup_dir="$HOME/.dotfiles-backup/$(date +%Y-%m-%d)"
|
|
if [[ -e "$target" && ! -L "$target" ]]; then
|
|
mkdir -p "$backup_dir"
|
|
local rel="${target#"$HOME/"}"
|
|
local dest="$backup_dir/${rel//\//__}"
|
|
warn "Backing up $(basename "$target") → $backup_dir/"
|
|
mv "$target" "$dest"
|
|
fi
|
|
}
|
|
|
|
# ── Command existence check ────────────────────────────────────────────────
|
|
has_cmd() { command -v "$1" &>/dev/null; }
|
|
|
|
# ── Load dotfiles.env ─────────────────────────────────────────────────────
|
|
load_env() {
|
|
local env_file="$HOME/.dotfiles.env"
|
|
if [[ ! -f "$env_file" ]]; then
|
|
error "~/.dotfiles.env not found."
|
|
echo ""
|
|
echo " Run: cp $(dirname "$(dirname "${BASH_SOURCE[0]}")")/.env.example ~/.dotfiles.env"
|
|
echo " Then: fill in the values and re-run install.sh"
|
|
exit 1
|
|
fi
|
|
# shellcheck source=/dev/null
|
|
set -a; source "$env_file"; set +a
|
|
|
|
# Validate required fields
|
|
local missing=()
|
|
[[ -z "${ANTHROPIC_API_KEY:-}" ]] && missing+=("ANTHROPIC_API_KEY")
|
|
[[ -z "${GIT_USER_NAME:-}" ]] && missing+=("GIT_USER_NAME")
|
|
[[ -z "${GIT_USER_EMAIL:-}" ]] && missing+=("GIT_USER_EMAIL")
|
|
[[ -z "${OBSIDIAN_VAULT:-}" ]] && missing+=("OBSIDIAN_VAULT")
|
|
[[ -z "${PROJECTS_ROOT:-}" ]] && missing+=("PROJECTS_ROOT")
|
|
|
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
error "Missing required values in ~/.dotfiles.env:"
|
|
for field in "${missing[@]}"; do
|
|
echo " - $field"
|
|
done
|
|
exit 1
|
|
fi
|
|
}
|