#!/bin/bash # --- Main Script --- # This script presents a menu of software packages defined in a remote # configuration file. The user can select a package, and the script # will download the corresponding files. It includes a feature to show # a diff and ask for confirmation before overwriting existing config files. # --- Functions --- # A simple function to log messages with a consistent format. log() { echo "[$1] $2" } # --- Main Logic --- # Generate a unique temporary filename with a timestamp. # This file will hold the package definitions downloaded from the remote source. conf_file="packages.conf.$(date +%Y%m%d%H%M%S)" # Set up a trap to delete the temporary file on exit. This ensures that # no matter how the script exits (normally, with an error, or via Ctrl+C), # the temporary file is cleaned up. trap 'rm -f "${conf_file}"' EXIT # Download the configuration file before sourcing it. log "🔄" "Downloading configuration file..." if ! curl -fsSL -o "${conf_file}" "https://git.technopunk.space/tomi/Scripts/raw/branch/main/packages.conf"; then log "❌" "Error: Failed to download packages.conf. Exiting." exit 1 fi log "✅" "Configuration file downloaded successfully." # Source the configuration file to load the SCRIPT_PACKAGES associative array. # The file is expected to contain a declaration like: # declare -A SCRIPT_PACKAGES=( [key1]="url1 url2" [key2]="url3" ) source "${conf_file}" # --- User Interface --- echo "-------------------------------------" echo " Script Downloader " echo "-------------------------------------" # Create an array of options from the package names (the keys of our map). options=("${!SCRIPT_PACKAGES[@]}") options+=("Quit") # Add a Quit option to the menu. # Set the prompt for the select menu. PS3="Please enter the number of the script/package you want to download: " # Display the menu and handle user input. The `select` statement is a # convenient way to create interactive menus in shell scripts. select choice in "${options[@]}"; do case "${choice}" in "Quit") log "👋" "Exiting." break # Exit the select loop. ;; *) # Check if the user's choice is a valid package name. if [[ -n "${SCRIPT_PACKAGES[$choice]}" ]]; then echo log "⬇️" "Downloading package: '${choice}'..." # Get the space-separated list of URLs for the chosen package. urls_to_download="${SCRIPT_PACKAGES[$choice]}" # Read the URLs into an array for safer handling. read -r -a urls_to_download_array <<< "$urls_to_download" # Loop through each URL in the list and download the file. for url in "${urls_to_download_array[@]}"; do filename=$(basename "${url}") # If it's a .conf file AND it already exists, ask to overwrite. if [[ "${filename}" == *.conf && -f "${filename}" ]]; then log "->" "Found existing config file: '${filename}'." # Create a temporary file to download the new version for comparison. tmp_file=$(mktemp) # Download the new version silently to the temp file. if curl -fsSL -o "${tmp_file}" "${url}"; then log "🔎" "Comparing versions..." echo "-------------------- DIFF START --------------------" # Show a colorized diff if 'colordiff' is available, otherwise use regular 'diff'. if command -v colordiff &> /dev/null; then colordiff -u "${filename}" "${tmp_file}" else diff --color=always -u "${filename}" "${tmp_file}" fi echo "--------------------- DIFF END ---------------------" # Ask the user for confirmation before overwriting. read -p "Do you want to overwrite '${filename}'? (y/N) " -n 1 -r REPLY echo # Move to a new line for cleaner output. if [[ $REPLY =~ ^[Yy]$ ]]; then mv "${tmp_file}" "${filename}" log "✅" "Updated '${filename}'." else rm "${tmp_file}" log "🤷" "Kept existing version of '${filename}'." fi else log "❌" "Error: Failed to download new version of '${filename}' for comparison." # Clean up the temp file on failure. rm -f "${tmp_file}" fi else # Original download logic for all other files (or new .conf files). log "->" "Downloading '${filename}'..." if curl -fsSL -o "${filename}" "${url}"; then log "✅" "Successfully downloaded '${filename}'." # If the downloaded file is a shell script, make it executable. if [[ "${filename}" == *.sh ]]; then chmod +x "${filename}" log "🤖" "Made '${filename}' executable." fi else log "❌" "Error: Failed to download '${filename}'." fi fi done echo log "📦" "Package download complete." break # Exit the select loop after a successful operation. else # The user entered an invalid number. echo "Invalid selection. Please try again." fi ;; esac done