'local result=$(cmd)' resets $? to 0 (the local builtin's own exit), so the
following checkSuccess always saw success regardless of cmd's real exit — the
mechanism that masked the de-sudo write failures. Split declaration from
assignment ('local result; result=$(cmd)') across all 235 active-code sites
(84 files) so the command's exit reaches checkSuccess. No behaviour change
beyond $? now being accurate (no set -e in runtime code; multi-line
assignments transform safely).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
156 lines
7.0 KiB
Bash
Executable File
156 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
databaseAppScan()
|
|
{
|
|
# Check if sqlite3 is available
|
|
if ! command -v sqlite3 &> /dev/null; then
|
|
isNotice "sqlite3 command not found. Make sure it's installed."
|
|
fi
|
|
|
|
# Check if database file is available
|
|
if [ ! -f "$docker_dir/$db_file" ] ; then
|
|
isNotice "Database file not found. Make sure it's installed."
|
|
fi
|
|
|
|
isHeader "Scanning Docker folder for apps"
|
|
|
|
# Check if the folder exists
|
|
if [ ! -d "$containers_dir" ]; then
|
|
checkSuccess "Install path not found or not a directory: $containers_dir"
|
|
fi
|
|
|
|
# Scan the folder and retrieve folder names
|
|
local folder_names=$(runFileOp find "$containers_dir" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
|
|
|
|
# Check if no folders are found
|
|
if [ -z "$folder_names" ]; then
|
|
checkSuccess "No apps found."
|
|
fi
|
|
|
|
# Initialize the updated_count variable to keep track of updates made to the database
|
|
local updated_count=0
|
|
|
|
# Get the list of all folder names and statuses from the database
|
|
local existing_folders=$(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT name, status, uninstall_date FROM apps;")
|
|
|
|
# Create an array to store existing folder names in the database
|
|
local existing_folder_names=()
|
|
while IFS='|' read -r folder_name status uninstall_date; do
|
|
if [[ -n "$folder_name" ]]; then
|
|
existing_folder_names+=("$folder_name")
|
|
# Check if the folder exists in the containers_dir
|
|
if [ -d "$containers_dir/$folder_name" ]; then
|
|
if (( status == 0 )); then
|
|
isNotice "The folder for $folder_name has been found."
|
|
# Update the database to set the status to 1 (installed) and unset the uninstall_date
|
|
local result; result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "UPDATE apps SET status = 1, uninstall_date = NULL WHERE name = '$folder_name';")
|
|
checkSuccess "Updating apps database for $folder_name to installed status."
|
|
((updated_count++)) # Increment updated_count
|
|
fi
|
|
fi
|
|
fi
|
|
done <<< "$existing_folders"
|
|
|
|
# Loop through immediate subdirectories of $containers_dir
|
|
for app_dir in "$containers_dir"/*/; do
|
|
# Get the app name from the folder name
|
|
local app_name=$(basename "$app_dir")
|
|
|
|
# Check if the app name is not already in the database
|
|
if ! [[ " ${existing_folder_names[@]} " =~ " $app_name " ]]; then
|
|
# Check if the folder contains a valid .config file
|
|
if [ -f "$app_dir/$app_name.config" ]; then
|
|
# Extract the date and time from the folder name (if present)
|
|
local folder_datetime=$(echo "$app_name" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}')
|
|
if [ -z "$folder_datetime" ]; then
|
|
# If no date and time are found in the folder name, use the current date and time
|
|
local folder_datetime=$(date "+%Y-%m-%d %H:%M:%S")
|
|
fi
|
|
|
|
# Split folder_datetime into date and time variables
|
|
local folder_date=$(echo "$folder_datetime" | awk '{print $1}')
|
|
local folder_time=$(echo "$folder_datetime" | awk '{print $2}')
|
|
|
|
# Add the new entry to the database with a default status of 1 (installed) and the extracted or current date
|
|
local result; result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "INSERT INTO apps (name, status, install_date, install_time) VALUES ('$app_name', 1, '$folder_date', '$folder_time');")
|
|
checkSuccess "Adding $app_name to the apps database."
|
|
((updated_count++)) # Increment updated_count
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Create an array to store folder names that should be removed from the database
|
|
local folders_to_remove=()
|
|
|
|
# Get a list of folder names that exist in the database but not in the current folder structure
|
|
for folder_name in "${existing_folder_names[@]}"; do
|
|
if [ ! -d "$containers_dir/$folder_name" ]; then
|
|
local folders_to_remove+=("$folder_name")
|
|
fi
|
|
done
|
|
|
|
# Get a list of folder names that exist in the database but not in the current folder structure
|
|
for folder_name in "${existing_folder_names[@]}"; do
|
|
if [ ! -d "$containers_dir/$folder_name" ]; then
|
|
# Check if this folder is actually associated with an entry in the database
|
|
if [[ " ${folder_names[@]} " =~ " $folder_name " ]]; then
|
|
isNotice "Folder $folder_name no longer exists. Removing from the Database."
|
|
|
|
# Delete the entry from the apps table
|
|
local result; result=$(runInstallOp sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$app_name';")
|
|
checkSuccess "Removing $app_name from the apps database."
|
|
|
|
portsRemoveFromDatabase $app_name;
|
|
|
|
((updated_count++)) # Increment updated_count
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Check if all apps are up to date
|
|
if [ "$updated_count" -eq 0 ]; then
|
|
checkSuccess "All apps are up to date."
|
|
fi
|
|
|
|
# Reap leftover app folders that hold no real data: completely empty, or
|
|
# holding only the regenerable .config and/or the migrate.txt marker. There
|
|
# is nothing to lose in any of these cases, so we clean them automatically
|
|
# rather than prompting — the old "WIPE ALL DATA" question fired precisely
|
|
# when there was no data to wipe.
|
|
for folder_name in $folder_names; do
|
|
[[ "$folder_name" == "libreportal" ]] && continue
|
|
local folder_path="$containers_dir/$folder_name"
|
|
|
|
if [ ! -d "$folder_path" ]; then
|
|
isNotice "Folder $folder_name no longer exists — removing it from the database."
|
|
runInstallOp sqlite3 "$docker_dir/$db_file" "DELETE FROM apps WHERE name = '$folder_name';"
|
|
checkSuccess "Removing $folder_name from the apps database."
|
|
((updated_count++))
|
|
continue
|
|
fi
|
|
|
|
local num_files=$(runFileOp find "$folder_path" -maxdepth 1 -type f | wc -l)
|
|
local has_config=false has_migrate=false
|
|
[ -f "$folder_path/$folder_name.config" ] && has_config=true
|
|
[ -f "$folder_path/migrate.txt" ] && has_migrate=true
|
|
|
|
# Describe why the folder counts as a no-data leftover (empty string =
|
|
# it has real content, so leave it alone).
|
|
local reason=""
|
|
if [ "$num_files" -eq 0 ]; then
|
|
reason="empty"
|
|
elif [ "$num_files" -eq 1 ] && $has_config; then
|
|
reason="only a config file"
|
|
elif [ "$num_files" -eq 1 ] && $has_migrate; then
|
|
reason="only a migrate.txt marker"
|
|
elif [ "$num_files" -eq 2 ] && $has_config && $has_migrate; then
|
|
reason="only a config file and a migrate.txt marker"
|
|
fi
|
|
|
|
if [[ -n "$reason" ]]; then
|
|
isNotice "Cleaning up $folder_name ($reason — no data to lose)."
|
|
dockerUninstallApp "$folder_name"
|
|
fi
|
|
done
|
|
}
|