Commit local changes before merging with remote

This commit is contained in:
Peter Wood
2025-05-29 11:25:02 -04:00
parent 868b340fb5
commit be4f6a8d8c
75 changed files with 14107 additions and 562 deletions

View File

@@ -11,10 +11,20 @@ ENV DEBIAN_FRONTEND=noninteractive
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
&& apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y curl git sudo wget
&& apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y \
curl git sudo wget
# Pre-install cowsay and lolcat packages for testing
RUN apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y cowsay lolcat
# Pre-install essential packages from packages.list for faster testing
RUN apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y \
python3 \
bat \
cowsay \
lolcat \
fzf \
zsh \
nala \
fd-find \
eza
# Create logs directory with proper permissions
RUN mkdir -p /logs && chmod -R 777 /logs
@@ -28,15 +38,21 @@ WORKDIR /home/testuser
# Create directory structure for shell setup
RUN mkdir -p /home/testuser/shell/setup
RUN mkdir -p /home/testuser/shell/dotfiles
# Copy test script, startup script, and packages.list
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
# Copy all necessary setup files
COPY --chown=testuser:testuser test-setup.sh /home/testuser/shell/setup/
COPY --chown=testuser:testuser startup.sh /home/testuser/
COPY --chown=testuser:testuser packages.list /home/testuser/shell/
COPY --chown=testuser:testuser setup.sh /home/testuser/shell/setup/
COPY --chown=testuser:testuser bootstrap.sh /home/testuser/shell/setup/
COPY --chown=testuser:testuser packages.list /home/testuser/shell/setup/
COPY --chown=testuser:testuser my-aliases.zsh.template /home/testuser/shell/dotfiles/
# Make scripts executable
RUN chmod +x /home/testuser/test-setup.sh
RUN chmod +x /home/testuser/shell/setup/test-setup.sh
RUN chmod +x /home/testuser/startup.sh
RUN chmod +x /home/testuser/shell/setup/setup.sh
RUN chmod +x /home/testuser/shell/setup/bootstrap.sh
CMD ["/bin/bash", "-c", "./startup.sh"]
@@ -67,14 +83,20 @@ WORKDIR /home/testuser
# Create directory structure for shell setup
RUN mkdir -p /home/testuser/shell/setup
RUN mkdir -p /home/testuser/shell/dotfiles
# Copy test script, startup script, and packages.list
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
COPY --chown=testuser:testuser startup.sh /home/testuser/
COPY --chown=testuser:testuser packages.list /home/testuser/shell/
# Copy all necessary setup files
COPY --chown=testuser:testuser test-setup.sh /home/testuser/shell/setup/
COPY --chown=testuser:testuser startup.sh /home/testuser/
COPY --chown=testuser:testuser setup.sh /home/testuser/shell/setup/
COPY --chown=testuser:testuser bootstrap.sh /home/testuser/shell/setup/
COPY --chown=testuser:testuser packages.list /home/testuser/shell/setup/
COPY --chown=testuser:testuser my-aliases.zsh.template /home/testuser/shell/dotfiles/
# Make scripts executable
RUN chmod +x /home/testuser/test-setup.sh
RUN chmod +x /home/testuser/shell/setup/test-setup.sh
RUN chmod +x /home/testuser/startup.sh
RUN chmod +x /home/testuser/shell/setup/setup.sh
RUN chmod +x /home/testuser/shell/setup/bootstrap.sh
CMD ["/bin/bash", "-c", "./startup.sh"]

View File

@@ -47,6 +47,12 @@ if ! command -v git &>/dev/null; then
sudo nala install -y git
;;
dnf)
# Enable COPR repositories for Fedora before installing packages
if [ "$OS_NAME" = "fedora" ]; then
echo -e "${YELLOW}Setting up COPR repositories for Fedora...${NC}"
sudo dnf copr enable -y alternateved/eza 2>/dev/null || echo -e "${YELLOW}Eza COPR repo already enabled or unavailable${NC}"
sudo dnf copr enable -y shaps/lazygit 2>/dev/null || echo -e "${YELLOW}Lazygit COPR repo already enabled or unavailable${NC}"
fi
sudo dnf install -y git
;;
apt)
@@ -71,6 +77,7 @@ fi
# Make scripts executable
chmod +x "$DOTFILES_DIR/setup/setup.sh"
chmod +x "$DOTFILES_DIR/completions/backup-scripts-completion.bash" 2>/dev/null || true
# Run setup script
"$DOTFILES_DIR/setup/setup.sh"

View File

View File

@@ -1,11 +1,23 @@
// Essential packages for shell setup
// Cross-platform package list with fallbacks handled in setup scripts
// Core tools
git
python3
wget
curl
bat
cowsay
lolcat
fzf
zsh
nala
fd-find
// Enhanced shell tools
bat // Modern cat alternative (available as 'batcat' on Ubuntu/Debian)
cowsay // Fun ASCII art
lolcat // Colorful text output
fzf // Fuzzy finder
zsh // Z shell
nala // Modern apt frontend
fd-find // Modern find alternative (available as 'fd' or 'fdfind')
eza // Modern ls alternative
// Note: lazygit and lazydocker require special installation (snap/GitHub releases)
// These are handled separately in the setup script
// lazygit
// lazydocker

