#!/bin/bash # CMtec Update System - Package Management Abstraction Layer # Provides unified interface for different package managers # Package manager detection and initialization init_package_managers() { log INFO "Initializing package managers for ${SYSTEM_INFO[DISTRO]}..." case "${SYSTEM_INFO[DISTRO]}" in "arch") PACKAGE_MANAGER="pacman" AUR_HELPER="" detect_aur_helper FLATPAK_AVAILABLE=$(command_exists flatpak && echo "yes" || echo "no") ;; "ubuntu"|"debian") PACKAGE_MANAGER="apt" SNAP_AVAILABLE=$(command_exists snap && echo "yes" || echo "no") FLATPAK_AVAILABLE=$(command_exists flatpak && echo "yes" || echo "no") ;; *) log ERROR "Unsupported distribution: ${SYSTEM_INFO[DISTRO]}" return 1 ;; esac log SUCCESS "Package managers initialized" log INFO "Primary: $PACKAGE_MANAGER" [ -n "$AUR_HELPER" ] && log INFO "AUR helper: $AUR_HELPER" [ "$FLATPAK_AVAILABLE" == "yes" ] && log INFO "Flatpak: available" [ "$SNAP_AVAILABLE" == "yes" ] && log INFO "Snap: available" } # Detect AUR helper for Arch systems detect_aur_helper() { local helpers=("yay" "paru" "pikaur" "trizen") for helper in "${helpers[@]}"; do if command_exists "$helper"; then AUR_HELPER="$helper" log INFO "Found AUR helper: $helper" return 0 fi done log WARNING "No AUR helper found - will install yay if needed" AUR_HELPER="" } # Install AUR helper (yay) if not present install_aur_helper() { if [ -n "$AUR_HELPER" ]; then return 0 fi log INFO "Installing yay AUR helper..." local section_start=$(date +%s) # Clean up any existing build directory [ -d ~/yay-bin ] && rm -rf ~/yay-bin cd ~ ( git clone https://aur.archlinux.org/yay-bin.git 2>&1 | tee -a "$LOG_FILE" cd yay-bin makepkg --noconfirm -si 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing yay AUR helper..." wait # Clean up build directory [ -d ~/yay-bin ] && rm -rf ~/yay-bin AUR_HELPER="yay" log SUCCESS "Yay AUR helper installed $(show_timer $section_start)" } # Update package databases update_package_databases() { local section_start=$(date +%s) log SECTION "Updating package databases" case "$PACKAGE_MANAGER" in "pacman") if confirm "Refresh pacman package databases?"; then ( sudo pacman -Syy --noconfirm 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Refreshing pacman databases..." wait log SUCCESS "Pacman databases updated $(show_timer $section_start)" else log WARNING "Package database refresh skipped" fi ;; "apt") if confirm "Update APT package databases?"; then ( sudo apt update 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Updating APT databases..." wait log SUCCESS "APT databases updated $(show_timer $section_start)" else log WARNING "Package database update skipped" fi ;; esac } # System upgrade system_upgrade() { local section_start=$(date +%s) log SECTION "Upgrading system packages" case "$PACKAGE_MANAGER" in "pacman") if confirm "Upgrade all system packages?"; then ( sudo pacman -Su --noconfirm 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Upgrading system packages (may take a while)..." wait log SUCCESS "System packages upgraded $(show_timer $section_start)" else log WARNING "System upgrade skipped" fi ;; "apt") if confirm "Upgrade all system packages?"; then ( sudo apt upgrade -y 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Upgrading system packages (may take a while)..." wait log SUCCESS "System packages upgraded $(show_timer $section_start)" else log WARNING "System upgrade skipped" fi ;; esac } # Install packages using primary package manager install_packages() { local packages=("$@") if [ ${#packages[@]} -eq 0 ]; then return 0 fi log INFO "Installing packages: ${packages[*]}" case "$PACKAGE_MANAGER" in "pacman") ( sudo pacman --noconfirm --needed -S "${packages[@]}" 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing ${#packages[@]} packages..." wait ;; "apt") ( sudo apt install -y "${packages[@]}" 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing ${#packages[@]} packages..." wait ;; esac } # Install AUR packages (Arch only) install_aur_packages() { local packages=("$@") if [ ${#packages[@]} -eq 0 ] || [ "$PACKAGE_MANAGER" != "pacman" ]; then return 0 fi # Ensure AUR helper is available if [ -z "$AUR_HELPER" ]; then install_aur_helper fi log INFO "Installing AUR packages: ${packages[*]}" ( "$AUR_HELPER" --noconfirm -S --needed --aur "${packages[@]}" 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing ${#packages[@]} AUR packages..." wait } # Update AUR packages update_aur_packages() { if [ "$PACKAGE_MANAGER" != "pacman" ] || [ -z "$AUR_HELPER" ]; then return 0 fi local section_start=$(date +%s) log SECTION "Updating AUR packages" if confirm "Update AUR packages?"; then ( "$AUR_HELPER" --noconfirm --aur 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Updating AUR packages..." wait log SUCCESS "AUR packages updated $(show_timer $section_start)" else log WARNING "AUR update skipped" fi } # Install Flatpak applications install_flatpak_apps() { local apps=("$@") if [ ${#apps[@]} -eq 0 ] || [ "$FLATPAK_AVAILABLE" != "yes" ]; then return 0 fi log INFO "Installing Flatpak apps: ${apps[*]}" for app in "${apps[@]}"; do ( flatpak install -y flathub "$app" 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing Flatpak app: $app..." wait done } # Update Flatpak applications update_flatpak_apps() { if [ "$FLATPAK_AVAILABLE" != "yes" ]; then return 0 fi local section_start=$(date +%s) log SECTION "Updating Flatpak applications" if confirm "Update Flatpak applications?"; then ( flatpak update -y 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Updating Flatpak applications..." wait log SUCCESS "Flatpak applications updated $(show_timer $section_start)" else log WARNING "Flatpak update skipped" fi } # Install Snap packages (Ubuntu/Debian) install_snap_packages() { local packages=("$@") if [ ${#packages[@]} -eq 0 ] || [ "$SNAP_AVAILABLE" != "yes" ]; then return 0 fi log INFO "Installing Snap packages: ${packages[*]}" for package in "${packages[@]}"; do local snap_args="" # Handle special snap flags case "$package" in *"--classic") snap_args="--classic" package=${package//" --classic"/} ;; esac ( sudo snap install $snap_args "$package" 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing Snap package: $package..." wait done } # Update Snap packages update_snap_packages() { if [ "$SNAP_AVAILABLE" != "yes" ]; then return 0 fi local section_start=$(date +%s) log SECTION "Updating Snap packages" if confirm "Update Snap packages?"; then ( sudo snap refresh 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Updating Snap packages..." wait log SUCCESS "Snap packages updated $(show_timer $section_start)" else log WARNING "Snap update skipped" fi } # Install packages from various sources (unified interface) install_package_set() { local pkg_type="$1" shift local packages=("$@") if [ ${#packages[@]} -eq 0 ]; then return 0 fi case "$pkg_type" in "system"|"main") install_packages "${packages[@]}" ;; "aur") install_aur_packages "${packages[@]}" ;; "flatpak") install_flatpak_apps "${packages[@]}" ;; "snap") install_snap_packages "${packages[@]}" ;; *) log ERROR "Unknown package type: $pkg_type" return 1 ;; esac } # Setup package managers (install if needed) setup_package_managers() { log SECTION "Setting up package managers" # Setup Flatpak if not available but potentially useful if [ "$FLATPAK_AVAILABLE" != "yes" ] && [ "${SYSTEM_INFO[WSL]}" != "yes" ]; then setup_flatpak fi # Setup Snap for Ubuntu systems if not available if [ "$PACKAGE_MANAGER" == "apt" ] && [ "$SNAP_AVAILABLE" != "yes" ]; then setup_snap fi # Install AUR helper for Arch if needed if [ "$PACKAGE_MANAGER" == "pacman" ] && [ -z "$AUR_HELPER" ]; then install_aur_helper fi } # Setup Flatpak setup_flatpak() { log INFO "Setting up Flatpak..." local section_start=$(date +%s) ( case "$PACKAGE_MANAGER" in "pacman") sudo pacman --noconfirm --needed -S flatpak ;; "apt") sudo apt install -y flatpak ;; esac # Add Flathub repository flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo # Install Flatseal for permission management flatpak install -y flathub com.github.tchx84.Flatseal ) 2>&1 | tee -a "$LOG_FILE" & spinner $! "Setting up Flatpak and Flathub repository..." wait FLATPAK_AVAILABLE="yes" log SUCCESS "Flatpak setup completed $(show_timer $section_start)" } # Setup Snap setup_snap() { log INFO "Setting up Snap..." local section_start=$(date +%s) ( sudo apt install -y snap 2>&1 | tee -a "$LOG_FILE" ) & spinner $! "Installing Snap package manager..." wait SNAP_AVAILABLE="yes" log SUCCESS "Snap setup completed $(show_timer $section_start)" } # Get package manager status get_package_manager_status() { echo "Primary: $PACKAGE_MANAGER" [ -n "$AUR_HELPER" ] && echo "AUR: $AUR_HELPER" [ "$FLATPAK_AVAILABLE" == "yes" ] && echo "Flatpak: available" [ "$SNAP_AVAILABLE" == "yes" ] && echo "Snap: available" } # Source guard to prevent double-sourcing if [ -z "$PACKAGES_LIB_LOADED" ]; then PACKAGES_LIB_LOADED=true fi