Centralized dotfiles.conf, revamped stuff.

This commit is contained in:
Aaron D. Lee
2025-12-14 15:51:49 -05:00
parent fece4e7d3e
commit 5a82f9046b
8 changed files with 505 additions and 506 deletions

View File

@@ -1,71 +1,75 @@
#!/usr/bin/env bash
# ============================================================================
# ADLee Theme System-wide Deployment Script (Enhanced)
# ADLee Theme System-wide Deployment Script
# ============================================================================
# This script deploys the adlee.zsh-theme system-wide via symlinks
# Deploys the zsh theme system-wide via symlinks
#
# Usage:
# sudo ./deploy-theme-systemwide.sh # Interactive mode
# sudo ./deploy-theme-systemwide.sh --all # All users with TTY
# sudo ./deploy-theme-systemwide.sh --current # Current user + root only
# sudo ./deploy-theme-systemwide.sh --force # Force replace all links
# sudo ./deploy-zshtheme-systemwide.sh # Interactive mode
# sudo ./deploy-zshtheme-systemwide.sh --all # All users with oh-my-zsh
# sudo ./deploy-zshtheme-systemwide.sh --current # Current user + root only
# sudo ./deploy-zshtheme-systemwide.sh --status # Show deployment status
# sudo ./deploy-zshtheme-systemwide.sh --force # Force replace existing links
set -euo pipefail
# ============================================================================
# Load Configuration
# ============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTFILES_CONF="${SCRIPT_DIR}/../dotfiles.conf"
[[ -f "$DOTFILES_CONF" ]] || DOTFILES_CONF="$HOME/.dotfiles/dotfiles.conf"
if [[ -f "$DOTFILES_CONF" ]]; then
source "$DOTFILES_CONF"
else
DOTFILES_DIR="$HOME/.dotfiles"
ZSH_THEME_NAME="adlee"
fi
# ============================================================================
# Configuration
# ============================================================================
MASTER_THEME_DIR="/usr/local/share/zsh/themes"
MASTER_THEME_PATH="${MASTER_THEME_DIR}/adlee.zsh-theme"
THEME_NAME="adlee.zsh-theme"
SOURCE_THEME="${HOME}/.dotfiles/zsh/themes/${THEME_NAME}"
THEME_FILE="${ZSH_THEME_NAME}.zsh-theme"
MASTER_THEME_PATH="${MASTER_THEME_DIR}/${THEME_FILE}"
SOURCE_THEME="${DOTFILES_DIR}/zsh/themes/${THEME_FILE}"
FORCE_REPLACE=false
# Colors for output
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
NC='\033[0m'
# ============================================================================
# Helper Functions
# ============================================================================
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
print_info() {
echo -e "${CYAN}${NC} $1"
}
print_step() {
echo -e "\n${GREEN}==>${NC} $1"
}
print_success() { echo -e "${GREEN}${NC} $1"; }
print_warning() { echo -e "${YELLOW}${NC} $1"; }
print_error() { echo -e "${RED}${NC} $1"; }
print_info() { echo -e "${CYAN}${NC} $1"; }
print_step() { echo -e "\n${GREEN}==>${NC} $1"; }
print_header() {
echo -e "\n${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}${NC} ADLee Theme System-wide Deployment ${BLUE}${NC}"
echo -e "${BLUE}${NC} ${ZSH_THEME_NAME} Theme System-wide Deployment ${BLUE}${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}\n"
}
# Check if running as root
check_root() {
if [[ $EUID -ne 0 ]]; then
print_error "This script must be run as root (use sudo)"
echo "Usage: sudo $0 [--all|--current]"
echo "Usage: sudo $0 [--all|--current|--status]"
exit 1
fi
}
# Ask yes/no question
ask_yes_no() {
local prompt="$1"
local default="${2:-y}"
@@ -78,17 +82,14 @@ ask_yes_no() {
read -p "$prompt" response
response=${response:-$default}
[[ "$response" =~ ^[Yy]$ ]]
}
# Check if a path is a symlink pointing to master theme
is_system_symlink() {
local path="$1"
[[ -L "$path" ]] && [[ "$(readlink -f "$path")" == "$MASTER_THEME_PATH" ]]
}
# Check if a path is a local symlink (from dotfiles)
is_local_symlink() {
local path="$1"
if [[ -L "$path" ]]; then
@@ -99,13 +100,6 @@ is_local_symlink() {
fi
}
# Check if a path is a regular file
is_regular_file() {
local path="$1"
[[ -f "$path" ]] && [[ ! -L "$path" ]]
}
# Get link status description
get_link_status() {
local path="$1"
@@ -115,7 +109,7 @@ get_link_status() {
echo "system_link"
elif is_local_symlink "$path"; then
echo "local_link"
elif is_regular_file "$path"; then
elif [[ -f "$path" ]] && [[ ! -L "$path" ]]; then
echo "regular_file"
elif [[ -L "$path" ]]; then
echo "other_link"
@@ -125,93 +119,58 @@ get_link_status() {
}
# ============================================================================
# Master Theme Setup
# Setup Functions
# ============================================================================
setup_master_location() {
print_step "Setting up master theme location"
# Create directory if it doesn't exist
if [[ ! -d "$MASTER_THEME_DIR" ]]; then
mkdir -p "$MASTER_THEME_DIR"
print_success "Created directory: $MASTER_THEME_DIR"
fi
[[ ! -d "$MASTER_THEME_DIR" ]] && mkdir -p "$MASTER_THEME_DIR" && print_success "Created: $MASTER_THEME_DIR"
# Determine source file
local source_file=""
[[ -f "$SOURCE_THEME" ]] && source_file="$SOURCE_THEME"
[[ -z "$source_file" && -f "$THEME_FILE" ]] && source_file="$THEME_FILE"
[[ -z "$source_file" && -f "$HOME/.oh-my-zsh/themes/$THEME_FILE" ]] && source_file="$HOME/.oh-my-zsh/themes/$THEME_FILE"
if [[ -f "$SOURCE_THEME" ]]; then
source_file="$SOURCE_THEME"
elif [[ -f "$THEME_NAME" ]]; then
source_file="$THEME_NAME"
elif [[ -f "$HOME/.oh-my-zsh/themes/$THEME_NAME" ]]; then
source_file="$HOME/.oh-my-zsh/themes/$THEME_NAME"
fi
# Copy or verify master theme
if [[ -f "$MASTER_THEME_PATH" ]]; then
print_info "Master theme already exists: $MASTER_THEME_PATH"
if [[ -n "$source_file" ]]; then
# Check if update is needed
if ! diff -q "$source_file" "$MASTER_THEME_PATH" &>/dev/null; then
print_warning "Source theme differs from master"
if ask_yes_no "Update master theme from source?"; then
cp "$source_file" "$MASTER_THEME_PATH"
chmod 644 "$MASTER_THEME_PATH"
print_success "Master theme updated"
fi
else
print_success "Master theme is up to date"
print_info "Master theme exists: $MASTER_THEME_PATH"
if [[ -n "$source_file" ]] && ! diff -q "$source_file" "$MASTER_THEME_PATH" &>/dev/null; then
print_warning "Source differs from master"
if ask_yes_no "Update master theme?"; then
cp "$source_file" "$MASTER_THEME_PATH"
chmod 644 "$MASTER_THEME_PATH"
print_success "Master theme updated"
fi
fi
else
if [[ -z "$source_file" ]]; then
print_error "Theme file not found. Please ensure $THEME_NAME exists in:"
print_error "Theme file not found. Check these locations:"
echo " - $SOURCE_THEME"
echo " - ./$THEME_NAME"
echo " - ~/.oh-my-zsh/themes/$THEME_NAME"
echo " - ./$THEME_FILE"
exit 1
fi
cp "$source_file" "$MASTER_THEME_PATH"
chmod 644 "$MASTER_THEME_PATH"
print_success "Copied theme to master location"
fi
}
# ============================================================================
# User Detection and Selection
# ============================================================================
get_users_with_tty() {
local users=()
[[ -d "/root/.oh-my-zsh" ]] && users+=("root")
# Add root if oh-my-zsh is installed
if [[ -d "/root/.oh-my-zsh" ]]; then
users+=("root")
fi
# Find regular users with oh-my-zsh
while IFS=: read -r username _ uid _ _ home_dir shell; do
# Skip system users (UID < 1000)
while IFS=: read -r username _ uid _ _ home_dir _; do
[[ $uid -lt 1000 ]] && continue
# Check if user has oh-my-zsh
if [[ -d "$home_dir/.oh-my-zsh" ]]; then
users+=("$username")
fi
[[ -d "$home_dir/.oh-my-zsh" ]] && users+=("$username")
done < /etc/passwd
echo "${users[@]}"
}
get_current_user() {
# Get the user who invoked sudo
if [[ -n "${SUDO_USER:-}" ]]; then
echo "$SUDO_USER"
else
# Fallback to first non-root user with oh-my-zsh
while IFS=: read -r username _ uid _ _ home_dir _; do
if [[ $uid -ge 1000 ]] && [[ -d "$home_dir/.oh-my-zsh" ]]; then
echo "$username"
@@ -231,22 +190,14 @@ select_users() {
;;
current)
local current_user=$(get_current_user)
if [[ -n "$current_user" ]]; then
users=("$current_user")
fi
if [[ -d "/root/.oh-my-zsh" ]]; then
users+=("root")
fi
[[ -n "$current_user" ]] && users=("$current_user")
[[ -d "/root/.oh-my-zsh" ]] && users+=("root")
;;
interactive)
local all_users=($(get_users_with_tty))
[[ ${#all_users[@]} -eq 0 ]] && { print_error "No users with oh-my-zsh found"; exit 1; }
if [[ ${#all_users[@]} -eq 0 ]]; then
print_error "No users with oh-my-zsh found"
exit 1
fi
echo "Users with oh-my-zsh detected:"
echo "Users with oh-my-zsh:"
for i in "${!all_users[@]}"; do
echo " $((i+1)). ${all_users[$i]}"
done
@@ -256,16 +207,8 @@ select_users() {
users=("${all_users[@]}")
else
local current_user=$(get_current_user)
if [[ -n "$current_user" ]]; then
users=("$current_user")
print_info "Selected: $current_user"
fi
if [[ -d "/root/.oh-my-zsh" ]]; then
if ask_yes_no "Include root user?"; then
users+=("root")
fi
fi
[[ -n "$current_user" ]] && users=("$current_user") && print_info "Selected: $current_user"
[[ -d "/root/.oh-my-zsh" ]] && ask_yes_no "Include root?" && users+=("root")
fi
;;
esac
@@ -273,322 +216,130 @@ select_users() {
echo "${users[@]}"
}
# ============================================================================
# Deployment Functions
# ============================================================================
analyze_user_theme() {
local username="$1"
local home_dir
if [[ "$username" == "root" ]]; then
home_dir="/root"
else
home_dir=$(eval echo "~$username")
fi
local theme_path="$home_dir/.oh-my-zsh/themes/$THEME_NAME"
local status=$(get_link_status "$theme_path")
echo "$status"
}
deploy_for_user() {
local username="$1"
local home_dir
local home_dir=$([[ "$username" == "root" ]] && echo "/root" || eval echo "~$username")
# Get home directory
if [[ "$username" == "root" ]]; then
home_dir="/root"
else
home_dir=$(eval echo "~$username")
fi
[[ ! -d "$home_dir" ]] && { print_warning "Home not found: $username"; return 1; }
[[ ! -d "$home_dir/.oh-my-zsh" ]] && { print_warning "oh-my-zsh not installed: $username"; return 1; }
# Check if user's home directory exists
if [[ ! -d "$home_dir" ]]; then
print_warning "Home directory not found for user: $username"
return 1
fi
local oh_my_zsh_themes="$home_dir/.oh-my-zsh/themes"
local theme_link="$oh_my_zsh_themes/$THEME_NAME"
# Check if oh-my-zsh is installed
if [[ ! -d "$home_dir/.oh-my-zsh" ]]; then
print_warning "oh-my-zsh not installed for user: $username"
return 1
fi
# Analyze current status
local theme_link="$home_dir/.oh-my-zsh/themes/$THEME_FILE"
local status=$(get_link_status "$theme_link")
case "$status" in
system_link)
if [[ "$FORCE_REPLACE" == true ]]; then
print_info "Recreating system-wide link for: $username"
else
print_success "✓ Already using system-wide theme: $username"
return 0
fi
;;
local_link)
print_info "Converting local symlink → system-wide for: $username"
;;
regular_file)
print_warning "Replacing regular file → system-wide for: $username"
;;
other_link)
print_warning "Replacing unknown symlink → system-wide for: $username"
;;
not_present)
print_info "Creating new system-wide link for: $username"
[[ "$FORCE_REPLACE" != true ]] && { print_success "Already system-wide: $username"; return 0; }
print_info "Recreating link: $username"
;;
local_link) print_info "Converting local → system: $username" ;;
regular_file) print_warning "Replacing file → system: $username" ;;
*) print_info "Creating link: $username" ;;
esac
# Create themes directory if it doesn't exist
if [[ ! -d "$oh_my_zsh_themes" ]]; then
mkdir -p "$oh_my_zsh_themes"
if [[ "$username" != "root" ]]; then
chown "$username:$(id -gn "$username" 2>/dev/null || echo "$username")" "$oh_my_zsh_themes"
fi
fi
# Remove existing file/link (this is the key fix!)
if [[ -e "$theme_link" ]] || [[ -L "$theme_link" ]]; then
rm -f "$theme_link"
fi
# Create symlink to master theme
mkdir -p "$home_dir/.oh-my-zsh/themes"
rm -f "$theme_link"
ln -sf "$MASTER_THEME_PATH" "$theme_link"
# Fix ownership
if [[ "$username" != "root" ]]; then
chown -h "$username:$(id -gn "$username" 2>/dev/null || echo "$username")" "$theme_link" 2>/dev/null || true
fi
[[ "$username" != "root" ]] && chown -h "$username:$(id -gn "$username" 2>/dev/null || echo "$username")" "$theme_link" 2>/dev/null || true
# Verify the symlink was created correctly
if is_system_symlink "$theme_link"; then
print_success "✓ Deployed system-wide theme for: $username"
else
print_error "✗ Failed to create system-wide link for: $username"
return 1
fi
is_system_symlink "$theme_link" && print_success "Deployed: $username" || { print_error "Failed: $username"; return 1; }
}
# ============================================================================
# Status and Reporting
# ============================================================================
show_deployment_status() {
print_step "Current deployment status"
print_step "Deployment status"
local users=($(get_users_with_tty))
if [[ ${#users[@]} -eq 0 ]]; then
print_warning "No users with oh-my-zsh found"
return
fi
[[ ${#users[@]} -eq 0 ]] && { print_warning "No users with oh-my-zsh"; return; }
echo
printf "%-20s %-20s %s\n" "User" "Status" "Details"
printf "%-20s %-20s %s\n" "----" "------" "-------"
for user in "${users[@]}"; do
local status=$(analyze_user_theme "$user")
local home_dir
if [[ "$user" == "root" ]]; then
home_dir="/root"
else
home_dir=$(eval echo "~$user")
fi
local theme_path="$home_dir/.oh-my-zsh/themes/$THEME_NAME"
local home_dir=$([[ "$user" == "root" ]] && echo "/root" || eval echo "~$user")
local theme_path="$home_dir/.oh-my-zsh/themes/$THEME_FILE"
local status=$(get_link_status "$theme_path")
case "$status" in
system_link)
printf "%-20s ${GREEN}%-20s${NC} %s\n" "$user" "System-wide ✓" "$MASTER_THEME_PATH"
;;
local_link)
local target=$(readlink "$theme_path")
printf "%-20s ${YELLOW}%-20s${NC} %s\n" "$user" "Local symlink" "$target"
;;
regular_file)
printf "%-20s ${CYAN}%-20s${NC} %s\n" "$user" "Regular file" "(standalone copy)"
;;
other_link)
local target=$(readlink "$theme_path" 2>/dev/null || echo "broken")
printf "%-20s ${YELLOW}%-20s${NC} %s\n" "$user" "Other symlink" "$target"
;;
not_present)
printf "%-20s ${RED}%-20s${NC} %s\n" "$user" "Not installed" ""
;;
*)
printf "%-20s ${RED}%-20s${NC} %s\n" "$user" "Unknown" ""
;;
system_link) printf "%-20s ${GREEN}%-20s${NC} %s\n" "$user" "System-wide ✓" "$MASTER_THEME_PATH" ;;
local_link) printf "%-20s ${YELLOW}%-20s${NC} %s\n" "$user" "Local symlink" "$(readlink "$theme_path")" ;;
regular_file) printf "%-20s ${CYAN}%-20s${NC} %s\n" "$user" "Regular file" "(standalone)" ;;
not_present) printf "%-20s ${RED}%-20s${NC}\n" "$user" "Not installed" ;;
*) printf "%-20s ${RED}%-20s${NC}\n" "$user" "Unknown" ;;
esac
done
echo
}
# ============================================================================
# Main Execution
# ============================================================================
show_summary() {
echo
echo "============================================================================"
echo "Deployment Summary"
echo "============================================================================"
echo "Master theme location: $MASTER_THEME_PATH"
echo "Master theme: $MASTER_THEME_PATH"
echo
echo "To update the theme in the future:"
echo " 1. Edit: $MASTER_THEME_PATH"
echo " 2. All users will get updates automatically (via symlinks)"
echo "To update theme globally:"
echo " sudo cp $SOURCE_THEME $MASTER_THEME_PATH"
echo
echo "Alternatively, update from your dotfiles:"
echo " sudo cp ~/.dotfiles/zsh/themes/$THEME_NAME $MASTER_THEME_PATH"
echo
echo "To check deployment status:"
echo " sudo $0 --status"
echo "Check status: sudo $0 --status"
echo "============================================================================"
}
# ============================================================================
# Main
# ============================================================================
main() {
local mode="interactive"
local status_only=false
# Parse arguments
for arg in "$@"; do
case "$arg" in
--all)
mode="all"
;;
--current)
mode="current"
;;
--force)
FORCE_REPLACE=true
;;
--status|-s)
status_only=true
;;
--all) mode="all" ;;
--current) mode="current" ;;
--force) FORCE_REPLACE=true ;;
--status|-s) status_only=true ;;
--help|-h)
echo "Usage: sudo $0 [OPTIONS]"
echo
echo "Options:"
echo " --all Deploy to all users with oh-my-zsh"
echo " --current Deploy to current user and root only"
echo " --force Force replacement even if system-wide link exists"
echo " --status Show current deployment status"
echo " --help Show this help message"
echo
echo "Examples:"
echo " sudo $0 # Interactive mode"
echo " sudo $0 --all # Deploy to all users"
echo " sudo $0 --current --force # Force update for current user + root"
echo
echo " --all Deploy to all users with oh-my-zsh"
echo " --current Deploy to current user and root"
echo " --force Force replacement of existing links"
echo " --status Show current deployment status"
echo " --help Show this help"
exit 0
;;
*)
print_error "Unknown option: $arg"
echo "Use --help for usage information"
exit 1
;;
*) print_error "Unknown option: $arg"; exit 1 ;;
esac
done
print_header
check_root
# Status only mode
if [[ "$status_only" == true ]]; then
show_deployment_status
exit 0
fi
# Show current status first
show_deployment_status
# Setup master location
setup_master_location
# Select users
local users=($(select_users "$mode"))
[[ ${#users[@]} -eq 0 ]] && { print_error "No users selected"; exit 1; }
if [[ ${#users[@]} -eq 0 ]]; then
print_error "No users selected for deployment"
exit 1
fi
# Print info about selected mode
case "$mode" in
all)
print_info "Deploying to all users with oh-my-zsh"
;;
current)
print_info "Deploying to current user and root"
;;
esac
echo
print_step "Deploying to ${#users[@]} user(s): ${users[*]}"
[[ "$FORCE_REPLACE" == true ]] && print_warning "Force mode enabled"
if [[ "$FORCE_REPLACE" == true ]]; then
print_warning "Force mode: will replace ALL existing links"
fi
ask_yes_no "Proceed?" || { print_warning "Cancelled"; exit 0; }
echo
# Interactive confirmation for converting local links
if [[ "$mode" == "interactive" ]]; then
local has_local_links=false
for user in "${users[@]}"; do
local status=$(analyze_user_theme "$user")
if [[ "$status" == "local_link" ]]; then
has_local_links=true
break
fi
done
if [[ "$has_local_links" == true ]]; then
echo "⚠ Some users have local dotfiles symlinks."
echo "This will replace them with system-wide symlinks pointing to:"
echo " $MASTER_THEME_PATH"
echo
if ! ask_yes_no "Convert local symlinks to system-wide?"; then
print_warning "Deployment cancelled"
exit 0
fi
fi
fi
if ! ask_yes_no "Proceed with deployment?"; then
print_warning "Deployment cancelled"
exit 0
fi
# Deploy to each user
echo
local deployed_count=0
local failed_count=0
local ok=0 fail=0
for user in "${users[@]}"; do
if deploy_for_user "$user"; then
((deployed_count++))
else
((failed_count++))
fi
deploy_for_user "$user" && ((ok++)) || ((fail++))
done
echo
if [[ $failed_count -eq 0 ]]; then
print_success "Deployment complete! ($deployed_count/${#users[@]} users)"
else
print_warning "Deployment finished with errors ($deployed_count succeeded, $failed_count failed)"
fi
[[ $fail -eq 0 ]] && print_success "Complete! ($ok/${#users[@]})" || print_warning "Done with errors ($ok ok, $fail failed)"
# Show updated status
echo
show_deployment_status
show_summary
}