View File

@@ -39,7 +39,7 @@ determine_pkg_manager() {
# Set up package management based on OS
if [ "$OS_NAME" = "fedora" ]; then
echo -e "${YELLOW}Setting up Fedora Tsrepositories and package management...${NC}"
echo -e "${YELLOW}Setting up Fedora repositories and package management...${NC}"
# Install prerequisites for Fedora
sudo dnf install -y wget gpg
@@ -55,6 +55,14 @@ if [ "$OS_NAME" = "fedora" ]; then
# Use a different approach to add the GitHub CLI repo to avoid the "--add-repo" error
sudo curl -fsSL https://cli.github.com/packages/rpm/gh-cli.repo -o /etc/yum.repos.d/gh-cli.repo
# Setup COPR repository for eza
echo -e "${YELLOW}Setting up COPR repository for eza...${NC}"
sudo dnf copr enable -y alternateved/eza
# Setup COPR repository for lazygit
echo -e "${YELLOW}Setting up COPR repository for lazygit...${NC}"
sudo dnf copr enable -y shaps/lazygit
# Update package lists
echo -e "${YELLOW}Updating package lists for Fedora...${NC}"
sudo dnf check-update -y || true
@@ -90,6 +98,19 @@ else
fi
fi
# Setup eza repository for Ubuntu/Debian
echo -e "${YELLOW}Setting up eza repository...${NC}"
if ! apt-cache show eza &>/dev/null; then
# Add eza repository for older Ubuntu/Debian versions
echo -e "${YELLOW}Adding eza repository...${NC}"
sudo mkdir -p -m 755 /etc/apt/keyrings
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
sudo chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list
else
echo -e "${GREEN}Eza is available in standard repositories${NC}"
fi
# Setup VS Code repository
echo -e "${YELLOW}Setting up VS Code repository...${NC}"
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /tmp/packages.microsoft.gpg
@@ -130,22 +151,40 @@ PKG_MANAGER=$(determine_pkg_manager)
echo -e "${GREEN}Using package manager: $PKG_MANAGER${NC}"
# Load packages from package list
mapfile -t pkgs < <(grep -v '^//' "$SCRIPT_DIR/packages.list" | grep -v -e '^$')
mapfile -t pkgs < <(grep -v '^//' "$SCRIPT_DIR/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$')
# Map Debian/Ubuntu package names to Fedora equivalents if needed
declare -A fedora_pkg_map
fedora_pkg_map["bat"]="bat"
fedora_pkg_map["fd-find"]="fd" # On Fedora, the package is called 'fd'
# eza is available from COPR repository
fedora_pkg_map["eza"]="eza"
# lazygit is available from COPR repository
fedora_pkg_map["lazygit"]="lazygit"
# lazydocker will be installed manually from GitHub releases
# Add more package mappings as needed
# Process the package list based on OS
install_pkg_list=()
special_installs=()
for pkg in "${pkgs[@]}"; do
# Skip nala package on non-Debian/Ubuntu systems
if [ "$pkg" = "nala" ] && [ "$OS_NAME" != "ubuntu" ] && [ "$OS_NAME" != "debian" ]; then
continue
fi
# Handle packages that need special installation
if [ "$pkg" = "lazydocker" ]; then
special_installs+=("$pkg")
continue
fi
# Handle lazygit - available in COPR for Fedora, special install for Debian/Ubuntu
if [ "$pkg" = "lazygit" ] && [ "$OS_NAME" != "fedora" ]; then
special_installs+=("$pkg")
continue
fi
# Check if we need to map the package name for Fedora
if [ "$OS_NAME" = "fedora" ] && [[ -n "${fedora_pkg_map[$pkg]}" ]]; then
install_pkg_list+=("${fedora_pkg_map[$pkg]}")
@@ -165,10 +204,13 @@ case $PKG_MANAGER in
sudo rm -f /etc/apt/sources.list.d/nala-sources.list 2>/dev/null
# Try to fetch mirrors with less aggressive settings
if ! sudo nala fetch --auto --fetches 1 --country auto; then
echo -e "${YELLOW}Mirror selection failed, continuing with system default mirrors...${NC}"
echo -e "${YELLOW}Attempting to find faster mirrors (this may fail and that's okay)...${NC}"
if ! sudo nala fetch --auto --fetches 1 --country auto 2>/dev/null; then
echo -e "${YELLOW}Note: Fast mirror selection failed, using default mirrors (this is normal and safe)${NC}"
# Remove any potentially corrupted Nala sources
sudo rm -f /etc/apt/sources.list.d/nala-sources.list 2>/dev/null
else
echo -e "${GREEN}Fast mirrors configured successfully!${NC}"
fi
# Install packages using Nala
@@ -189,6 +231,44 @@ esac
echo -e "${GREEN}Package installation completed for $OS_NAME $OS_VERSION.${NC}"
# Handle special installations that aren't available through package managers
echo -e "${YELLOW}Installing special packages...${NC}"
for pkg in "${special_installs[@]}"; do
case $pkg in
"lazydocker")
if ! command -v lazydocker &> /dev/null; then
echo -e "${YELLOW}Installing Lazydocker from GitHub releases...${NC}"
LAZYDOCKER_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazydocker/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
curl -Lo lazydocker.tar.gz "https://github.com/jesseduffield/lazydocker/releases/latest/download/lazydocker_${LAZYDOCKER_VERSION}_Linux_x86_64.tar.gz"
mkdir -p lazydocker-temp
tar xf lazydocker.tar.gz -C lazydocker-temp
sudo mv lazydocker-temp/lazydocker /usr/local/bin
rm -rf lazydocker-temp lazydocker.tar.gz
echo -e "${GREEN}Lazydocker installed successfully!${NC}"
else
echo -e "${GREEN}Lazydocker is already installed${NC}"
fi
;;
"lazygit")
if ! command -v lazygit &> /dev/null; then
echo -e "${YELLOW}Installing Lazygit from GitHub releases...${NC}"
LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz"
mkdir -p lazygit-temp
tar xf lazygit.tar.gz -C lazygit-temp
sudo mv lazygit-temp/lazygit /usr/local/bin
rm -rf lazygit-temp lazygit.tar.gz
echo -e "${GREEN}Lazygit installed successfully!${NC}"
else
echo -e "${GREEN}Lazygit is already installed${NC}"
fi
;;
*)
echo -e "${YELLOW}Unknown special package: $pkg${NC}"
;;
esac
done
# Install Zsh if not already installed
echo -e "${YELLOW}Installing Zsh...${NC}"
if ! command -v zsh &> /dev/null; then
@@ -247,20 +327,6 @@ else
echo -e "${YELLOW}Warning: nvm installation may require a new shell session${NC}"
fi
# Install Lazydocker (not available in apt repositories)
echo -e "${YELLOW}Installing Lazydocker...${NC}"
if ! command -v lazydocker &> /dev/null; then
LAZYDOCKER_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazydocker/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
curl -Lo lazydocker.tar.gz "https://github.com/jesseduffield/lazydocker/releases/latest/download/lazydocker_${LAZYDOCKER_VERSION}_Linux_x86_64.tar.gz"
mkdir -p lazydocker-temp
tar xf lazydocker.tar.gz -C lazydocker-temp
sudo mv lazydocker-temp/lazydocker /usr/local/bin
rm -rf lazydocker-temp lazydocker.tar.gz
echo -e "${GREEN}Lazydocker installed successfully!${NC}"
else
echo -e "Lazydocker is already installed"
fi
# Define a reusable function for cloning Zsh plugins
clone_zsh_plugin() {
local plugin_url=$1
@@ -279,6 +345,24 @@ clone_zsh_plugin "https://github.com/zsh-users/zsh-autosuggestions" "$PLUGINS_DI
clone_zsh_plugin "https://github.com/zsh-users/zsh-syntax-highlighting" "$PLUGINS_DIR/zsh-syntax-highlighting"
clone_zsh_plugin "https://github.com/MichaelAquilina/zsh-you-should-use" "$PLUGINS_DIR/zsh-you-should-use"
# Set up bash completion for backup scripts
echo -e "${YELLOW}Setting up bash completion for backup scripts...${NC}"
COMPLETION_SCRIPT="$DOTFILES_DIR/completions/backup-scripts-completion.bash"
if [ -f "$COMPLETION_SCRIPT" ]; then
# Create completions directory in home
mkdir -p "$HOME/.local/share/bash-completion/completions"
# Copy completion script to user's completion directory
cp "$COMPLETION_SCRIPT" "$HOME/.local/share/bash-completion/completions/"
# Make sure it's executable
chmod +x "$HOME/.local/share/bash-completion/completions/backup-scripts-completion.bash"
echo -e "${GREEN}Bash completion script installed successfully!${NC}"
else
echo -e "${YELLOW}Warning: Bash completion script not found at $COMPLETION_SCRIPT${NC}"
fi
# Set up dotfiles
echo -e "${YELLOW}Setting up dotfiles...${NC}"
# Consolidate symbolic link creation for dotfiles
@@ -294,10 +378,23 @@ ALIASES_FILE="$ZSH_CUSTOM/aliases.zsh"
mkdir -p "$ZSH_CUSTOM"
# Create a copy of the original aliases file for backup
cp "$DOTFILES_SUBDIR/my-aliases.zsh" "$ALIASES_FILE.bak"
cp "$DOTFILES_SUBDIR/my-aliases.zsh.original" "$ALIASES_FILE.bak"
# First, copy all general aliases except those we'll modify based on OS
grep -v "alias cat=" "$DOTFILES_SUBDIR/my-aliases.zsh" | grep -v "alias fd=" | grep -v "alias fzf=" > "$ALIASES_FILE"
# First, copy all general aliases except those we'll modify based on OS and available commands
grep -v "^alias cat=" "$DOTFILES_SUBDIR/my-aliases.zsh.original" | \
grep -v "^alias fd=" | \
grep -v "^alias fzf=" | \
grep -v "^alias ls=" | \
grep -v "^alias ll=" | \
grep -v "^alias la=" | \
grep -v "^alias l=" | \
grep -v "^alias tree=" | \
grep -v "^alias lt=" | \
grep -v "^alias llt=" | \
grep -v "^alias lg=" | \
grep -v "^alias lh=" | \
grep -v "^alias lr=" | \
grep -v "^alias lx=" > "$ALIASES_FILE"
# Function to check for command existence and add appropriate alias
add_conditional_alias() {
@@ -342,13 +439,39 @@ if command -v fzf &> /dev/null; then
fi
fi
# Also create a symlink from the custom aliases file back to the dotfiles directory for persistence
# This allows changes made to aliases.zsh to be tracked in the dotfiles repo
echo -e "${YELLOW}Creating symlink to save customized aliases back to dotfiles...${NC}"
# Set up eza aliases if eza is available
if command -v eza &> /dev/null; then
echo -e "${YELLOW}Setting up eza aliases...${NC}"
cat >> "$ALIASES_FILE" << 'EOF'
# 🌟 Eza aliases - Modern replacement for ls
alias ls="eza --icons=always -a --color=auto --group-directories-first"
alias la="eza --icons=always -la --color=auto --group-directories-first"
alias ll="eza --icons=always -la --classify=always -h --color=auto --group-directories-first"
alias l="eza --icons=always -1 -a --color=auto --group-directories-first"
alias lt="eza --icons=always -a --tree --level=2 --color=auto --group-directories-first"
alias llt="eza --icons=always -la --tree --level=2 --color=auto --group-directories-first"
alias lg="eza --icons=always -la --git --color=auto --group-directories-first"
alias lh="eza --icons=always -la --color=auto --group-directories-first --sort=size"
alias lr="eza --icons=always -la --color=auto --group-directories-first --sort=modified"
alias lx="eza --icons=always -la --color=auto --group-directories-first --sort=extension"
alias tree="eza --icons=always -a --tree --color=auto --group-directories-first"
EOF
echo -e "${GREEN}Eza aliases configured successfully!${NC}"
else
echo -e "${YELLOW}Eza not found. Using traditional ls aliases.${NC}"
cat >> "$ALIASES_FILE" << 'EOF'
# Traditional ls aliases
alias ll="ls -laFh --group-directories-first --color=auto"
EOF
fi
# Save the customized aliases to the dotfiles directory for reference
echo -e "${YELLOW}Saving customized aliases to dotfiles directory...${NC}"
if [ -f "$ALIASES_FILE" ]; then
# Save a copy of the original for reference
cp "$DOTFILES_SUBDIR/my-aliases.zsh" "$DOTFILES_SUBDIR/my-aliases.zsh.original" 2>/dev/null || true
# Replace the my-aliases.zsh with the new customized one
# Copy the customized aliases to the dotfiles directory as my-aliases.zsh
# This file will be ignored by git but serves as a local reference
cp "$ALIASES_FILE" "$DOTFILES_SUBDIR/my-aliases.zsh"
fi

View File

@@ -25,7 +25,7 @@ echo -e "${BLUE}Checking for packages.list:${NC}"
if [ -f "$HOME/shell/setup/packages.list" ]; then
echo -e "- packages.list: ${GREEN}Found${NC}"
# Count packages in list (excluding comments and empty lines)
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$' | wc -l)
echo -e "- Package count: ${GREEN}$pkg_count packages${NC}"
else
echo -e "- packages.list: ${RED}Not found${NC}"
@@ -36,19 +36,19 @@ fi
echo -e "${BLUE}Setting up logs directory:${NC}"
if [ -d "/logs" ]; then
echo -e "- Logs directory: ${GREEN}Found${NC}"
# Check ownership and permissions
logs_owner=$(stat -c '%U:%G' /logs)
echo -e "- Current ownership: $logs_owner"
echo "- Setting permissions on /logs directory..."
sudo chown -R $(whoami):$(whoami) /logs 2>/dev/null || echo -e "${YELLOW}Failed to set ownership${NC}"
sudo chmod -R 777 /logs 2>/dev/null || echo -e "${YELLOW}Failed to set permissions${NC}"
# Verify permissions are correct
if [ -w "/logs" ]; then
echo -e "- Write permission: ${GREEN}OK${NC}"
# Create a test file to really verify we can write
if touch "/logs/test_file" 2>/dev/null; then
echo -e "- Test write: ${GREEN}Succeeded${NC}"

View File

@@ -17,7 +17,22 @@ MAX_INSTALL_ATTEMPTS=3
CURRENT_ATTEMPT=1
# Log file
# Create logs directory if it doesn't exist and is writable
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
CONTAINER_INFO=""
if [ -f /.dockerenv ]; then
# We're in a container, try to get container info
if [ -f /etc/os-release ]; then
CONTAINER_INFO="$(grep '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"')-"
fi
fi
# Create logs directory if it doesn't exist
LOGS_DIR="/tmp"
if [ ! -d "$LOGS_DIR" ]; then
mkdir -p "$LOGS_DIR"
fi
# Try creating the logs directory if it doesn't exist and is writable
# First, try creating the logs directory in case it doesn't exist
if [ -d "/logs" ] || mkdir -p /logs 2>/dev/null; then
if [ -w "/logs" ]; then
@@ -52,6 +67,23 @@ echo "Starting setup test at $(date)" > "$LOG_FILE" || {
echo "Starting setup test at $(date)" > "$LOG_FILE"
}
# Helper function to log colored output to terminal and clean output to file
log_both() {
local colored_message="$1"
local clean_message="$2"
# Display colored message to terminal
echo -e "$colored_message"
# Log clean message to file
if [ -n "$clean_message" ]; then
echo "$clean_message" >> "$LOG_FILE"
else
# Strip ANSI escape codes for file logging
echo "$colored_message" | sed 's/\x1b\[[0-9;]*m//g' >> "$LOG_FILE"
fi
}
# Identify the system
echo -e "${BLUE}=== System Information ===${NC}"
if [ -f /etc/os-release ]; then
@@ -101,64 +133,115 @@ check_command() {
command -v "$1" &> /dev/null
}
# Refresh the environment after package installation
refresh_environment() {
# Refresh package database
hash -r 2>/dev/null || true
# Update PATH to include common installation directories
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/games:/usr/local/games:$HOME/.local/bin:$PATH"
# Source common profile files if they exist
[ -f /etc/profile ] && source /etc/profile 2>/dev/null || true
[ -f "$HOME/.profile" ] && source "$HOME/.profile" 2>/dev/null || true
[ -f "$HOME/.bashrc" ] && source "$HOME/.bashrc" 2>/dev/null || true
}
test_package() {
local pkg=$1
local cmd=${2:-$1}
local alt_cmd=$3 # Optional alternative command name
echo -en "Testing if $pkg is installed... "
# Special case for cowsay and lolcat which might be in different paths
if [ "$pkg" = "cowsay" ]; then
if check_command "$cmd"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
return 0
elif [ -x "/usr/games/cowsay" ]; then
echo -e "${GREEN}${NC} (in /usr/games)"
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
# Create a symlink to make it available in PATH for other scripts
if [ ! -e "$HOME/.local/bin" ]; then
mkdir -p "$HOME/.local/bin"
# Special case handling for different packages
case "$pkg" in
"python3")
if check_command "python3"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (as python3)" >> "$LOG_FILE"
return 0
fi
if [ ! -e "$HOME/.local/bin/cowsay" ] && [ -w "$HOME/.local/bin" ]; then
ln -sf /usr/games/cowsay "$HOME/.local/bin/cowsay"
echo "Created symlink for cowsay in $HOME/.local/bin" >> "$LOG_FILE"
;;
"bat")
if check_command "bat"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (as bat)" >> "$LOG_FILE"
return 0
elif check_command "batcat"; then
echo -e "${GREEN}${NC} (as batcat)"
echo "$pkg: Installed (as batcat)" >> "$LOG_FILE"
return 0
fi
return 0
fi
elif [ "$pkg" = "lolcat" ]; then
if check_command "$cmd"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
return 0
elif [ -x "/usr/games/lolcat" ]; then
echo -e "${GREEN}${NC} (in /usr/games)"
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
# Create a symlink to make it available in PATH for other scripts
if [ ! -e "$HOME/.local/bin" ]; then
mkdir -p "$HOME/.local/bin"
;;
"fd-find")
if check_command "fd" || check_command "fdfind"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (as fd/fdfind)" >> "$LOG_FILE"
return 0
fi
if [ ! -e "$HOME/.local/bin/lolcat" ] && [ -w "$HOME/.local/bin" ]; then
ln -sf /usr/games/lolcat "$HOME/.local/bin/lolcat"
echo "Created symlink for lolcat in $HOME/.local/bin" >> "$LOG_FILE"
;;
"eza")
if check_command "eza" || check_command "exa"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed" >> "$LOG_FILE"
return 0
fi
return 0
fi
elif check_command "$cmd"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (as $cmd)" >> "$LOG_FILE"
return 0
elif [ -n "$alt_cmd" ] && check_command "$alt_cmd"; then
echo -e "${GREEN}${NC} (as $alt_cmd)"
echo "$pkg: Installed (as $alt_cmd)" >> "$LOG_FILE"
return 0
else
echo -e "${RED}${NC}"
echo "$pkg: Missing" >> "$LOG_FILE"
return 1
fi
# Note: The calling code will handle the failure and continue testing
;;
"cowsay")
if check_command "$cmd"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
return 0
elif [ -x "/usr/games/cowsay" ]; then
echo -e "${GREEN}${NC} (in /usr/games)"
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
# Create a symlink to make it available in PATH for other scripts
if [ ! -e "$HOME/.local/bin" ]; then
mkdir -p "$HOME/.local/bin"
fi
if [ ! -e "$HOME/.local/bin/cowsay" ] && [ -w "$HOME/.local/bin" ]; then
ln -sf /usr/games/cowsay "$HOME/.local/bin/cowsay"
echo "Created symlink for cowsay in $HOME/.local/bin" >> "$LOG_FILE"
fi
return 0
fi
;;
"lolcat")
if check_command "$cmd"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
return 0
elif [ -x "/usr/games/lolcat" ]; then
echo -e "${GREEN}${NC} (in /usr/games)"
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
# Create a symlink to make it available in PATH for other scripts
if [ ! -e "$HOME/.local/bin" ]; then
mkdir -p "$HOME/.local/bin"
fi
if [ ! -e "$HOME/.local/bin/lolcat" ] && [ -w "$HOME/.local/bin" ]; then
ln -sf /usr/games/lolcat "$HOME/.local/bin/lolcat"
echo "Created symlink for lolcat in $HOME/.local/bin" >> "$LOG_FILE"
fi
return 0
fi
;;
*)
if check_command "$cmd"; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed (as $cmd)" >> "$LOG_FILE"
return 0
elif [ -n "$alt_cmd" ] && check_command "$alt_cmd"; then
echo -e "${GREEN}${NC} (as $alt_cmd)"
echo "$pkg: Installed (as $alt_cmd)" >> "$LOG_FILE"
return 0
fi
;;
esac
echo -e "${RED}${NC}"
echo "$pkg: Missing" >> "$LOG_FILE"
return 1
}
test_file_exists() {
@@ -179,7 +262,7 @@ test_file_exists() {
# Get actual package name based on distribution
get_package_name() {
local pkg=$1
# Handle Debian-specific package name differences
if [[ "$ID" == "debian" ]]; then
case "$pkg" in
@@ -201,89 +284,97 @@ install_missing_packages() {
local packages=("$@")
local install_cmd_name
local install_cmd=()
if [ ${#packages[@]} -eq 0 ]; then
echo -e "${GREEN}No packages to install${NC}"
echo "No packages to install" >> "$LOG_FILE"
return 0
fi
echo -e "\n${BLUE}=== Installing missing packages (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===${NC}"
echo "=== Installing missing packages (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===" >> "$LOG_FILE"
# Determine the best installation command
if check_command nala; then
install_cmd=(sudo DEBIAN_FRONTEND=noninteractive nala install -y)
install_cmd=(sudo env DEBIAN_FRONTEND=noninteractive nala install -y)
install_cmd_name="nala"
echo -e "${GREEN}Using nala for package installation${NC}"
echo "Using nala for package installation" >> "$LOG_FILE"
else
install_cmd=(sudo DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install -y)
install_cmd=(sudo env DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install -y)
install_cmd_name="apt-get"
echo -e "${YELLOW}Using apt-get for package installation${NC}"
echo "Using apt-get for package installation" >> "$LOG_FILE"
fi
# Convert package list to distribution-specific names
local install_list=()
for pkg in "${packages[@]}"; do
local actual_pkg=$(get_package_name "$pkg")
install_list+=("$actual_pkg")
done
# Update package lists
echo -e "${YELLOW}Updating package lists...${NC}"
echo "Updating package lists" >> "$LOG_FILE"
if check_command nala; then
echo -e "${GREEN}Running: sudo DEBIAN_FRONTEND=noninteractive nala update${NC}"
sudo DEBIAN_FRONTEND=noninteractive nala update | tee -a "$LOG_FILE"
echo -e "${GREEN}Running: sudo env DEBIAN_FRONTEND=noninteractive nala update${NC}"
sudo env DEBIAN_FRONTEND=noninteractive nala update | tee -a "$LOG_FILE"
else
echo -e "${GREEN}Running: sudo DEBIAN_FRONTEND=noninteractive apt-get update${NC}"
sudo DEBIAN_FRONTEND=noninteractive apt-get update | tee -a "$LOG_FILE"
echo -e "${GREEN}Running: sudo env DEBIAN_FRONTEND=noninteractive apt-get update${NC}"
sudo env DEBIAN_FRONTEND=noninteractive apt-get update | tee -a "$LOG_FILE"
fi
# Install packages
echo -e "${YELLOW}Installing packages: ${install_list[*]}${NC}"
echo "Installing packages: ${install_list[*]}" >> "$LOG_FILE"
# Show the exact command being run for debugging
echo -e "${BLUE}Running: ${install_cmd[*]} ${install_list[*]}${NC}"
# Execute the install command with the package list
if ! "${install_cmd[@]}" "${install_list[@]}" 2>&1 | tee -a "$LOG_FILE"; then
# Use PIPESTATUS to catch apt-get failures even when piped through tee
if bash -c "set -o pipefail; \"${install_cmd[@]}\" \"${install_list[@]}\" 2>&1 | tee -a \"$LOG_FILE\""; then
echo -e "${GREEN}Successfully installed all packages!${NC}"
echo "Successfully installed all packages" >> "$LOG_FILE"
installed_this_round=("${packages[@]}")
# Refresh environment after installation
refresh_environment
return 0
else
echo -e "${RED}Failed to install some packages. Check the log for details.${NC}"
echo "Failed to install some packages" >> "$LOG_FILE"
# Try to install packages one by one to identify problematic ones
echo -e "${YELLOW}Trying to install packages individually...${NC}"
echo "Trying to install packages individually" >> "$LOG_FILE"
installed_this_round=()
local failed_this_round=()
for i in "${!packages[@]}"; do
local pkg="${packages[$i]}"
local actual_pkg="${install_list[$i]}"
echo -en "Installing $pkg as $actual_pkg... "
if "${install_cmd[@]}" "$actual_pkg" >> "$LOG_FILE" 2>&1; then
echo -e "${GREEN}${NC}"
echo "$pkg: Installed successfully" >> "$LOG_FILE"
installed_this_round+=("$pkg")
# Refresh environment after each successful install
refresh_environment
else
echo -e "${RED}${NC}"
echo "$pkg: Installation failed" >> "$LOG_FILE"
failed_this_round+=("$pkg")
fi
done
failed_packages=("${failed_this_round[@]}")
return 1
else
echo -e "${GREEN}Successfully installed all packages!${NC}"
echo "Successfully installed all packages" >> "$LOG_FILE"
installed_this_round=("${packages[@]}")
return 0
fi
}
@@ -362,10 +453,10 @@ fi
if [ -f "$HOME/shell/setup/packages.list" ]; then
echo -e "${YELLOW}Testing package availability in repositories:${NC}"
echo "Testing package availability:" >> "$LOG_FILE"
# Exclude commented lines and empty lines
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$')
# Exclude commented lines and empty lines, and strip inline comments
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$')
for pkg in $packages; do
echo -en "Checking if $pkg is available in repos... "
actual_pkg=$(get_package_name "$pkg")
@@ -410,9 +501,9 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
echo "Testing packages listed in packages.list:" >> "$LOG_FILE"
if [ -f "$HOME/shell/setup/packages.list" ]; then
# Exclude commented lines and empty lines
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$')
# Exclude commented lines and empty lines, and strip inline comments
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$')
for pkg in $packages; do
case "$pkg" in
"bat")
@@ -423,20 +514,20 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
;;
"cowsay")
# Extra debugging for cowsay
echo -e "\n${BLUE}Debugging cowsay package:${NC}" | tee -a "$LOG_FILE"
log_both "\n${BLUE}Debugging cowsay package:${NC}" "Debugging cowsay package:"
if [ -f "/usr/games/cowsay" ]; then
echo -e "- Cowsay found at /usr/games/cowsay" | tee -a "$LOG_FILE"
ls -la /usr/games/cowsay | tee -a "$LOG_FILE"
log_both "- Cowsay found at /usr/games/cowsay"
ls -la /usr/games/cowsay >> "$LOG_FILE"
else
echo -e "- Cowsay not found at /usr/games/cowsay" | tee -a "$LOG_FILE"
log_both "- Cowsay not found at /usr/games/cowsay"
fi
if check_command cowsay; then
echo -e "- Cowsay found in PATH" | tee -a "$LOG_FILE"
command -v cowsay | tee -a "$LOG_FILE"
log_both "- Cowsay found in PATH"
command -v cowsay >> "$LOG_FILE"
else
echo -e "- Cowsay not found in PATH" | tee -a "$LOG_FILE"
log_both "- Cowsay not found in PATH"
fi
if ! test_package "cowsay" "cowsay"; then
((errors++))
missing_packages+=("$pkg")
@@ -457,7 +548,7 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
else
echo -e "- Lolcat not found in PATH" | tee -a "$LOG_FILE"
fi
if ! test_package "lolcat" "lolcat"; then
((errors++))
missing_packages+=("$pkg")
@@ -471,24 +562,24 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
;;
esac
done
# Report missing packages
if [ ${#missing_packages[@]} -gt 0 ]; then
echo -e "\n${YELLOW}Missing packages:${NC}"
for pkg in "${missing_packages[@]}"; do
echo -e "- ${RED}$pkg${NC}"
done
# Count installed vs. total packages
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$' | wc -l)
installed_pkgs=$((total_pkgs - ${#missing_packages[@]}))
echo -e "${GREEN}$installed_pkgs of $total_pkgs packages installed${NC} (${YELLOW}${#missing_packages[@]} missing${NC})"
echo "$installed_pkgs of $total_pkgs packages installed (${#missing_packages[@]} missing)" >> "$LOG_FILE"
# Install missing packages if we haven't reached the maximum attempts
if [ $CURRENT_ATTEMPT -lt $MAX_INSTALL_ATTEMPTS ]; then
install_missing_packages "${missing_packages[@]}"
echo -e "\n${BLUE}=== Installation Results ===${NC}"
if [ ${#installed_this_round[@]} -gt 0 ]; then
echo -e "${GREEN}Successfully installed:${NC}"
@@ -497,7 +588,7 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
done
echo "Successfully installed: ${installed_this_round[*]}" >> "$LOG_FILE"
fi
if [ ${#failed_packages[@]} -gt 0 ]; then
echo -e "${RED}Failed to install:${NC}"
for pkg in "${failed_packages[@]}"; do
@@ -505,14 +596,14 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
done
echo "Failed to install: ${failed_packages[*]}" >> "$LOG_FILE"
fi
CURRENT_ATTEMPT=$((CURRENT_ATTEMPT + 1))
echo -e "\n${YELLOW}Continuing to next test iteration...${NC}"
echo "Continuing to next test iteration" >> "$LOG_FILE"
continue
fi
else
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$' | wc -l)
echo -e "\n${GREEN}All $total_pkgs packages are installed!${NC}"
echo "All $total_pkgs packages are installed" >> "$LOG_FILE"
break
@@ -521,7 +612,7 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
echo -e "${RED}packages.list file not found at $HOME/shell/setup/packages.list${NC}"
echo "packages.list file not found" >> "$LOG_FILE"
fi
# If no missing packages or we've reached max attempts, break out of the loop
if [ ${#missing_packages[@]} -eq 0 ] || [ $CURRENT_ATTEMPT -ge $MAX_INSTALL_ATTEMPTS ]; then
break
@@ -534,11 +625,11 @@ done
if [ -d "$HOME/.nvm" ]; then
echo -e "NVM: ${GREEN}Installed${NC}"
echo "NVM: Installed" >> "$LOG_FILE"
# Source NVM
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Test Node.js installed by NVM
if check_command node; then
node_version=$(node -v)
@@ -590,7 +681,7 @@ for dotfile in "${dotfiles[@]}"; do
if [ -L "$dotfile" ]; then
echo -e "Dotfile $dotfile: ${GREEN}Symlinked${NC}"
echo "Dotfile $dotfile: Symlinked" >> "$LOG_FILE"
# Check if symlink is valid
if [ -e "$dotfile" ]; then
target=$(readlink -f "$dotfile")
@@ -620,7 +711,7 @@ if [ $errors -eq 0 ]; then
else
echo -e "${RED}Found $errors potential issues with your setup.${NC}"
echo "Result: Found $errors potential issues" >> "$LOG_FILE"
# Display missing packages if any
if [ ${#missing_packages[@]} -gt 0 ]; then
echo -e "\n${YELLOW}The following packages were not found:${NC}"
@@ -629,13 +720,13 @@ else
echo -e " - ${RED}$pkg${NC}"
echo " - $pkg" >> "$LOG_FILE"
done
if [ $CURRENT_ATTEMPT -gt $MAX_INSTALL_ATTEMPTS ]; then
echo -e "\n${RED}Reached maximum installation attempts ($MAX_INSTALL_ATTEMPTS).${NC}"
echo -e "${YELLOW}Some packages could not be installed automatically.${NC}"
echo "Reached maximum installation attempts" >> "$LOG_FILE"
fi
echo -e "\n${BLUE}You can manually install these packages with:${NC}"
echo -e " sudo apt-get install ${missing_packages[*]}"
fi
@@ -659,12 +750,12 @@ if [[ "$ID" == "debian" ]]; then
echo "1. Ensure Debian's 'universe' equivalent repositories are enabled (contrib, non-free)"
echo "2. Some packages like 'bat' may have different names in Debian (batcat)"
echo "3. Consider adding Debian-specific adjustments to setup.sh"
# Add specific Debian package name mappings
echo -e "\nOn Debian, you may need these package name adjustments:"
echo " - bat → batcat"
echo " - (add more as needed)"
echo "Debian package name mappings may be required" >> "$LOG_FILE"
fi
@@ -672,16 +763,16 @@ fi
check_bootstrapped_environment() {
echo -e "\n${BLUE}=== Checking for bootstrapped environment ===${NC}"
echo "=== Checking for bootstrapped environment ===" >> "$LOG_FILE"
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ]; then
echo -e "${GREEN}Environment appears to be bootstrapped:${NC}"
echo "Environment is bootstrapped" >> "$LOG_FILE"
# Check the shell repository structure
if [ -d "$HOME/shell/setup" ] && [ -f "$HOME/shell/setup/setup.sh" ]; then
echo -e " - ${GREEN}Setup directory and script present${NC}"
echo "Setup directory and script: Present" >> "$LOG_FILE"
# Check if setup.sh is executable
if [ -x "$HOME/shell/setup/setup.sh" ]; then
echo -e " - ${GREEN}Setup script is executable${NC}"
@@ -694,26 +785,26 @@ check_bootstrapped_environment() {
echo -e " - ${RED}Setup directory or setup.sh missing${NC}"
echo "Setup directory or setup.sh: Missing" >> "$LOG_FILE"
fi
# Check packages.list
if [ -f "$HOME/shell/setup/packages.list" ]; then
echo -e " - ${GREEN}Packages list present${NC}"
echo "Packages list: Present" >> "$LOG_FILE"
# Count packages in list
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | sed 's|//.*||' | awk '{print $1}' | grep -v '^$' | wc -l)
echo -e " - ${GREEN}Package list contains $pkg_count packages${NC}"
echo "Package list count: $pkg_count" >> "$LOG_FILE"
else
echo -e " - ${RED}Packages list missing${NC}"
echo "Packages list: Missing" >> "$LOG_FILE"
fi
# Check dotfiles directory
if [ -d "$HOME/shell/dotfiles" ]; then
echo -e " - ${GREEN}Dotfiles directory present${NC}"
echo "Dotfiles directory: Present" >> "$LOG_FILE"
# Check if dotfiles are properly symlinked
dotfiles_linked=true
for dotfile in "$HOME/.zshrc" "$HOME/.nanorc" "$HOME/.profile" "$HOME/.gitconfig"; do
@@ -730,7 +821,7 @@ check_bootstrapped_environment() {
break
fi
done
if $dotfiles_linked; then
echo -e " - ${GREEN}Dotfiles are properly symlinked${NC}"
echo "Dotfiles symlinked: Yes" >> "$LOG_FILE"