feat: Enhance package detection and installation process with improved parsing and validation

This commit is contained in:
Peter Wood
2025-05-29 07:31:59 -04:00
parent d75c7c5a94
commit ed50395490
9 changed files with 460 additions and 105 deletions

View File

@@ -31,7 +31,8 @@ LOGS_DIR="/tmp"
if [ ! -d "$LOGS_DIR" ]; then
mkdir -p "$LOGS_DIR"
fi
firectory if it doesn't exist and is writable
# 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
@@ -132,6 +133,20 @@ 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}
@@ -139,57 +154,94 @@ test_package() {
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() {
@@ -244,12 +296,12 @@ install_missing_packages() {
# 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"
@@ -266,11 +318,11 @@ install_missing_packages() {
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
@@ -281,7 +333,17 @@ install_missing_packages() {
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"
@@ -301,6 +363,9 @@ install_missing_packages() {
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"
@@ -310,11 +375,6 @@ install_missing_packages() {
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
}
@@ -394,8 +454,8 @@ 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... "
@@ -441,8 +501,8 @@ 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
@@ -511,7 +571,7 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
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"
@@ -543,7 +603,7 @@ while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
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
@@ -732,7 +792,7 @@ check_bootstrapped_environment() {
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