diff --git a/scripts/manage-modules-sql.sh b/scripts/manage-modules-sql.sh index ba56eac..714117e 100755 --- a/scripts/manage-modules-sql.sh +++ b/scripts/manage-modules-sql.sh @@ -5,6 +5,7 @@ trap 'echo " ❌ SQL helper error (line ${LINENO}): ${BASH_COMMAND}" >&2' ERR CUSTOM_SQL_ROOT="/tmp/scripts/sql/custom" ALT_CUSTOM_SQL_ROOT="/scripts/sql/custom" +HELPER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SQL_SUCCESS_LOG=() SQL_FAILURE_LOG=() @@ -108,13 +109,66 @@ run_custom_sql_group(){ done < <(LC_ALL=C find "$dir" -type f -name "*.sql" | sort) || true } +ensure_module_metadata(){ + if declare -p MODULE_NAME >/dev/null 2>&1; then + return 0 + fi + + local -a module_py_candidates=( + "${MODULE_HELPER:-}" + "${HELPER_DIR%/*}/modules.py" + "/tmp/scripts/modules.py" + "/scripts/modules.py" + ) + + local module_py="" + for candidate in "${module_py_candidates[@]}"; do + [ -n "$candidate" ] || continue + if [ -f "$candidate" ]; then + module_py="$candidate" + break + fi + done + + local manifest_path="${MANIFEST_PATH:-${MODULES_MANIFEST_PATH:-/tmp/config/modules.json}}" + local env_path="${ENV_PATH:-${MODULES_ENV_PATH:-/tmp/.env}}" + local state_env_candidate="${STATE_DIR:-${MODULES_ROOT:-/modules}}/modules.env" + if [ -f "$state_env_candidate" ]; then + env_path="$state_env_candidate" + fi + + if [ -z "$module_py" ]; then + echo " ⚠️ Module metadata helper missing; skipping module SQL execution." + return 1 + fi + if [ ! -f "$manifest_path" ] || [ ! -f "$env_path" ]; then + echo " ⚠️ Module manifest (${manifest_path}) or env (${env_path}) not found; skipping module SQL execution." + return 1 + fi + + local shell_dump + echo " ℹ️ Reloading module metadata using ${module_py} (env=${env_path}, manifest=${manifest_path})" + if ! shell_dump="$(python3 "$module_py" --env-path "$env_path" --manifest "$manifest_path" dump --format shell 2>/dev/null)"; then + echo " ⚠️ Unable to regenerate module metadata from ${module_py}; skipping module SQL execution." + return 1 + fi + shell_dump="$(echo "$shell_dump" | sed 's/^declare -A /declare -gA /')" + eval "$shell_dump" + return 0 +} + # Function to execute SQL files for a module module_sql_run_module(){ local module_key="$1" - local module_dir="$2" + local module_dir_path="$2" + local module_dir_name="${3:-}" local module_name="${MODULE_NAME[$module_key]:-}" if [ -z "$module_name" ]; then - module_name="$module_dir" + if [ -n "$module_dir_name" ]; then + module_name="$module_dir_name" + else + module_name="$(basename "$module_dir_path")" + fi fi local world_db="${DB_WORLD_NAME:-acore_world}" local auth_db="${DB_AUTH_NAME:-acore_auth}" @@ -183,34 +237,34 @@ module_sql_run_module(){ fi # Find and execute SQL files in the module - if [ -d "$module_dir/data/sql" ]; then + if [ -d "$module_dir_path/data/sql" ]; then # Execute world database scripts - if [ -d "$module_dir/data/sql/world" ]; then + if [ -d "$module_dir_path/data/sql/world" ]; then while IFS= read -r sql_file; do execute_sql_file_in_db "$world_db" "$sql_file" "world SQL" - done < <(find "$module_dir/data/sql/world" -type f -name "*.sql") || true + done < <(find "$module_dir_path/data/sql/world" -type f -name "*.sql") || true fi - run_sorted_sql "$module_dir/data/sql/db-world" "${world_db}" "world SQL" + run_sorted_sql "$module_dir_path/data/sql/db-world" "${world_db}" "world SQL" # Execute auth database scripts - if [ -d "$module_dir/data/sql/auth" ]; then + if [ -d "$module_dir_path/data/sql/auth" ]; then while IFS= read -r sql_file; do execute_sql_file_in_db "$auth_db" "$sql_file" "auth SQL" - done < <(find "$module_dir/data/sql/auth" -type f -name "*.sql") || true + done < <(find "$module_dir_path/data/sql/auth" -type f -name "*.sql") || true fi - run_sorted_sql "$module_dir/data/sql/db-auth" "${auth_db}" "auth SQL" + run_sorted_sql "$module_dir_path/data/sql/db-auth" "${auth_db}" "auth SQL" # Execute character database scripts - if [ -d "$module_dir/data/sql/characters" ]; then + if [ -d "$module_dir_path/data/sql/characters" ]; then while IFS= read -r sql_file; do execute_sql_file_in_db "$characters_db" "$sql_file" "characters SQL" - done < <(find "$module_dir/data/sql/characters" -type f -name "*.sql") || true + done < <(find "$module_dir_path/data/sql/characters" -type f -name "*.sql") || true fi - run_sorted_sql "$module_dir/data/sql/db-characters" "${characters_db}" "characters SQL" + run_sorted_sql "$module_dir_path/data/sql/db-characters" "${characters_db}" "characters SQL" # Execute playerbots database scripts - if [ "$module_key" = "MODULE_PLAYERBOTS" ] && [ -d "$module_dir/data/sql/playerbots" ]; then - local pb_root="$module_dir/data/sql/playerbots" + if [ "$module_key" = "MODULE_PLAYERBOTS" ] && [ -d "$module_dir_path/data/sql/playerbots" ]; then + local pb_root="$module_dir_path/data/sql/playerbots" run_sorted_sql "$pb_root/base" "$playerbots_db" "playerbots SQL" run_sorted_sql "$pb_root/custom" "$playerbots_db" "playerbots SQL" run_sorted_sql "$pb_root/updates" "$playerbots_db" "playerbots SQL" @@ -221,14 +275,14 @@ module_sql_run_module(){ # Execute base SQL files (common pattern) while IFS= read -r sql_file; do execute_sql_file_in_db "$world_db" "$sql_file" "base SQL" - done < <(find "$module_dir/data/sql" -maxdepth 1 -type f -name "*.sql") || true + done < <(find "$module_dir_path/data/sql" -maxdepth 1 -type f -name "*.sql") || true fi # Look for SQL files in other common locations - if [ -d "$module_dir/sql" ]; then + if [ -d "$module_dir_path/sql" ]; then while IFS= read -r sql_file; do execute_sql_file_in_db "$world_db" "$sql_file" "module SQL" - done < <(find "$module_dir/sql" -type f -name "*.sql") || true + done < <(find "$module_dir_path/sql" -type f -name "*.sql") || true fi return 0 @@ -245,28 +299,52 @@ execute_module_sql_scripts() { SQL_SUCCESS_LOG=() SQL_FAILURE_LOG=() + local metadata_available=1 + if ! ensure_module_metadata; then + metadata_available=0 + echo " ⚠️ Module metadata unavailable; module repository SQL will be skipped." + fi + # Iterate modules from manifest metadata local key module_dir enabled local world_db="${DB_WORLD_NAME:-acore_world}" local auth_db="${DB_AUTH_NAME:-acore_auth}" local characters_db="${DB_CHARACTERS_NAME:-acore_characters}" - for key in "${MODULE_KEYS[@]}"; do - module_dir="${MODULE_NAME[$key]:-}" - [ -n "$module_dir" ] || continue - [ -d "$module_dir" ] || continue + local modules_root="${MODULES_ROOT:-/modules}" + modules_root="${modules_root%/}" + if [ "$metadata_available" = "1" ]; then + echo "Discovered ${#MODULE_KEYS[@]} module definitions (MODULES_ROOT=${modules_root})" + for key in "${MODULE_KEYS[@]}"; do + module_dir="${MODULE_NAME[$key]:-}" + [ -n "$module_dir" ] || continue - enabled="${MODULE_ENABLED[$key]:-0}" - if [ "$enabled" != "1" ]; then - continue - fi + local module_dir_path="$module_dir" + case "$module_dir_path" in + /*) ;; + *) + module_dir_path="${modules_root}/${module_dir_path#/}" + ;; + esac + enabled="${MODULE_ENABLED[$key]:-0}" + if [ "$enabled" != "1" ]; then + continue + fi - if [ "$module_dir" = "mod-pocket-portal" ]; then - echo '⚠️ Skipping mod-pocket-portal SQL: module disabled until C++20 patch is applied.' - continue - fi + if [ ! -d "$module_dir_path" ]; then + echo " ⚠️ Skipping ${module_dir} (enabled) because directory is missing at ${module_dir_path}" + continue + fi - module_sql_run_module "$key" "$module_dir" - done + if [ "$module_dir" = "mod-pocket-portal" ] || [ "$(basename "$module_dir_path")" = "mod-pocket-portal" ]; then + echo '⚠️ Skipping mod-pocket-portal SQL: module disabled until C++20 patch is applied.' + continue + fi + + module_sql_run_module "$key" "$module_dir_path" "$module_dir" + done + else + echo "Discovered 0 module definitions (MODULES_ROOT=${modules_root})" + fi run_custom_sql_group world "${world_db}" "custom world SQL" run_custom_sql_group auth "${auth_db}" "custom auth SQL" diff --git a/scripts/manage-modules.sh b/scripts/manage-modules.sh index d23b8f6..f2b492c 100755 --- a/scripts/manage-modules.sh +++ b/scripts/manage-modules.sh @@ -18,6 +18,10 @@ ok(){ printf '%b\n' "${GREEN}✅ $*${NC}"; } warn(){ printf '%b\n' "${YELLOW}⚠️ $*${NC}"; } err(){ printf '%b\n' "${RED}❌ $*${NC}"; exit 1; } +# Declare module metadata arrays globally at script level +declare -A MODULE_NAME MODULE_REPO MODULE_REF MODULE_TYPE MODULE_ENABLED MODULE_NEEDS_BUILD MODULE_BLOCKED MODULE_POST_INSTALL MODULE_REQUIRES MODULE_CONFIG_CLEANUP MODULE_NOTES MODULE_STATUS MODULE_BLOCK_REASON +declare -a MODULE_KEYS + read_env_value(){ local key="$1" default="${2:-}" value="${!key:-}" if [ -n "$value" ]; then @@ -86,11 +90,14 @@ generate_module_state(){ fi # shellcheck disable=SC1090 source "$env_file" + + # Module arrays are already declared at script level if ! MODULE_SHELL_STATE="$(python3 "$MODULE_HELPER" --env-path "$ENV_PATH" --manifest "$MANIFEST_PATH" dump --format shell)"; then err "Unable to load manifest metadata" fi local eval_script - eval_script="$(echo "$MODULE_SHELL_STATE" | sed 's/^declare -A /declare -gA /')" + # Remove the declare line since we already declared the arrays + eval_script="$(echo "$MODULE_SHELL_STATE" | sed '/^declare -A /d')" eval "$eval_script" IFS=' ' read -r -a MODULES_COMPILE_LIST <<< "${MODULES_COMPILE:-}" if [ "${#MODULES_COMPILE_LIST[@]}" -eq 1 ] && [ -z "${MODULES_COMPILE_LIST[0]}" ]; then @@ -161,8 +168,8 @@ run_post_install_hooks(){ esac fi - # Clean up environment - unset MODULE_KEY MODULE_DIR MODULE_NAME MODULES_ROOT LUA_SCRIPTS_TARGET + # Clean up hook-specific environment (preserve MODULE_NAME array and script-level MODULES_ROOT) + unset MODULE_KEY MODULE_DIR LUA_SCRIPTS_TARGET else err "Hook script not found for ${hook} (searched: ${hook_search_paths[*]})" fi