update installer, select multiple packages at the same time
This commit is contained in:
213
install.sh
213
install.sh
@@ -3,8 +3,8 @@
|
|||||||
# --- Main Script ---
|
# --- Main Script ---
|
||||||
|
|
||||||
# This script presents a menu of software packages defined in a remote
|
# This script presents a menu of software packages defined in a remote
|
||||||
# configuration file. The user can select a package, and the script
|
# configuration file. The user can select one or more packages, and the
|
||||||
# will download the corresponding files. It includes a feature to show
|
# script will download the corresponding files. It includes a feature to show
|
||||||
# a diff and ask for confirmation before overwriting existing config files.
|
# a diff and ask for confirmation before overwriting existing config files.
|
||||||
# It can also check for updates to already-installed scripts.
|
# It can also check for updates to already-installed scripts.
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ log() {
|
|||||||
echo "[$1] $2"
|
echo "[$1] $2"
|
||||||
}
|
}
|
||||||
|
|
||||||
# New function to get the version from a local script file.
|
# Get the version from a local script file.
|
||||||
# It reads the first 5 lines and extracts the version number.
|
# It reads the first 5 lines and extracts the version number.
|
||||||
get_local_version() {
|
get_local_version() {
|
||||||
local file_path="$1"
|
local file_path="$1"
|
||||||
@@ -27,7 +27,7 @@ get_local_version() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# New function to compare two version strings (e.g., "1.2.0" vs "1.10.0").
|
# Compare two version strings (e.g., "1.2.0" vs "1.10.0").
|
||||||
# Returns 0 if v1 is newer, 1 if they are the same or v2 is newer.
|
# Returns 0 if v1 is newer, 1 if they are the same or v2 is newer.
|
||||||
is_version_greater() {
|
is_version_greater() {
|
||||||
local v1=$1
|
local v1=$1
|
||||||
@@ -41,6 +41,75 @@ is_version_greater() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# New function to process a single selected package.
|
||||||
|
process_package() {
|
||||||
|
local choice="$1"
|
||||||
|
# Check if the choice is a valid package name.
|
||||||
|
if [[ -z "${SCRIPT_PACKAGES[$choice]}" ]]; then
|
||||||
|
log "❌" "Invalid package name provided: '${choice}'"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
log "⬇️" "Processing package: '${choice}'..."
|
||||||
|
|
||||||
|
# Get the config value and split it into version and URLs
|
||||||
|
config_value="${SCRIPT_PACKAGES[$choice]}"
|
||||||
|
remote_version=$(echo "${config_value}" | cut -d'|' -f1)
|
||||||
|
urls_to_download=$(echo "${config_value}" | cut -d'|' -f2-)
|
||||||
|
|
||||||
|
read -r -a urls_to_download_array <<< "$urls_to_download"
|
||||||
|
|
||||||
|
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}'."
|
||||||
|
tmp_file=$(mktemp)
|
||||||
|
|
||||||
|
if curl -fsSL -o "${tmp_file}" "${url}"; then
|
||||||
|
log "🔎" "Comparing versions..."
|
||||||
|
echo "-------------------- DIFF START --------------------"
|
||||||
|
if command -v colordiff &> /dev/null; then
|
||||||
|
colordiff -u "${filename}" "${tmp_file}"
|
||||||
|
else
|
||||||
|
# Attempt to use diff's color option, which is common.
|
||||||
|
diff --color=always -u "${filename}" "${tmp_file}" 2>/dev/null || diff -u "${filename}" "${tmp_file}"
|
||||||
|
fi
|
||||||
|
echo "--------------------- DIFF END ---------------------"
|
||||||
|
|
||||||
|
read -p "Do you want to overwrite '${filename}'? (y/N) " -n 1 -r REPLY
|
||||||
|
echo
|
||||||
|
|
||||||
|
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."
|
||||||
|
rm -f "${tmp_file}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Original download logic for all other files.
|
||||||
|
log "->" "Downloading '${filename}'..."
|
||||||
|
if curl -fsSL -o "${filename}" "${url}"; then
|
||||||
|
log "✅" "Successfully downloaded '${filename}'."
|
||||||
|
if [[ "${filename}" == *.sh || "${filename}" == *.bash ]]; then
|
||||||
|
chmod +x "${filename}"
|
||||||
|
log "🤖" "Made '${filename}' executable."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "❌" "Error: Failed to download '${filename}'."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
log "📦" "Package processing complete for '${choice}'."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# --- Main Logic ---
|
# --- Main Logic ---
|
||||||
|
|
||||||
# Generate a unique temporary filename with a timestamp.
|
# Generate a unique temporary filename with a timestamp.
|
||||||
@@ -62,10 +131,6 @@ source "${conf_file}"
|
|||||||
|
|
||||||
# --- Update Check & User Interface ---
|
# --- Update Check & User Interface ---
|
||||||
|
|
||||||
echo "-------------------------------------"
|
|
||||||
echo " Script Downloader "
|
|
||||||
echo "-------------------------------------"
|
|
||||||
|
|
||||||
# Create an array of options from the package names.
|
# Create an array of options from the package names.
|
||||||
# We will modify this array to show installation and update status.
|
# We will modify this array to show installation and update status.
|
||||||
declare -a options
|
declare -a options
|
||||||
@@ -76,7 +141,7 @@ for key in "${package_keys[@]}"; do
|
|||||||
# The config format is now "VERSION|URL1 URL2..."
|
# The config format is now "VERSION|URL1 URL2..."
|
||||||
config_value="${SCRIPT_PACKAGES[$key]}"
|
config_value="${SCRIPT_PACKAGES[$key]}"
|
||||||
remote_version=$(echo "${config_value}" | cut -d'|' -f1)
|
remote_version=$(echo "${config_value}" | cut -d'|' -f1)
|
||||||
|
|
||||||
# Get just the URLs and assume the first URL is the main script to check.
|
# Get just the URLs and assume the first URL is the main script to check.
|
||||||
urls=$(echo "${config_value}" | cut -d'|' -f2-)
|
urls=$(echo "${config_value}" | cut -d'|' -f2-)
|
||||||
read -r -a url_array <<< "$urls"
|
read -r -a url_array <<< "$urls"
|
||||||
@@ -95,92 +160,62 @@ for key in "${package_keys[@]}"; do
|
|||||||
fi
|
fi
|
||||||
options+=("${key}${status}")
|
options+=("${key}${status}")
|
||||||
done
|
done
|
||||||
echo
|
|
||||||
|
|
||||||
options+=("Quit") # Add a Quit option to the menu.
|
options+=("Quit") # Add a Quit option to the menu.
|
||||||
|
|
||||||
# Set the prompt for the select menu.
|
# --- User Interaction ---
|
||||||
PS3="Please enter your choice: "
|
|
||||||
|
|
||||||
# Display the menu and handle user input.
|
# Manually display the options with numbers.
|
||||||
# Setting COLUMNS=1 forces the select menu to display vertically.
|
echo
|
||||||
COLUMNS=1
|
echo "-------------------------------------"
|
||||||
select choice_with_status in "${options[@]}"; do
|
echo " Script Downloader "
|
||||||
# Strip the status message from the choice for key lookup
|
echo "-------------------------------------"
|
||||||
|
for i in "${!options[@]}"; do
|
||||||
|
printf "%d) %s\n" "$((i+1))" "${options[$i]}"
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Prompt the user for one or more choices.
|
||||||
|
read -p "Please enter your choice(s) (e.g., 1 3 4), or press Enter to quit: " -r -a user_choices
|
||||||
|
|
||||||
|
# If no choices are made, exit gracefully.
|
||||||
|
if [ ${#user_choices[@]} -eq 0 ]; then
|
||||||
|
log "👋" "No selection made. Exiting."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Loop through the user's selections and process each one.
|
||||||
|
for choice_num in "${user_choices[@]}"; do
|
||||||
|
# Validate that the input is a number.
|
||||||
|
if ! [[ "$choice_num" =~ ^[0-9]+$ ]]; then
|
||||||
|
log "⚠️" "Skipping invalid input: '${choice_num}'. Not a number."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert selection number to array index (0-based).
|
||||||
|
index=$((choice_num - 1))
|
||||||
|
|
||||||
|
# Validate that the index is within the bounds of the options array.
|
||||||
|
if [[ -z "${options[$index]}" ]]; then
|
||||||
|
log "⚠️" "Skipping invalid choice: '${choice_num}'. Out of range."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the choice text from the array.
|
||||||
|
choice_with_status="${options[$index]}"
|
||||||
|
|
||||||
|
# Strip the status message to get the package key.
|
||||||
choice=$(echo "${choice_with_status}" | sed 's/ (.*//')
|
choice=$(echo "${choice_with_status}" | sed 's/ (.*//')
|
||||||
|
|
||||||
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 "⬇️" "Processing package: '${choice}'..."
|
|
||||||
|
|
||||||
# Get the config value and split it into version and URLs
|
|
||||||
config_value="${SCRIPT_PACKAGES[$choice]}"
|
|
||||||
remote_version=$(echo "${config_value}" | cut -d'|' -f1)
|
|
||||||
urls_to_download=$(echo "${config_value}" | cut -d'|' -f2-)
|
|
||||||
|
|
||||||
read -r -a urls_to_download_array <<< "$urls_to_download"
|
|
||||||
|
|
||||||
for url in "${urls_to_download_array[@]}"; do
|
# Handle the "Quit" option.
|
||||||
filename=$(basename "${url}")
|
if [[ "${choice}" == "Quit" ]]; then
|
||||||
# If it's a .conf file AND it already exists, ask to overwrite.
|
log "👋" "Quit selected. Exiting now."
|
||||||
if [[ "${filename}" == *.conf && -f "${filename}" ]]; then
|
exit 0
|
||||||
log "->" "Found existing config file: '${filename}'."
|
fi
|
||||||
tmp_file=$(mktemp)
|
|
||||||
|
|
||||||
if curl -fsSL -o "${tmp_file}" "${url}"; then
|
# Process the selected package.
|
||||||
log "🔎" "Comparing versions..."
|
process_package "${choice}"
|
||||||
echo "-------------------- DIFF START --------------------"
|
|
||||||
if command -v colordiff &> /dev/null; then
|
|
||||||
colordiff -u "${filename}" "${tmp_file}"
|
|
||||||
else
|
|
||||||
# Attempt to use diff's color option, which is common.
|
|
||||||
diff --color=always -u "${filename}" "${tmp_file}" 2>/dev/null || diff -u "${filename}" "${tmp_file}"
|
|
||||||
fi
|
|
||||||
echo "--------------------- DIFF END ---------------------"
|
|
||||||
|
|
||||||
read -p "Do you want to overwrite '${filename}'? (y/N) " -n 1 -r REPLY
|
|
||||||
echo
|
|
||||||
|
|
||||||
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."
|
|
||||||
rm -f "${tmp_file}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Original download logic for all other files.
|
|
||||||
log "->" "Downloading '${filename}'..."
|
|
||||||
if curl -fsSL -o "${filename}" "${url}"; then
|
|
||||||
log "✅" "Successfully downloaded '${filename}'."
|
|
||||||
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 processing complete."
|
|
||||||
break
|
|
||||||
else
|
|
||||||
echo "Invalid selection. Please try again."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
log "🏁" "All selected packages have been processed."
|
||||||
|
|||||||
Reference in New Issue
Block a user