mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 20:34:53 +08:00
Feat/refactoring-module-menu (#22733)
This commit is contained in:
parent
5c31e3b411
commit
5a79a4edce
9
.github/workflows/dashboard-ci.yml
vendored
9
.github/workflows/dashboard-ci.yml
vendored
@ -42,7 +42,12 @@ jobs:
|
||||
|
||||
- name: Install requirements
|
||||
run: |
|
||||
sudo apt install -y bats
|
||||
sudo apt-get update
|
||||
# Install bats-core >= 1.5.0 to support bats_require_minimum_version
|
||||
sudo apt-get install -y git curl
|
||||
git clone --depth 1 https://github.com/bats-core/bats-core.git /tmp/bats-core
|
||||
sudo /tmp/bats-core/install.sh /usr/local
|
||||
bats --version
|
||||
./acore.sh install-deps
|
||||
|
||||
- name: Run bash script tests for ${{ matrix.test-module }}
|
||||
@ -50,7 +55,7 @@ jobs:
|
||||
TERM: xterm-256color
|
||||
run: |
|
||||
cd apps/test-framework
|
||||
./run-tests.sh --tap
|
||||
./run-tests.sh --tap --all
|
||||
|
||||
build-and-test:
|
||||
name: Build and Integration Test
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
# Require minimum BATS version to avoid warnings
|
||||
bats_require_minimum_version 1.5.0
|
||||
# Require minimum BATS version when supported (older distro packages lack this)
|
||||
if type -t bats_require_minimum_version >/dev/null 2>&1; then
|
||||
bats_require_minimum_version 1.5.0
|
||||
fi
|
||||
|
||||
# AzerothCore Compiler Scripts Test Suite
|
||||
# Tests the functionality of the compiler scripts using the unified test framework
|
||||
|
||||
@ -118,142 +118,28 @@ function inst_allInOne() {
|
||||
inst_download_client_data
|
||||
}
|
||||
|
||||
function inst_getVersionBranch() {
|
||||
local res="master"
|
||||
local v="not-defined"
|
||||
local MODULE_MAJOR=0
|
||||
local MODULE_MINOR=0
|
||||
local MODULE_PATCH=0
|
||||
local MODULE_SPECIAL=0;
|
||||
local ACV_MAJOR=0
|
||||
local ACV_MINOR=0
|
||||
local ACV_PATCH=0
|
||||
local ACV_SPECIAL=0;
|
||||
local curldata=$(curl -f --silent -H 'Cache-Control: no-cache' "$1" || echo "{}")
|
||||
local parsed=$(echo "$curldata" | "$AC_PATH_DEPS/jsonpath/JSONPath.sh" -b '$.compatibility.*.[version,branch]')
|
||||
############################################################
|
||||
# Module helpers and dispatcher #
|
||||
############################################################
|
||||
|
||||
semverParseInto "$ACORE_VERSION" ACV_MAJOR ACV_MINOR ACV_PATCH ACV_SPECIAL
|
||||
|
||||
if [[ ! -z "$parsed" ]]; then
|
||||
readarray -t vers < <(echo "$parsed")
|
||||
local idx
|
||||
res="none"
|
||||
# since we've the pair version,branch alternated in not associative and one-dimensional
|
||||
# array, we've to simulate the association with length/2 trick
|
||||
for idx in `seq 0 $((${#vers[*]}/2-1))`; do
|
||||
semverParseInto "${vers[idx*2]}" MODULE_MAJOR MODULE_MINOR MODULE_PATCH MODULE_SPECIAL
|
||||
if [[ $MODULE_MAJOR -eq $ACV_MAJOR && $MODULE_MINOR -le $ACV_MINOR ]]; then
|
||||
res="${vers[idx*2+1]}"
|
||||
v="${vers[idx*2]}"
|
||||
fi
|
||||
done
|
||||
# Returns the default branch name of a GitHub repo in the azerothcore org.
|
||||
# If the API call fails, defaults to "master".
|
||||
function inst_get_default_branch() {
|
||||
local repo="$1"
|
||||
local def
|
||||
def=$(curl --silent "https://api.github.com/repos/azerothcore/${repo}" \
|
||||
| "$AC_PATH_DEPS/jsonpath/JSONPath.sh" -b '$.default_branch')
|
||||
if [ -z "$def" ]; then
|
||||
def="master"
|
||||
fi
|
||||
|
||||
echo "$v" "$res"
|
||||
}
|
||||
|
||||
function inst_module_search {
|
||||
|
||||
local res="$1"
|
||||
local idx=0;
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Type what to search or leave blank for full list"
|
||||
read -p "Insert name: " res
|
||||
fi
|
||||
|
||||
local search="+$res"
|
||||
|
||||
echo "Searching $res..."
|
||||
echo "";
|
||||
|
||||
readarray -t MODS < <(curl --silent "https://api.github.com/search/repositories?q=org%3Aazerothcore${search}+fork%3Atrue+topic%3Acore-module+sort%3Astars&type=" \
|
||||
| "$AC_PATH_DEPS/jsonpath/JSONPath.sh" -b '$.items.*.name')
|
||||
while (( ${#MODS[@]} > idx )); do
|
||||
mod="${MODS[idx++]}"
|
||||
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/azerothcore/$mod/master/acore-module.json")
|
||||
|
||||
if [[ "$b" != "none" ]]; then
|
||||
echo "-> $mod (tested with AC version: $v)"
|
||||
else
|
||||
echo "-> $mod (no revision available for AC v$AC_VERSION, it could not work!)"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "";
|
||||
echo "";
|
||||
}
|
||||
|
||||
function inst_module_install {
|
||||
local res
|
||||
if [ -z "$1" ]; then
|
||||
echo "Type the name of the module to install"
|
||||
read -p "Insert name: " res
|
||||
else
|
||||
res="$1"
|
||||
fi
|
||||
|
||||
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/azerothcore/$res/master/acore-module.json")
|
||||
|
||||
if [[ "$b" != "none" ]]; then
|
||||
Joiner:add_repo "https://github.com/azerothcore/$res" "$res" "$b" && echo "Done, please re-run compiling and db assembly. Read instruction on module repository for more information"
|
||||
else
|
||||
echo "Cannot install $res module: it doesn't exists or no version compatible with AC v$ACORE_VERSION are available"
|
||||
fi
|
||||
|
||||
echo "";
|
||||
echo "";
|
||||
}
|
||||
|
||||
function inst_module_update {
|
||||
local res;
|
||||
local _tmp;
|
||||
local branch;
|
||||
local p;
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Type the name of the module to update"
|
||||
read -p "Insert name: " res
|
||||
else
|
||||
res="$1"
|
||||
fi
|
||||
|
||||
_tmp=$PWD
|
||||
|
||||
if [ -d "$J_PATH_MODULES/$res/" ]; then
|
||||
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/azerothcore/$res/master/acore-module.json")
|
||||
|
||||
cd "$J_PATH_MODULES/$res/"
|
||||
|
||||
# use current branch if something wrong with json
|
||||
if [[ "$v" == "none" || "$v" == "not-defined" ]]; then
|
||||
b=`git rev-parse --abbrev-ref HEAD`
|
||||
fi
|
||||
|
||||
Joiner:upd_repo "https://github.com/azerothcore/$res" "$res" "$b" && echo "Done, please re-run compiling and db assembly" || echo "Cannot update"
|
||||
cd $_tmp
|
||||
else
|
||||
echo "Cannot update! Path doesn't exist"
|
||||
fi;
|
||||
|
||||
echo "";
|
||||
echo "";
|
||||
}
|
||||
|
||||
function inst_module_remove {
|
||||
if [ -z "$1" ]; then
|
||||
echo "Type the name of the module to remove"
|
||||
read -p "Insert name: " res
|
||||
else
|
||||
res="$1"
|
||||
fi
|
||||
|
||||
Joiner:remove "$res" && echo "Done, please re-run compiling" || echo "Cannot remove"
|
||||
|
||||
echo "";
|
||||
echo "";
|
||||
echo "$def"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Module Management System
|
||||
# =============================================================================
|
||||
# Load the module manager functions from the dedicated modules-manager directory
|
||||
source "$AC_PATH_INSTALLER/includes/modules-manager/modules.sh"
|
||||
|
||||
function inst_simple_restarter {
|
||||
echo "Running $1 ..."
|
||||
@ -292,4 +178,4 @@ function inst_download_client_data {
|
||||
&& echo "unzip downloaded file in $path..." && unzip -q -o "$zipPath" -d "$path/" \
|
||||
&& echo "Remove downloaded file" && rm "$zipPath" \
|
||||
&& echo "INSTALLED_VERSION=$VERSION" > "$dataVersionFile"
|
||||
}
|
||||
}
|
||||
188
apps/installer/includes/modules-manager/README.md
Normal file
188
apps/installer/includes/modules-manager/README.md
Normal file
@ -0,0 +1,188 @@
|
||||
# AzerothCore Module Manager
|
||||
|
||||
This directory contains the module management system for AzerothCore, providing advanced functionality for installing, updating, and managing server modules.
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- **Advanced Syntax**: Support for `repo[:dirname][@branch[:commit]]` format
|
||||
- **Cross-Format Recognition**: Intelligent matching across URLs, SSH, and simple names
|
||||
- **Custom Directory Naming**: Prevent conflicts with custom directory names
|
||||
- **Duplicate Prevention**: Smart detection and prevention of duplicate installations
|
||||
- **Multi-Host Support**: GitHub, GitLab, and other Git hosts
|
||||
|
||||
## 📁 File Structure
|
||||
|
||||
```
|
||||
modules-manager/
|
||||
├── modules.sh # Core module management functions
|
||||
└── README.md # This documentation file
|
||||
```
|
||||
|
||||
## 🔧 Module Specification Syntax
|
||||
|
||||
The module manager supports flexible syntax for specifying modules:
|
||||
|
||||
### New Syntax Format
|
||||
```bash
|
||||
repo[:dirname][@branch[:commit]]
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
| Specification | Description |
|
||||
|---------------|-------------|
|
||||
| `mod-transmog` | Simple module name, uses default branch and directory |
|
||||
| `mod-transmog:my-custom-dir` | Custom directory name |
|
||||
| `mod-transmog@develop` | Specific branch |
|
||||
| `mod-transmog:custom@develop:abc123` | Custom directory, branch, and commit |
|
||||
| `https://github.com/owner/repo.git@main` | Full URL with branch |
|
||||
| `git@github.com:owner/repo.git:custom-dir` | SSH URL with custom directory |
|
||||
|
||||
## 🎯 Usage Examples
|
||||
|
||||
### Installing Modules
|
||||
|
||||
```bash
|
||||
# Simple module installation
|
||||
./acore.sh module install mod-transmog
|
||||
|
||||
# Install with custom directory name
|
||||
./acore.sh module install mod-transmog:my-transmog-dir
|
||||
|
||||
# Install specific branch
|
||||
./acore.sh module install mod-transmog@develop
|
||||
|
||||
# Install with full specification
|
||||
./acore.sh module install mod-transmog:custom-dir@develop:abc123
|
||||
|
||||
# Install from URL
|
||||
./acore.sh module install https://github.com/azerothcore/mod-transmog.git@main
|
||||
|
||||
# Install multiple modules
|
||||
./acore.sh module install mod-transmog mod-eluna:custom-eluna
|
||||
|
||||
# Install all modules from list
|
||||
./acore.sh module install --all
|
||||
```
|
||||
|
||||
### Updating Modules
|
||||
|
||||
```bash
|
||||
# Update specific module
|
||||
./acore.sh module update mod-transmog
|
||||
|
||||
# Update all modules
|
||||
./acore.sh module update --all
|
||||
|
||||
# Update with branch specification
|
||||
./acore.sh module update mod-transmog@develop
|
||||
```
|
||||
|
||||
### Removing Modules
|
||||
|
||||
```bash
|
||||
# Remove by simple name (cross-format recognition)
|
||||
./acore.sh module remove mod-transmog
|
||||
|
||||
# Remove by URL (recognizes same module)
|
||||
./acore.sh module remove https://github.com/azerothcore/mod-transmog.git
|
||||
|
||||
# Remove multiple modules
|
||||
./acore.sh module remove mod-transmog mod-eluna
|
||||
```
|
||||
|
||||
### Searching Modules
|
||||
|
||||
```bash
|
||||
# Search for modules
|
||||
./acore.sh module search transmog
|
||||
|
||||
# Search with multiple terms
|
||||
./acore.sh module search auction house
|
||||
|
||||
# Show all available modules
|
||||
./acore.sh module search
|
||||
```
|
||||
|
||||
## 🔍 Cross-Format Recognition
|
||||
|
||||
The system intelligently recognizes the same module across different specification formats:
|
||||
|
||||
```bash
|
||||
# These all refer to the same module:
|
||||
mod-transmog
|
||||
azerothcore/mod-transmog
|
||||
https://github.com/azerothcore/mod-transmog.git
|
||||
git@github.com:azerothcore/mod-transmog.git
|
||||
```
|
||||
|
||||
This allows:
|
||||
- Installing with one format and removing with another
|
||||
- Preventing duplicates regardless of specification format
|
||||
- Consistent module tracking across different input methods
|
||||
|
||||
## 🛡️ Conflict Prevention
|
||||
|
||||
The system prevents common conflicts:
|
||||
|
||||
### Directory Conflicts
|
||||
```bash
|
||||
# If 'mod-transmog' directory already exists:
|
||||
$ ./acore.sh module install mod-transmog:mod-transmog
|
||||
Error: Directory 'mod-transmog' already exists.
|
||||
Possible solutions:
|
||||
1. Use a different directory name: mod-transmog:my-custom-name
|
||||
2. Remove the existing directory first
|
||||
3. Use the update command if this is the same module
|
||||
```
|
||||
|
||||
## 🔄 Integration
|
||||
|
||||
### Including in Scripts
|
||||
```bash
|
||||
# Source the module functions
|
||||
source "$AC_PATH_INSTALLER/includes/modules-manager/modules.sh"
|
||||
|
||||
# Use module functions
|
||||
inst_module_install "mod-transmog:custom-dir@develop"
|
||||
```
|
||||
|
||||
### Testing
|
||||
The module system is tested through the main installer test suite:
|
||||
```bash
|
||||
./apps/installer/test/test_module_commands.bats
|
||||
```
|
||||
|
||||
## 📋 Module List Format
|
||||
|
||||
Modules are tracked in `conf/modules.list` with the format:
|
||||
```
|
||||
# Comments start with #
|
||||
repo_reference branch commit
|
||||
|
||||
# Examples:
|
||||
azerothcore/mod-transmog master abc123def456
|
||||
https://github.com/custom/mod-custom.git develop def456abc789
|
||||
mod-eluna:custom-eluna-dir main 789abc123def
|
||||
```
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables
|
||||
- `MODULES_LIST_FILE`: Override default modules list path
|
||||
- `J_PATH_MODULES`: Modules installation directory
|
||||
- `AC_PATH_ROOT`: AzerothCore root path
|
||||
|
||||
### Default Paths
|
||||
- Modules list: `$AC_PATH_ROOT/conf/modules.list`
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
When modifying the module manager:
|
||||
|
||||
1. Maintain backwards compatibility
|
||||
2. Update tests in `test_module_commands.bats`
|
||||
3. Update this documentation
|
||||
4. Test cross-format recognition thoroughly
|
||||
5. Ensure helpful error messages
|
||||
|
||||
|
||||
735
apps/installer/includes/modules-manager/modules.sh
Normal file
735
apps/installer/includes/modules-manager/modules.sh
Normal file
@ -0,0 +1,735 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# =============================================================================
|
||||
# AzerothCore Module Manager Functions
|
||||
# =============================================================================
|
||||
# This file contains all functions related to module management in AzerothCore.
|
||||
# It provides capabilities for installing, updating, removing, and searching
|
||||
# modules with support for advanced syntax and intelligent cross-format matching.
|
||||
#
|
||||
# Main Features:
|
||||
# - Advanced syntax: repo[:dirname][@branch[:commit]]
|
||||
# - Legacy compatibility: repo:branch:commit
|
||||
# - Cross-format module recognition (URLs, SSH, simple names)
|
||||
# - Custom directory naming to prevent conflicts
|
||||
# - Intelligent duplicate prevention
|
||||
#
|
||||
# Usage:
|
||||
# source "path/to/modules.sh"
|
||||
# inst_module_install "mod-transmog:my-custom-dir@develop:abc123"
|
||||
#
|
||||
# =============================================================================
|
||||
|
||||
# Dispatcher for the unified `module` command.
|
||||
# Usage: ./acore.sh module <search|install|update|remove> [args...]
|
||||
function inst_module() {
|
||||
# Normalize arguments into an array
|
||||
local tokens=()
|
||||
read -r -a tokens <<< "$*"
|
||||
local cmd="${tokens[0]}"
|
||||
local args=("${tokens[@]:1}")
|
||||
|
||||
case "$cmd" in
|
||||
""|"help"|"-h"|"--help")
|
||||
echo "Usage:"
|
||||
echo " ./acore.sh module search [terms...]"
|
||||
echo " ./acore.sh module install [--all | modules...]"
|
||||
echo " modules can be specified as: name[:branch[:commit]]"
|
||||
echo " ./acore.sh module update [modules...]"
|
||||
echo " ./acore.sh module remove [modules...]"
|
||||
;;
|
||||
"search"|"s")
|
||||
inst_module_search "${args[@]}"
|
||||
;;
|
||||
"install"|"i")
|
||||
inst_module_install "${args[@]}"
|
||||
;;
|
||||
"update"|"u")
|
||||
inst_module_update "${args[@]}"
|
||||
;;
|
||||
"remove"|"r")
|
||||
inst_module_remove "${args[@]}"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown subcommand: $cmd"
|
||||
echo "Try: ./acore.sh module help"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Module Specification Parsing
|
||||
# =============================================================================
|
||||
|
||||
# Parse a module spec with advanced syntax:
|
||||
# - New syntax: repo[:dirname][@branch[:commit]]
|
||||
#
|
||||
# Examples:
|
||||
# "mod-transmog" -> uses default branch, directory name = mod-transmog
|
||||
# "mod-transmog:custom-dir" -> uses default branch, directory name = custom-dir
|
||||
# "mod-transmog@develop" -> uses develop branch, directory name = mod-transmog
|
||||
# "mod-transmog:custom-dir@develop:abc123" -> custom directory, develop branch, specific commit
|
||||
#
|
||||
# Output: "repo_ref owner name branch commit url dirname"
|
||||
function inst_parse_module_spec() {
|
||||
local spec="$1"
|
||||
|
||||
local dirname="" branch="" commit="" repo_part=""
|
||||
|
||||
# Parse the new syntax: repo[:dirname][@branch[:commit]]
|
||||
|
||||
# First, extract custom directory name if present (format: repo:dirname@branch)
|
||||
local repo_with_branch="$spec"
|
||||
if [[ "$spec" =~ ^([^@:]+):([^@:]+)(@.*)?$ ]]; then
|
||||
repo_with_branch="${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
|
||||
dirname="${BASH_REMATCH[2]}"
|
||||
fi
|
||||
|
||||
# Now parse branch and commit from the repo part
|
||||
if [[ "$repo_with_branch" =~ ^([^@]+)@([^:]+)(:(.+))?$ ]]; then
|
||||
repo_part="${BASH_REMATCH[1]}"
|
||||
branch="${BASH_REMATCH[2]}"
|
||||
commit="${BASH_REMATCH[4]:-}"
|
||||
else
|
||||
repo_part="$repo_with_branch"
|
||||
fi
|
||||
|
||||
# Normalize repo reference and extract owner/name.
|
||||
local repo_ref owner name url owner_repo
|
||||
repo_ref="$repo_part"
|
||||
|
||||
# If repo_ref is a URL, extract owner/name from path when possible
|
||||
if [[ "$repo_ref" =~ :// ]] || [[ "$repo_ref" =~ ^git@ ]]; then
|
||||
# Extract owner/name (last two path components)
|
||||
owner_repo=$(echo "$repo_ref" | sed -E 's#(git@[^:]+:|https?://[^/]+/|ssh://[^/]+/)?(.*?)(\.git)?$#\2#')
|
||||
owner="$(echo "$owner_repo" | awk -F'/' '{print $(NF-1)}')"
|
||||
name="$(echo "$owner_repo" | awk -F'/' '{print $NF}' | sed -E 's/\.git$//')"
|
||||
else
|
||||
owner_repo="$repo_ref"
|
||||
if [[ "$owner_repo" == *"/"* ]]; then
|
||||
owner="$(echo "$owner_repo" | cut -d'/' -f1)"
|
||||
name="$(echo "$owner_repo" | cut -d'/' -f2)"
|
||||
else
|
||||
owner="azerothcore"
|
||||
name="$owner_repo"
|
||||
repo_ref="$owner/$name"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build URL only if repo_ref is not already a URL
|
||||
if [[ "$repo_ref" =~ :// ]] || [[ "$repo_ref" =~ ^git@ ]]; then
|
||||
url="$repo_ref"
|
||||
else
|
||||
url="https://github.com/${repo_ref}"
|
||||
fi
|
||||
|
||||
# Use custom dirname if provided, otherwise default to module name
|
||||
if [ -z "$dirname" ]; then
|
||||
dirname="$name"
|
||||
fi
|
||||
|
||||
echo "$repo_ref" "$owner" "$name" "${branch:--}" "${commit:--}" "$url" "$dirname"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Cross-Format Module Recognition
|
||||
# =============================================================================
|
||||
|
||||
# Extract owner/name from any repository reference for intelligent matching.
|
||||
# This enables recognizing the same module regardless of specification format.
|
||||
#
|
||||
# Supported formats:
|
||||
# - GitHub HTTPS: https://github.com/owner/name.git
|
||||
# - GitHub SSH: git@github.com:owner/name.git
|
||||
# - GitLab HTTPS: https://gitlab.com/owner/name.git
|
||||
# - Owner/name: owner/name
|
||||
# - Simple name: mod-name (assumes azerothcore namespace)
|
||||
#
|
||||
# Returns: "owner/name" format for consistent comparison
|
||||
function inst_extract_owner_name {
|
||||
local repo_ref="$1"
|
||||
|
||||
# For URLs, don't remove dirname suffix since : is part of the URL
|
||||
local base_ref="$repo_ref"
|
||||
if [[ ! "$repo_ref" =~ :// ]] && [[ ! "$repo_ref" =~ ^git@ ]]; then
|
||||
# Only remove dirname suffix for non-URL formats
|
||||
base_ref="${repo_ref%%:*}"
|
||||
fi
|
||||
|
||||
if [[ "$base_ref" =~ ^https?://github\.com/([^/]+)/([^/]+)(\.git)?(/.*)?$ ]]; then
|
||||
# HTTPS URL format - check this first before owner/name pattern
|
||||
local name="${BASH_REMATCH[2]}"
|
||||
name="${name%.git}" # Remove .git suffix if present
|
||||
echo "${BASH_REMATCH[1]}/$name"
|
||||
elif [[ "$base_ref" =~ ^https?://gitlab\.com/([^/]+)/([^/]+)(\.git)?(/.*)?$ ]]; then
|
||||
# GitLab URL format
|
||||
local name="${BASH_REMATCH[2]}"
|
||||
name="${name%.git}" # Remove .git suffix if present
|
||||
echo "${BASH_REMATCH[1]}/$name"
|
||||
elif [[ "$base_ref" =~ ^git@github\.com:([^/]+)/([^/]+)(\.git)?$ ]]; then
|
||||
# SSH URL format
|
||||
local name="${BASH_REMATCH[2]}"
|
||||
name="${name%.git}" # Remove .git suffix if present
|
||||
echo "${BASH_REMATCH[1]}/$name"
|
||||
elif [[ "$base_ref" =~ ^[^/]+/[^/]+$ ]]; then
|
||||
# Format: owner/name (check after URL patterns)
|
||||
echo "$base_ref"
|
||||
elif [[ "$base_ref" =~ ^(mod-|module-)?([a-zA-Z0-9-]+)$ ]]; then
|
||||
# Simple module name, assume azerothcore namespace
|
||||
local modname="${BASH_REMATCH[2]}"
|
||||
if [[ "$base_ref" == mod-* ]]; then
|
||||
modname="$base_ref"
|
||||
else
|
||||
modname="mod-$modname"
|
||||
fi
|
||||
echo "azerothcore/$modname"
|
||||
else
|
||||
# Unknown format, return as-is
|
||||
echo "$base_ref"
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Module List Management
|
||||
# =============================================================================
|
||||
|
||||
# Returns path to modules list file (configurable via MODULES_LIST_FILE).
|
||||
function inst_modules_list_path() {
|
||||
local path="${MODULES_LIST_FILE:-"$AC_PATH_ROOT/conf/modules.list"}"
|
||||
echo "$path"
|
||||
}
|
||||
|
||||
# Ensure the modules list file exists and its directory is created.
|
||||
function inst_mod_list_ensure() {
|
||||
local file
|
||||
file="$(inst_modules_list_path)"
|
||||
mkdir -p "$(dirname "$file")"
|
||||
[ -f "$file" ] || touch "$file"
|
||||
}
|
||||
|
||||
# Read modules list into stdout as triplets: "name branch commit"
|
||||
# Skips comments (# ...) and blank lines.
|
||||
function inst_mod_list_read() {
|
||||
local file
|
||||
file="$(inst_modules_list_path)"
|
||||
[ -f "$file" ] || return 0
|
||||
# shellcheck disable=SC2013
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
|
||||
echo "$line"
|
||||
done < "$file"
|
||||
}
|
||||
|
||||
# Add or update an entry in the list: repo_ref branch commit
|
||||
# Removes any existing entries with the same owner/name to avoid duplicates
|
||||
function inst_mod_list_upsert() {
|
||||
local repo_ref="$1"; shift
|
||||
local branch="$1"; shift
|
||||
local commit="$1"; shift
|
||||
local target_owner_name
|
||||
target_owner_name=$(inst_extract_owner_name "$repo_ref")
|
||||
|
||||
inst_mod_list_ensure
|
||||
local file tmp tmp_uns tmp_sorted
|
||||
file="$(inst_modules_list_path)"
|
||||
tmp="${file}.tmp"
|
||||
tmp_uns="${file}.unsorted"
|
||||
tmp_sorted="${file}.sorted"
|
||||
|
||||
# Build a list without existing duplicates
|
||||
: > "$tmp_uns"
|
||||
while read -r existing_ref existing_branch existing_commit; do
|
||||
[[ -z "$existing_ref" ]] && continue
|
||||
local existing_owner_name
|
||||
existing_owner_name=$(inst_extract_owner_name "$existing_ref")
|
||||
if [[ "$existing_owner_name" != "$target_owner_name" ]]; then
|
||||
echo "$existing_ref $existing_branch $existing_commit" >> "$tmp_uns"
|
||||
fi
|
||||
done < <(inst_mod_list_read)
|
||||
# Add/replace the new entry (preserving original repo_ref format)
|
||||
echo "$repo_ref $branch $commit" >> "$tmp_uns"
|
||||
|
||||
# Create key-prefixed lines to sort by normalized owner/name
|
||||
: > "$tmp"
|
||||
while read -r r b c; do
|
||||
[[ -z "$r" ]] && continue
|
||||
local k
|
||||
k=$(inst_extract_owner_name "$r")
|
||||
printf "%s\t%s %s %s\n" "$k" "$r" "$b" "$c" >> "$tmp"
|
||||
done < "$tmp_uns"
|
||||
|
||||
# Stable sort by key and strip the key
|
||||
LC_ALL=C sort -t $'\t' -k1,1 -s "$tmp" | cut -f2- > "$tmp_sorted" && mv "$tmp_sorted" "$file"
|
||||
rm -f "$tmp" "$tmp_uns" "$tmp_sorted" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Remove an entry from the list by matching owner/name.
|
||||
# This allows removing modules regardless of how they were specified (URL vs owner/name)
|
||||
function inst_mod_list_remove() {
|
||||
local repo_ref="$1"
|
||||
local target_owner_name
|
||||
target_owner_name=$(inst_extract_owner_name "$repo_ref")
|
||||
|
||||
local file
|
||||
file="$(inst_modules_list_path)"
|
||||
[ -f "$file" ] || return 0
|
||||
|
||||
local tmp_uns="${file}.unsorted"
|
||||
local tmp="${file}.tmp"
|
||||
local tmp_sorted="${file}.sorted"
|
||||
|
||||
# Keep only lines where owner/name doesn't match
|
||||
: > "$tmp_uns"
|
||||
while read -r existing_ref existing_branch existing_commit; do
|
||||
[[ -z "$existing_ref" ]] && continue
|
||||
local existing_owner_name
|
||||
existing_owner_name=$(inst_extract_owner_name "$existing_ref")
|
||||
if [[ "$existing_owner_name" != "$target_owner_name" ]]; then
|
||||
echo "$existing_ref $existing_branch $existing_commit" >> "$tmp_uns"
|
||||
fi
|
||||
done < <(inst_mod_list_read)
|
||||
|
||||
# Key-prefix and sort for deterministic alphabetical order
|
||||
: > "$tmp"
|
||||
while read -r r b c; do
|
||||
[[ -z "$r" ]] && continue
|
||||
local k
|
||||
k=$(inst_extract_owner_name "$r")
|
||||
printf "%s\t%s %s %s\n" "$k" "$r" "$b" "$c" >> "$tmp"
|
||||
done < "$tmp_uns"
|
||||
|
||||
LC_ALL=C sort -t $'\t' -k1,1 -s "$tmp" | cut -f2- > "$tmp_sorted" && mv "$tmp_sorted" "$file"
|
||||
rm -f "$tmp" "$tmp_uns" "$tmp_sorted" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Check if a module is already installed by comparing owner/name
|
||||
# Returns the existing repo_ref if found, empty if not found
|
||||
function inst_mod_is_installed() {
|
||||
local spec="$1"
|
||||
local target_owner_name
|
||||
target_owner_name=$(inst_extract_owner_name "$spec")
|
||||
|
||||
# Use a different approach: read into a variable first, then process
|
||||
local modules_content
|
||||
modules_content=$(inst_mod_list_read)
|
||||
|
||||
# Process each line
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" ]] && continue
|
||||
read -r repo_ref branch commit <<< "$line"
|
||||
local existing_owner_name
|
||||
existing_owner_name=$(inst_extract_owner_name "$repo_ref")
|
||||
if [[ "$existing_owner_name" == "$target_owner_name" ]]; then
|
||||
echo "$repo_ref" # Return the existing entry
|
||||
return 0
|
||||
fi
|
||||
done <<< "$modules_content"
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Conflict Detection and Validation
|
||||
# =============================================================================
|
||||
|
||||
# Check for module directory conflicts with helpful error messages
|
||||
function inst_check_module_conflict {
|
||||
local dirname="$1"
|
||||
local repo_ref="$2"
|
||||
|
||||
if [ -d "$J_PATH_MODULES/$dirname" ]; then
|
||||
echo "Error: Directory '$dirname' already exists."
|
||||
echo "Possible solutions:"
|
||||
echo " 1. Use a different directory name: $repo_ref:my-custom-name"
|
||||
echo " 2. Remove the existing directory first"
|
||||
echo " 3. Use the update command if this is the same module"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Module Operations
|
||||
# =============================================================================
|
||||
|
||||
# Get version and branch information from acore-module.json
|
||||
function inst_getVersionBranch() {
|
||||
local res="master"
|
||||
local v="not-defined"
|
||||
local MODULE_MAJOR=0
|
||||
local MODULE_MINOR=0
|
||||
local MODULE_PATCH=0
|
||||
local MODULE_SPECIAL=0;
|
||||
local ACV_MAJOR=0
|
||||
local ACV_MINOR=0
|
||||
local ACV_PATCH=0
|
||||
local ACV_SPECIAL=0;
|
||||
local curldata=$(curl -f --silent -H 'Cache-Control: no-cache' "$1" || echo "{}")
|
||||
local parsed=$(echo "$curldata" | "$AC_PATH_DEPS/jsonpath/JSONPath.sh" -b '$.compatibility.*.[version,branch]')
|
||||
|
||||
semverParseInto "$ACORE_VERSION" ACV_MAJOR ACV_MINOR ACV_PATCH ACV_SPECIAL
|
||||
|
||||
if [[ ! -z "$parsed" ]]; then
|
||||
readarray -t vers < <(echo "$parsed")
|
||||
local idx
|
||||
res="none"
|
||||
# since we've the pair version,branch alternated in not associative and one-dimensional
|
||||
# array, we've to simulate the association with length/2 trick
|
||||
for idx in `seq 0 $((${#vers[*]}/2-1))`; do
|
||||
semverParseInto "${vers[idx*2]}" MODULE_MAJOR MODULE_MINOR MODULE_PATCH MODULE_SPECIAL
|
||||
if [[ $MODULE_MAJOR -eq $ACV_MAJOR && $MODULE_MINOR -le $ACV_MINOR ]]; then
|
||||
res="${vers[idx*2+1]}"
|
||||
v="${vers[idx*2]}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$v" "$res"
|
||||
}
|
||||
|
||||
# Search for modules in the AzerothCore repository
|
||||
function inst_module_search {
|
||||
# Accept 0..N search terms; if none provided, prompt the user.
|
||||
local terms=("$@")
|
||||
if [ ${#terms[@]} -eq 0 ]; then
|
||||
echo "Type what to search (blank for full list)"
|
||||
read -p "Insert name(s): " _line
|
||||
if [ -n "$_line" ]; then
|
||||
read -r -a terms <<< "$_line"
|
||||
fi
|
||||
fi
|
||||
|
||||
local CATALOG_URL="https://www.azerothcore.org/data/catalogue.json"
|
||||
|
||||
echo "Searching ${terms[*]}..."
|
||||
echo ""
|
||||
|
||||
# Build candidate list from catalogue (full_name = owner/repo)
|
||||
local MODS=()
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
mapfile -t MODS < <(curl --silent -L "$CATALOG_URL" \
|
||||
| jq -r '
|
||||
[ .. | objects
|
||||
| select(.full_name and .topics)
|
||||
| select(.topics | index("azerothcore-module"))
|
||||
]
|
||||
| unique_by(.full_name)
|
||||
| sort_by(.stargazers_count // 0) | reverse
|
||||
| .[].full_name
|
||||
')
|
||||
else
|
||||
# Fallback without jq: best-effort extraction of owner/repo
|
||||
mapfile -t MODS < <(curl --silent -L "$CATALOG_URL" \
|
||||
| grep -oE '\"full_name\"\\s*:\\s*\"[^\"/[:space:]]+/[^\"[:space:]]+\"' \
|
||||
| sed -E 's/.*\"full_name\"\\s*:\\s*\"([^\"]+)\".*/\\1/' \
|
||||
| sort -u)
|
||||
fi
|
||||
|
||||
# Local AND filter on user terms (case-insensitive) against full_name
|
||||
if (( ${#terms[@]} > 0 )); then
|
||||
local filtered=()
|
||||
local item
|
||||
for item in "${MODS[@]}"; do
|
||||
local keep=1
|
||||
local lower="${item,,}"
|
||||
local t
|
||||
for t in "${terms[@]}"; do
|
||||
[ -z "$t" ] && continue
|
||||
if [[ "$lower" != *"${t,,}"* ]]; then
|
||||
keep=0; break
|
||||
fi
|
||||
done
|
||||
(( keep )) && filtered+=("$item")
|
||||
done
|
||||
MODS=("${filtered[@]}")
|
||||
fi
|
||||
|
||||
if (( ${#MODS[@]} == 0 )); then
|
||||
echo "No results."
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
|
||||
local idx=0
|
||||
while (( ${#MODS[@]} > idx )); do
|
||||
local mod_full="${MODS[idx++]}" # owner/repo
|
||||
local mod="${mod_full##*/}" # repo name only for display
|
||||
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/${mod_full}/master/acore-module.json")
|
||||
|
||||
if [[ "$b" != "none" ]]; then
|
||||
echo "-> $mod (tested with AC version: $v)"
|
||||
else
|
||||
echo "-> $mod (NOTE: The module latest tested AC revision is Unknown)"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
}
|
||||
|
||||
|
||||
# Install one or more modules with advanced syntax support
|
||||
function inst_module_install {
|
||||
# Support multiple modules and the --all flag; prompt if none specified.
|
||||
local args=("$@")
|
||||
local use_all=false
|
||||
if [ ${#args[@]} -gt 0 ] && { [ "${args[0]}" = "--all" ] || [ "${args[0]}" = "-a" ]; }; then
|
||||
use_all=true
|
||||
shift || true
|
||||
fi
|
||||
|
||||
local modules=("$@")
|
||||
|
||||
echo "Installing modules: ${modules[*]}"
|
||||
|
||||
if $use_all; then
|
||||
# Install all modules from the list (respecting recorded branch and commit).
|
||||
inst_mod_list_ensure
|
||||
local line repo_ref branch commit url owner modname dirname
|
||||
|
||||
# First pass: detect duplicate target directories (flat structure)
|
||||
declare -A _seen _first
|
||||
local dup_error=0
|
||||
while read -r repo_ref branch commit; do
|
||||
[ -z "$repo_ref" ] && continue
|
||||
parsed_output=$(inst_parse_module_spec "$repo_ref")
|
||||
IFS=' ' read -r _ owner modname _ _ url dirname <<< "$parsed_output"
|
||||
# dirname defaults to repo name; flat install path uses dirname only
|
||||
if [[ -n "${_seen[$dirname]:-}" ]]; then
|
||||
echo "Error: duplicate module target directory '$dirname' detected in modules.list:"
|
||||
echo " - ${_first[$dirname]}"
|
||||
echo " - ${repo_ref}"
|
||||
echo "Use a custom folder name to disambiguate, e.g.: ${repo_ref}:$dirname-alt"
|
||||
dup_error=1
|
||||
else
|
||||
_seen[$dirname]=1
|
||||
_first[$dirname]="$repo_ref"
|
||||
fi
|
||||
done < <(inst_mod_list_read)
|
||||
if [[ "$dup_error" -ne 0 ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Second pass: install in flat modules directory (no owner subfolders)
|
||||
while read -r repo_ref branch commit; do
|
||||
[ -z "$repo_ref" ] && continue
|
||||
parsed_output=$(inst_parse_module_spec "$repo_ref")
|
||||
IFS=' ' read -r _ owner modname _ _ url dirname <<< "$parsed_output"
|
||||
|
||||
if [ -d "$J_PATH_MODULES/$dirname" ]; then
|
||||
echo "[$repo_ref] Already installed (skipping)."
|
||||
continue
|
||||
fi
|
||||
|
||||
if Joiner:add_repo "$url" "$dirname" "$branch" ""; then
|
||||
# Checkout the recorded commit if present
|
||||
if [ -n "$commit" ]; then
|
||||
git -C "$J_PATH_MODULES/$dirname" fetch --all --quiet || true
|
||||
if git -C "$J_PATH_MODULES/$dirname" rev-parse --verify "$commit" >/dev/null 2>&1; then
|
||||
git -C "$J_PATH_MODULES/$dirname" checkout --quiet "$commit"
|
||||
fi
|
||||
fi
|
||||
local curCommit
|
||||
curCommit=$(git -C "$J_PATH_MODULES/$dirname" rev-parse HEAD 2>/dev/null || echo "")
|
||||
inst_mod_list_upsert "$repo_ref" "$branch" "$curCommit"
|
||||
echo "[$repo_ref] Installed."
|
||||
else
|
||||
echo "[$repo_ref] Install failed."
|
||||
exit 1;
|
||||
fi
|
||||
done < <(inst_mod_list_read)
|
||||
else
|
||||
# Install specified modules; prompt if none specified.
|
||||
if [ ${#modules[@]} -eq 0 ]; then
|
||||
echo "Type the name(s) of the module(s) to install"
|
||||
read -p "Insert name(s): " _line
|
||||
read -r -a modules <<< "$_line"
|
||||
fi
|
||||
|
||||
local spec name override_branch override_commit v b def curCommit existing_repo_ref dirname
|
||||
for spec in "${modules[@]}"; do
|
||||
[ -z "$spec" ] && continue
|
||||
|
||||
# Check if module is already installed (by owner/name matching)
|
||||
existing_repo_ref=$(inst_mod_is_installed "$spec" || true)
|
||||
if [ -n "$existing_repo_ref" ]; then
|
||||
echo "[$spec] Already installed as [$existing_repo_ref] (skipping)."
|
||||
continue
|
||||
fi
|
||||
|
||||
parsed_output=$(inst_parse_module_spec "$spec")
|
||||
IFS=' ' read -r repo_ref owner modname override_branch override_commit url dirname <<< "$parsed_output"
|
||||
[ -z "$repo_ref" ] && continue
|
||||
|
||||
# Check for directory conflicts with custom directory names
|
||||
if ! inst_check_module_conflict "$dirname" "$repo_ref"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# override_branch takes precedence; otherwise consult acore-module.json on azerothcore unless repo_ref contains owner or URL
|
||||
if [ -n "$override_branch" ] && [ "$override_branch" != "-" ]; then
|
||||
b="$override_branch"
|
||||
else
|
||||
# For GitHub repositories, use raw.githubusercontent.com to check acore-module.json
|
||||
if [[ "$url" =~ github.com ]] || [[ "$repo_ref" =~ ^[^/]+/[^/]+$ ]]; then
|
||||
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/${owner}/${modname}/master/acore-module.json")
|
||||
else
|
||||
# Unknown host: try the repository URL as-is (may fail)
|
||||
read v b < <(inst_getVersionBranch "${url}/master/acore-module.json")
|
||||
fi
|
||||
if [[ "$v" == "none" || "$v" == "not-defined" || "$b" == "none" ]]; then
|
||||
def="$(inst_get_default_branch "$repo_ref")"
|
||||
echo "Warning: $repo_ref has no compatible acore-module.json; installing from branch '$def' (latest commit)."
|
||||
b="$def"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Use flat directory structure with custom directory name
|
||||
if [ -d "$J_PATH_MODULES/$dirname" ]; then
|
||||
echo "[$repo_ref] Already installed (skipping)."
|
||||
curCommit=$(git -C "$J_PATH_MODULES/$dirname" rev-parse HEAD 2>/dev/null || echo "")
|
||||
inst_mod_list_upsert "$repo_ref" "$b" "$curCommit"
|
||||
continue
|
||||
fi
|
||||
|
||||
if Joiner:add_repo "$url" "$dirname" "$b" ""; then
|
||||
# If a commit was provided, try to checkout it
|
||||
if [ -n "$override_commit" ] && [ "$override_commit" != "-" ]; then
|
||||
git -C "$J_PATH_MODULES/$dirname" fetch --all --quiet || true
|
||||
if git -C "$J_PATH_MODULES/$dirname" rev-parse --verify "$override_commit" >/dev/null 2>&1; then
|
||||
git -C "$J_PATH_MODULES/$dirname" checkout --quiet "$override_commit"
|
||||
else
|
||||
echo "[$repo_ref] Warning: provided commit '$override_commit' not found; staying on branch '$b' HEAD."
|
||||
fi
|
||||
fi
|
||||
curCommit=$(git -C "$J_PATH_MODULES/$dirname" rev-parse HEAD 2>/dev/null || echo "")
|
||||
inst_mod_list_upsert "$repo_ref" "$b" "$curCommit"
|
||||
echo "[$repo_ref] Installed in '$dirname'. Please re-run compiling and db assembly."
|
||||
else
|
||||
echo "[$repo_ref] Install failed or module not found"
|
||||
exit 1;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Update one or more modules
|
||||
function inst_module_update {
|
||||
# Support multiple modules and the --all flag; prompt if none specified.
|
||||
local args=("$@")
|
||||
local use_all=false
|
||||
if [ ${#args[@]} -gt 0 ] && { [ "${args[0]}" = "--all" ] || [ "${args[0]}" = "-a" ]; }; then
|
||||
use_all=true
|
||||
shift || true
|
||||
fi
|
||||
|
||||
local _tmp=$PWD
|
||||
|
||||
if $use_all; then
|
||||
local line repo_ref branch commit newCommit owner modname url dirname
|
||||
while read -r repo_ref branch commit; do
|
||||
[ -z "$repo_ref" ] && continue
|
||||
parsed_output=$(inst_parse_module_spec "$repo_ref")
|
||||
IFS=' ' read -r _ owner modname _ _ url dirname <<< "$parsed_output"
|
||||
|
||||
dirname="${dirname:-$modname}"
|
||||
if [ ! -d "$J_PATH_MODULES/$dirname/" ]; then
|
||||
echo "[$repo_ref] Not installed locally, skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
if Joiner:upd_repo "$url" "$dirname" "$branch" ""; then
|
||||
newCommit=$(git -C "$J_PATH_MODULES/$dirname" rev-parse HEAD 2>/dev/null || echo "")
|
||||
inst_mod_list_upsert "$repo_ref" "$branch" "$newCommit"
|
||||
echo "[$repo_ref] Updated to latest commit on '$branch'."
|
||||
else
|
||||
echo "[$repo_ref] Cannot update"
|
||||
fi
|
||||
done < <(inst_mod_list_read)
|
||||
else
|
||||
local modules=("$@")
|
||||
if [ ${#modules[@]} -eq 0 ]; then
|
||||
echo "Type the name(s) of the module(s) to update"
|
||||
read -p "Insert name(s): " _line
|
||||
read -r -a modules <<< "$_line"
|
||||
fi
|
||||
|
||||
local spec repo_ref override_branch override_commit owner modname url dirname v b branch def newCommit
|
||||
for spec in "${modules[@]}"; do
|
||||
[ -z "$spec" ] && continue
|
||||
parsed_output=$(inst_parse_module_spec "$spec")
|
||||
IFS=' ' read -r repo_ref owner modname override_branch override_commit url dirname <<< "$parsed_output"
|
||||
|
||||
dirname="${dirname:-$modname}"
|
||||
if [ -d "$J_PATH_MODULES/$dirname/" ]; then
|
||||
# determine preferred branch if not provided
|
||||
if [ -n "$override_branch" ] && [ "$override_branch" != "-" ]; then
|
||||
b="$override_branch"
|
||||
else
|
||||
# try reading acore-module.json for this repo
|
||||
if [[ "$url" =~ github.com ]]; then
|
||||
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/${owner}/${modname}/master/acore-module.json")
|
||||
else
|
||||
read v b < <(inst_getVersionBranch "${url}/master/acore-module.json")
|
||||
fi
|
||||
if [[ "$v" == "none" || "$v" == "not-defined" || "$b" == "none" ]]; then
|
||||
if branch=$(git -C "$J_PATH_MODULES/$dirname" rev-parse --abbrev-ref HEAD 2>/dev/null); then
|
||||
echo "Warning: $repo_ref has no compatible acore-module.json; updating current branch '$branch'."
|
||||
b="$branch"
|
||||
else
|
||||
def="$(inst_get_default_branch "$repo_ref")"
|
||||
echo "Warning: $repo_ref has no compatible acore-module.json and no git branch detected; updating default branch '$def'."
|
||||
b="$def"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if Joiner:upd_repo "$url" "$dirname" "$b" ""; then
|
||||
newCommit=$(git -C "$J_PATH_MODULES/$dirname" rev-parse HEAD 2>/dev/null || echo "")
|
||||
inst_mod_list_upsert "$repo_ref" "$b" "$newCommit"
|
||||
echo "[$repo_ref] Done, please re-run compiling and db assembly"
|
||||
else
|
||||
echo "[$repo_ref] Cannot update"
|
||||
fi
|
||||
else
|
||||
echo "[$repo_ref] Cannot update! Path doesn't exist ($J_PATH_MODULES/$dirname/)"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Remove one or more modules
|
||||
function inst_module_remove {
|
||||
# Support multiple modules; prompt if none specified.
|
||||
local modules=("$@")
|
||||
if [ ${#modules[@]} -eq 0 ]; then
|
||||
echo "Type the name(s) of the module(s) to remove"
|
||||
read -p "Insert name(s): " _line
|
||||
read -r -a modules <<< "$_line"
|
||||
fi
|
||||
|
||||
local spec repo_ref owner modname url override_branch override_commit dirname
|
||||
for spec in "${modules[@]}"; do
|
||||
[ -z "$spec" ] && continue
|
||||
parsed_output=$(inst_parse_module_spec "$spec")
|
||||
IFS=' ' read -r repo_ref owner modname override_branch override_commit url dirname <<< "$parsed_output"
|
||||
[ -z "$repo_ref" ] && continue
|
||||
|
||||
dirname="${dirname:-$modname}"
|
||||
if Joiner:remove "$dirname" ""; then
|
||||
inst_mod_list_remove "$repo_ref"
|
||||
echo "[$repo_ref] Done, please re-run compiling"
|
||||
else
|
||||
echo "[$repo_ref] Cannot remove"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
}
|
||||
@ -6,22 +6,22 @@ source "$CURRENT_PATH/includes/includes.sh"
|
||||
|
||||
PS3='[Please enter your choice]: '
|
||||
options=(
|
||||
"init (i): First Installation" # 1
|
||||
"install-deps (d): Configure OS dep" # 2
|
||||
"pull (u): Update Repository" # 3
|
||||
"reset (r): Reset & Clean Repository" # 4
|
||||
"compiler (c): Run compiler tool" # 5
|
||||
"module-search (ms): Module Search by keyword" # 6
|
||||
"module-install (mi): Module Install by name" # 7
|
||||
"module-update (mu): Module Update by name" # 8
|
||||
"module-remove: (mr): Module Remove by name" # 9
|
||||
"client-data: (gd): download client data from github repository (beta)" # 10
|
||||
"run-worldserver (rw): execute a simple restarter for worldserver" # 11
|
||||
"run-authserver (ra): execute a simple restarter for authserver" # 12
|
||||
"docker (dr): Run docker tools" # 13
|
||||
"version (v): Show AzerothCore version" # 14
|
||||
"service-manager (sm): Run service manager to run authserver and worldserver in background" # 15
|
||||
"quit: Exit from this menu" # 16
|
||||
"init (i): First Installation"
|
||||
"install-deps (d): Configure OS dep"
|
||||
"pull (u): Update Repository"
|
||||
"reset (r): Reset & Clean Repository"
|
||||
"compiler (c): Run compiler tool"
|
||||
"module (m): Module manager (search/install/update/remove)"
|
||||
"module-install (mi): Module Install by name [DEPRECATED]"
|
||||
"module-update (mu): Module Update by name [DEPRECATED]"
|
||||
"module-remove: (mr): Module Remove by name [DEPRECATED]"
|
||||
"client-data: (gd): download client data from github repository (beta)"
|
||||
"run-worldserver (rw): execute a simple restarter for worldserver"
|
||||
"run-authserver (ra): execute a simple restarter for authserver"
|
||||
"docker (dr): Run docker tools"
|
||||
"version (v): Show AzerothCore version"
|
||||
"service-manager (sm): Run service manager to run authserver and worldserver in background"
|
||||
"quit (q): Exit from this menu"
|
||||
)
|
||||
|
||||
function _switch() {
|
||||
@ -29,56 +29,64 @@ function _switch() {
|
||||
_opt="$2"
|
||||
|
||||
case $_reply in
|
||||
""|"i"|"init"|"1")
|
||||
""|"i"|"init")
|
||||
inst_allInOne
|
||||
;;
|
||||
""|"d"|"install-deps"|"2")
|
||||
""|"d"|"install-deps")
|
||||
inst_configureOS
|
||||
;;
|
||||
""|"u"|"pull"|"3")
|
||||
""|"u"|"pull")
|
||||
inst_updateRepo
|
||||
;;
|
||||
""|"r"|"reset"|"4")
|
||||
""|"r"|"reset")
|
||||
inst_resetRepo
|
||||
;;
|
||||
""|"c"|"compiler"|"5")
|
||||
""|"c"|"compiler")
|
||||
bash "$AC_PATH_APPS/compiler/compiler.sh" $_opt
|
||||
;;
|
||||
""|"ms"|"module-search"|"6")
|
||||
inst_module_search "$_opt"
|
||||
""|"m"|"module")
|
||||
# Unified module command: supports subcommands search|install|update|remove
|
||||
inst_module "${@:2}"
|
||||
;;
|
||||
""|"mi"|"module-install"|"7")
|
||||
inst_module_install "$_opt"
|
||||
""|"ms"|"module-search")
|
||||
echo "[DEPRECATED] Use: ./acore.sh module search <terms...>"
|
||||
inst_module_search "${@:2}"
|
||||
;;
|
||||
""|"mu"|"module-update"|"8")
|
||||
inst_module_update "$_opt"
|
||||
""|"mi"|"module-install")
|
||||
echo "[DEPRECATED] Use: ./acore.sh module install <modules...>"
|
||||
inst_module_install "${@:2}"
|
||||
;;
|
||||
""|"mr"|"module-remove"|"9")
|
||||
inst_module_remove "$_opt"
|
||||
""|"mu"|"module-update")
|
||||
echo "[DEPRECATED] Use: ./acore.sh module update <modules...>"
|
||||
inst_module_update "${@:2}"
|
||||
;;
|
||||
""|"gd"|"client-data"|"10")
|
||||
""|"mr"|"module-remove")
|
||||
echo "[DEPRECATED] Use: ./acore.sh module remove <modules...>"
|
||||
inst_module_remove "${@:2}"
|
||||
;;
|
||||
""|"gd"|"client-data")
|
||||
inst_download_client_data
|
||||
;;
|
||||
""|"rw"|"run-worldserver"|"11")
|
||||
""|"rw"|"run-worldserver")
|
||||
inst_simple_restarter worldserver
|
||||
;;
|
||||
""|"ra"|"run-authserver"|"12")
|
||||
""|"ra"|"run-authserver")
|
||||
inst_simple_restarter authserver
|
||||
;;
|
||||
""|"dr"|"docker"|"13")
|
||||
""|"dr"|"docker")
|
||||
DOCKER=1 bash "$AC_PATH_ROOT/apps/docker/docker-cmd.sh" "${@:2}"
|
||||
exit
|
||||
;;
|
||||
""|"v"|"version"|"14")
|
||||
""|"v"|"version")
|
||||
# denoRunFile "$AC_PATH_APPS/installer/main.ts" "version"
|
||||
printf "AzerothCore Rev. %s\n" "$ACORE_VERSION"
|
||||
exit
|
||||
;;
|
||||
""|"sm"|"service-manager"|"15")
|
||||
""|"sm"|"service-manager")
|
||||
bash "$AC_PATH_APPS/startup-scripts/src/service-manager.sh" "${@:2}"
|
||||
exit
|
||||
;;
|
||||
""|"quit"|"16")
|
||||
""|"q"|"quit")
|
||||
echo "Goodbye!"
|
||||
exit
|
||||
;;
|
||||
@ -102,4 +110,5 @@ do
|
||||
_switch $REPLY
|
||||
break
|
||||
done
|
||||
echo "opt: $opt"
|
||||
done
|
||||
|
||||
14
apps/installer/test/bats.conf
Normal file
14
apps/installer/test/bats.conf
Normal file
@ -0,0 +1,14 @@
|
||||
# BATS Test Configuration
|
||||
|
||||
# Set test timeout (in seconds)
|
||||
export BATS_TEST_TIMEOUT=30
|
||||
|
||||
# Enable verbose output for debugging
|
||||
export BATS_VERBOSE_RUN=1
|
||||
|
||||
# Test output format
|
||||
export BATS_FORMATTER=pretty
|
||||
|
||||
# Enable colored output
|
||||
export BATS_NO_PARALLELIZE_ACROSS_FILES=1
|
||||
export BATS_NO_PARALLELIZE_WITHIN_FILE=1
|
||||
354
apps/installer/test/test_module_commands.bats
Executable file
354
apps/installer/test/test_module_commands.bats
Executable file
@ -0,0 +1,354 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
# Tests for installer module commands (search/install/update/remove)
|
||||
# Focused on installer:module install behavior using a mocked joiner
|
||||
|
||||
load '../../test-framework/bats_libs/acore-support'
|
||||
load '../../test-framework/bats_libs/acore-assert'
|
||||
|
||||
setup() {
|
||||
acore_test_setup
|
||||
# Point to the installer src directory (not needed in this test)
|
||||
|
||||
# Set installer/paths environment for the test
|
||||
export AC_PATH_APPS="$TEST_DIR/apps"
|
||||
export AC_PATH_ROOT="$TEST_DIR"
|
||||
export AC_PATH_DEPS="$TEST_DIR/deps"
|
||||
export AC_PATH_MODULES="$TEST_DIR/modules"
|
||||
export MODULES_LIST_FILE="$TEST_DIR/conf/modules.list"
|
||||
|
||||
# Create stubbed deps: joiner.sh (sourced by includes) and semver
|
||||
mkdir -p "$TEST_DIR/deps/acore/joiner"
|
||||
cat > "$TEST_DIR/deps/acore/joiner/joiner.sh" << 'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# Stub joiner functions used by installer
|
||||
Joiner:add_repo() {
|
||||
# arguments: url name branch basedir
|
||||
echo "ADD $@" > "$TEST_DIR/joiner_called.txt"
|
||||
return 0
|
||||
}
|
||||
Joiner:upd_repo() {
|
||||
echo "UPD $@" > "$TEST_DIR/joiner_called.txt"
|
||||
return 0
|
||||
}
|
||||
Joiner:remove() {
|
||||
echo "REM $@" > "$TEST_DIR/joiner_called.txt"
|
||||
return 0
|
||||
}
|
||||
EOF
|
||||
chmod +x "$TEST_DIR/deps/acore/joiner/joiner.sh"
|
||||
|
||||
mkdir -p "$TEST_DIR/deps/semver_bash"
|
||||
# Minimal semver stub
|
||||
cat > "$TEST_DIR/deps/semver_bash/semver.sh" << 'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# semver stub
|
||||
semver::satisfies() { return 0; }
|
||||
EOF
|
||||
chmod +x "$TEST_DIR/deps/semver_bash/semver.sh"
|
||||
|
||||
# Provide a minimal compiler includes file expected by installer
|
||||
mkdir -p "$TEST_DIR/apps/compiler/includes"
|
||||
touch "$TEST_DIR/apps/compiler/includes/includes.sh"
|
||||
|
||||
# Provide minimal bash_shared includes to satisfy installer include
|
||||
mkdir -p "$TEST_DIR/apps/bash_shared"
|
||||
cat > "$TEST_DIR/apps/bash_shared/includes.sh" << 'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# minimal stub
|
||||
EOF
|
||||
|
||||
# Copy the real installer app into the test apps dir
|
||||
mkdir -p "$TEST_DIR/apps"
|
||||
cp -r "$(cd "$AC_TEST_ROOT/apps/installer" && pwd)" "$TEST_DIR/apps/installer"
|
||||
}
|
||||
|
||||
teardown() {
|
||||
acore_test_teardown
|
||||
}
|
||||
|
||||
@test "module install should call joiner and record entry in modules list" {
|
||||
cd "$TEST_DIR"
|
||||
|
||||
# Source installer includes and call the install function directly to avoid menu interaction
|
||||
run bash -c "source '$TEST_DIR/apps/installer/includes/includes.sh' && inst_module_install example-module@main:abcd1234"
|
||||
|
||||
# Check that joiner was called
|
||||
[ -f "$TEST_DIR/joiner_called.txt" ]
|
||||
grep -q "ADD" "$TEST_DIR/joiner_called.txt"
|
||||
|
||||
# Check modules list was created and contains the repo_ref and branch
|
||||
[ -f "$TEST_DIR/conf/modules.list" ]
|
||||
grep -q "azerothcore/example-module main" "$TEST_DIR/conf/modules.list"
|
||||
}
|
||||
|
||||
@test "module install with owner/name format should work" {
|
||||
cd "$TEST_DIR"
|
||||
|
||||
# Test with owner/name format
|
||||
run bash -c "source '$TEST_DIR/apps/installer/includes/includes.sh' && inst_module_install myorg/mymodule"
|
||||
|
||||
# Check that joiner was called with correct URL
|
||||
[ -f "$TEST_DIR/joiner_called.txt" ]
|
||||
grep -q "ADD https://github.com/myorg/mymodule mymodule" "$TEST_DIR/joiner_called.txt"
|
||||
|
||||
# Check modules list contains the entry
|
||||
[ -f "$TEST_DIR/conf/modules.list" ]
|
||||
grep -q "myorg/mymodule" "$TEST_DIR/conf/modules.list"
|
||||
}
|
||||
|
||||
@test "module remove should call joiner remove and update modules list" {
|
||||
cd "$TEST_DIR"
|
||||
|
||||
# First install a module
|
||||
bash -c "source '$TEST_DIR/apps/installer/includes/includes.sh' && inst_module_install test-module"
|
||||
|
||||
# Then remove it
|
||||
run bash -c "source '$TEST_DIR/apps/installer/includes/includes.sh' && inst_module_remove test-module"
|
||||
|
||||
# Check that joiner remove was called
|
||||
[ -f "$TEST_DIR/joiner_called.txt" ]
|
||||
# With flat structure, basedir is empty; ensure name is present
|
||||
grep -q "REM test-module" "$TEST_DIR/joiner_called.txt"
|
||||
|
||||
# Check modules list no longer contains the entry
|
||||
[ -f "$TEST_DIR/conf/modules.list" ]
|
||||
! grep -q "azerothcore/test-module" "$TEST_DIR/conf/modules.list"
|
||||
}
|
||||
|
||||
# Tests for intelligent module management (duplicate prevention and cross-format removal)
|
||||
|
||||
@test "inst_extract_owner_name should extract owner/name from various formats" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Test simple name
|
||||
run inst_extract_owner_name "mod-transmog"
|
||||
[ "$output" = "azerothcore/mod-transmog" ]
|
||||
|
||||
# Test owner/name format
|
||||
run inst_extract_owner_name "azerothcore/mod-transmog"
|
||||
[ "$output" = "azerothcore/mod-transmog" ]
|
||||
|
||||
# Test HTTPS URL
|
||||
run inst_extract_owner_name "https://github.com/azerothcore/mod-transmog.git"
|
||||
[ "$output" = "azerothcore/mod-transmog" ]
|
||||
|
||||
# Test SSH URL
|
||||
run inst_extract_owner_name "git@github.com:azerothcore/mod-transmog.git"
|
||||
[ "$output" = "azerothcore/mod-transmog" ]
|
||||
|
||||
# Test GitLab URL
|
||||
run inst_extract_owner_name "https://gitlab.com/myorg/mymodule.git"
|
||||
[ "$output" = "myorg/mymodule" ]
|
||||
}
|
||||
|
||||
@test "duplicate module entries should be prevented across different formats" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Add module via simple name
|
||||
inst_mod_list_upsert "mod-transmog" "master" "abc123"
|
||||
|
||||
# Verify it's in the list
|
||||
grep -q "mod-transmog master abc123" "$TEST_DIR/conf/modules.list"
|
||||
|
||||
# Add same module via owner/name format - should replace, not duplicate
|
||||
inst_mod_list_upsert "azerothcore/mod-transmog" "dev" "def456"
|
||||
|
||||
# Should only have one entry (the new one)
|
||||
[ "$(grep -c "azerothcore/mod-transmog" "$TEST_DIR/conf/modules.list")" -eq 1 ]
|
||||
grep -q "azerothcore/mod-transmog dev def456" "$TEST_DIR/conf/modules.list"
|
||||
! grep -q "mod-transmog master abc123" "$TEST_DIR/conf/modules.list"
|
||||
}
|
||||
|
||||
@test "module installed via URL should be recognized when checking with different formats" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Install via HTTPS URL
|
||||
inst_mod_list_upsert "https://github.com/azerothcore/mod-transmog.git" "master" "abc123"
|
||||
|
||||
# Should be detected as installed using simple name
|
||||
run inst_mod_is_installed "mod-transmog"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Should be detected as installed using owner/name
|
||||
run inst_mod_is_installed "azerothcore/mod-transmog"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Should be detected as installed using SSH URL
|
||||
run inst_mod_is_installed "git@github.com:azerothcore/mod-transmog.git"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Non-existent module should not be detected
|
||||
run inst_mod_is_installed "mod-nonexistent"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "cross-format module removal should work" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Install via SSH URL
|
||||
inst_mod_list_upsert "git@github.com:azerothcore/mod-transmog.git" "master" "abc123"
|
||||
|
||||
# Verify it's installed
|
||||
grep -q "git@github.com:azerothcore/mod-transmog.git" "$TEST_DIR/conf/modules.list"
|
||||
|
||||
# Remove using simple name
|
||||
inst_mod_list_remove "mod-transmog"
|
||||
|
||||
# Should be completely removed
|
||||
! grep -q "azerothcore/mod-transmog" "$TEST_DIR/conf/modules.list"
|
||||
! grep -q "git@github.com:azerothcore/mod-transmog.git" "$TEST_DIR/conf/modules.list"
|
||||
}
|
||||
|
||||
@test "module installation should prevent duplicates when already installed" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Install via simple name first
|
||||
inst_mod_list_upsert "mod-worldchat" "master" "abc123"
|
||||
|
||||
# Try to install same module via URL - should detect it's already installed
|
||||
run inst_mod_is_installed "https://github.com/azerothcore/mod-worldchat.git"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
# Add via URL should replace the existing entry
|
||||
inst_mod_list_upsert "https://github.com/azerothcore/mod-worldchat.git" "dev" "def456"
|
||||
|
||||
# Should only have one entry
|
||||
[ "$(grep -c "azerothcore/mod-worldchat" "$TEST_DIR/conf/modules.list")" -eq 1 ]
|
||||
grep -q "https://github.com/azerothcore/mod-worldchat.git dev def456" "$TEST_DIR/conf/modules.list"
|
||||
}
|
||||
|
||||
@test "module update --all uses flat structure (no branch subfolders)" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Prepare modules.list with one entry and a matching local directory
|
||||
mkdir -p "$TEST_DIR/conf"
|
||||
echo "azerothcore/mod-transmog master abc123" > "$TEST_DIR/conf/modules.list"
|
||||
mkdir -p "$TEST_DIR/modules/mod-transmog"
|
||||
|
||||
# Run update all
|
||||
run bash -c "source '$TEST_DIR/apps/installer/includes/includes.sh' && inst_module_update --all"
|
||||
|
||||
# Verify Joiner:upd_repo received flat structure args (no basedir)
|
||||
[ -f "$TEST_DIR/joiner_called.txt" ]
|
||||
grep -q "UPD https://github.com/azerothcore/mod-transmog mod-transmog master" "$TEST_DIR/joiner_called.txt"
|
||||
}
|
||||
|
||||
@test "module update specific uses flat structure with override branch" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Create local directory so update proceeds
|
||||
mkdir -p "$TEST_DIR/modules/mymodule"
|
||||
|
||||
# Run update specifying owner/name and branch
|
||||
run bash -c "source '$TEST_DIR/apps/installer/includes/includes.sh' && inst_module_update myorg/mymodule@dev"
|
||||
|
||||
# Should call joiner with name 'mymodule' and branch 'dev' (no basedir)
|
||||
[ -f "$TEST_DIR/joiner_called.txt" ]
|
||||
grep -q "UPD https://github.com/myorg/mymodule mymodule dev" "$TEST_DIR/joiner_called.txt"
|
||||
}
|
||||
|
||||
@test "custom directory names should work with new syntax" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Test parsing with custom directory name
|
||||
run inst_parse_module_spec "mod-transmog:my-custom-dir@develop:abc123"
|
||||
[ "$status" -eq 0 ]
|
||||
# Should output: repo_ref owner name branch commit url dirname
|
||||
IFS=' ' read -r repo_ref owner name branch commit url dirname <<< "$output"
|
||||
[ "$repo_ref" = "azerothcore/mod-transmog" ]
|
||||
[ "$owner" = "azerothcore" ]
|
||||
[ "$name" = "mod-transmog" ]
|
||||
[ "$branch" = "develop" ]
|
||||
[ "$commit" = "abc123" ]
|
||||
[ "$url" = "https://github.com/azerothcore/mod-transmog" ]
|
||||
[ "$dirname" = "my-custom-dir" ]
|
||||
}
|
||||
|
||||
@test "directory conflict detection should work" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Create a fake existing directory
|
||||
mkdir -p "$TEST_DIR/modules/existing-dir"
|
||||
|
||||
# Should detect conflict
|
||||
run inst_check_module_conflict "existing-dir" "mod-test"
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" =~ "Directory 'existing-dir' already exists" ]]
|
||||
[[ "$output" =~ "Use a different directory name: mod-test:my-custom-name" ]]
|
||||
|
||||
# Should not detect conflict for non-existing directory
|
||||
run inst_check_module_conflict "non-existing-dir" "mod-test"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "module update should work with custom directories" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# First add module with custom directory to list
|
||||
inst_mod_list_upsert "azerothcore/mod-transmog:custom-dir" "master" "abc123"
|
||||
|
||||
# Create fake module directory structure
|
||||
mkdir -p "$TEST_DIR/modules/custom-dir/.git"
|
||||
echo "ref: refs/heads/master" > "$TEST_DIR/modules/custom-dir/.git/HEAD"
|
||||
|
||||
# Mock git commands in the fake module directory
|
||||
cat > "$TEST_DIR/modules/custom-dir/.git/config" << 'EOF'
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
[remote "origin"]
|
||||
url = https://github.com/azerothcore/mod-transmog
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[branch "master"]
|
||||
remote = origin
|
||||
merge = refs/heads/master
|
||||
EOF
|
||||
|
||||
# Test update with custom directory should work
|
||||
# Note: This would require more complex mocking for full integration test
|
||||
# For now, just test the parsing recognizes the custom directory
|
||||
run inst_parse_module_spec "azerothcore/mod-transmog:custom-dir"
|
||||
[ "$status" -eq 0 ]
|
||||
IFS=' ' read -r repo_ref owner name branch commit url dirname <<< "$output"
|
||||
[ "$dirname" = "custom-dir" ]
|
||||
}
|
||||
|
||||
@test "URL formats should be properly normalized" {
|
||||
cd "$TEST_DIR"
|
||||
source "$TEST_DIR/apps/installer/includes/includes.sh"
|
||||
|
||||
# Test various URL formats produce same owner/name
|
||||
run inst_extract_owner_name "https://github.com/azerothcore/mod-transmog"
|
||||
local url_format="$output"
|
||||
|
||||
run inst_extract_owner_name "https://github.com/azerothcore/mod-transmog.git"
|
||||
local url_git_format="$output"
|
||||
|
||||
run inst_extract_owner_name "git@github.com:azerothcore/mod-transmog.git"
|
||||
local ssh_format="$output"
|
||||
|
||||
run inst_extract_owner_name "azerothcore/mod-transmog"
|
||||
local owner_name_format="$output"
|
||||
|
||||
run inst_extract_owner_name "mod-transmog"
|
||||
local simple_format="$output"
|
||||
|
||||
# All should normalize to the same owner/name
|
||||
[ "$url_format" = "azerothcore/mod-transmog" ]
|
||||
[ "$url_git_format" = "azerothcore/mod-transmog" ]
|
||||
[ "$ssh_format" = "azerothcore/mod-transmog" ]
|
||||
[ "$owner_name_format" = "azerothcore/mod-transmog" ]
|
||||
[ "$simple_format" = "azerothcore/mod-transmog" ]
|
||||
}
|
||||
13
conf/dist/config.sh
vendored
13
conf/dist/config.sh
vendored
@ -149,4 +149,17 @@ export CPUPROFILESIGNAL=${CPUPROFILESIGNAL:-12}
|
||||
# Other values for HEAPCHECK: minimal, normal (equivalent to "1"), strict, draconian
|
||||
#export HEAPCHECK=${HEAPCHECK:-normal}
|
||||
|
||||
##############################################
|
||||
#
|
||||
# MODULES LIST FILE (for installer `module` commands)
|
||||
#
|
||||
# Path to the file where the installer records installed modules
|
||||
# with their branch and commit. You can override this path by
|
||||
# setting the MODULES_LIST_FILE inside your config.sh or as an environment variable.
|
||||
# By default it points inside the repository conf folder.
|
||||
# Format of each line:
|
||||
# <module-name> <branch> <commit>
|
||||
# Lines starting with '#' and empty lines are ignored.
|
||||
export MODULES_LIST_FILE=${MODULES_LIST_FILE:-"$AC_PATH_ROOT/conf/modules.list"}
|
||||
|
||||
|
||||
|
||||
36
deps/acore/joiner/joiner.sh
vendored
36
deps/acore/joiner/joiner.sh
vendored
@ -94,11 +94,11 @@ function Joiner:add_repo() (
|
||||
basedir="${4:-""}"
|
||||
|
||||
[[ -z $url ]] && hasReq=false || hasReq=true
|
||||
Joiner:_help $hasReq "$1" "Syntax: joiner.sh add-repo [-d] [-e] url name branch [basedir]"
|
||||
Joiner:_help "$hasReq" "$1" "Syntax: joiner.sh add-repo [-d] [-e] url name branch [basedir]"
|
||||
|
||||
# retrieving info from url if not set
|
||||
if [[ -z $name ]]; then
|
||||
basename=$(basename $url)
|
||||
basename=$(basename "$url")
|
||||
name=${basename%%.*}
|
||||
|
||||
if [[ -z "$basedir" ]]; then
|
||||
@ -115,10 +115,12 @@ function Joiner:add_repo() (
|
||||
|
||||
if [ -e "$path/.git/" ]; then
|
||||
# if exists , update
|
||||
git --git-dir="$path/.git/" rev-parse && git --git-dir="$path/.git/" pull origin $branch | grep 'Already up-to-date.' && changed="no" || true
|
||||
echo "Updating $name on branch $branch..."
|
||||
git --git-dir="$path/.git/" --work-tree="$path" rev-parse && git --git-dir="$path/.git/" --work-tree="$path" pull origin "$branch" | grep 'Already up-to-date.' && changed="no" || true
|
||||
else
|
||||
# otherwise clone
|
||||
git clone $url -c advice.detachedHead=0 -b $branch "$path"
|
||||
echo "Cloning $name on branch $branch..."
|
||||
git clone "$url" -c advice.detachedHead=0 -b "$branch" "$path"
|
||||
fi
|
||||
|
||||
if [ "$?" -ne "0" ]; then
|
||||
@ -140,16 +142,16 @@ function Joiner:add_git_submodule() (
|
||||
basedir=${4:-""}
|
||||
|
||||
[[ -z $url ]] && hasReq=false || hasReq=true
|
||||
Joiner:_help $hasReq "$1" "Syntax: joiner.sh add-git-submodule [-d] [-e] url name branch [basedir]"
|
||||
Joiner:_help "$hasReq" "$1" "Syntax: joiner.sh add-git-submodule [-d] [-e] url name branch [basedir]"
|
||||
|
||||
# retrieving info from url if not set
|
||||
if [[ -z $name ]]; then
|
||||
basename=$(basename $url)
|
||||
basename=$(basename "$url")
|
||||
name=${basename%%.*}
|
||||
|
||||
if [[ -z $basedir ]]; then
|
||||
dir=$(dirname $url)
|
||||
basedir=$(basename $dir)
|
||||
dir=$(dirname "$url")
|
||||
basedir=$(basename "$dir")
|
||||
fi
|
||||
|
||||
name="${name,,}" #to lowercase
|
||||
@ -158,17 +160,17 @@ function Joiner:add_git_submodule() (
|
||||
|
||||
path="$J_PATH_MODULES/$basedir/$name"
|
||||
valid_path=`Joiner:_searchFirstValiPath "$path"`
|
||||
rel_path=${path#$valid_path}
|
||||
rel_path=${path#"$valid_path"}
|
||||
rel_path=${rel_path#/}
|
||||
|
||||
if [ -e $path/ ]; then
|
||||
if [ -e "$path/" ]; then
|
||||
# if exists , update
|
||||
(cd "$path" && git pull origin $branch)
|
||||
(cd "$valid_path" && git submodule update -f --init $rel_path)
|
||||
(cd "$path" && git pull origin "$branch")
|
||||
(cd "$valid_path" && git submodule update -f --init "$rel_path")
|
||||
else
|
||||
# otherwise add
|
||||
(cd "$valid_path" && git submodule add -f -b $branch $url $rel_path)
|
||||
(cd "$valid_path" && git submodule update -f --init $rel_path)
|
||||
(cd "$valid_path" && git submodule add -f -b "$branch" "$url" "$rel_path")
|
||||
(cd "$valid_path" && git submodule update -f --init "$rel_path")
|
||||
fi
|
||||
|
||||
if [ "$?" -ne "0" ]; then
|
||||
@ -324,7 +326,7 @@ function Joiner:self_update() {
|
||||
if [ ! -z "$J_VER_REQ" ]; then
|
||||
# if J_VER_REQ is defined then update only if tag is different
|
||||
_cur_branch=`git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" rev-parse --abbrev-ref HEAD`
|
||||
_cur_ver=`git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" name-rev --tags --name-only $_cur_branch`
|
||||
_cur_ver=`git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" name-rev --tags --name-only "$_cur_branch"`
|
||||
if [ "$_cur_ver" != "$J_VER_REQ" ]; then
|
||||
git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" rev-parse && git --git-dir="$J_PATH/.git/" fetch --tags origin "$_cur_branch" --quiet
|
||||
git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" checkout "tags/$J_VER_REQ" -b "$_cur_branch"
|
||||
@ -416,8 +418,8 @@ function Joiner:menu() {
|
||||
while true
|
||||
do
|
||||
# run option directly if specified in argument
|
||||
[ ! -z $1 ] && _switch $@
|
||||
[ ! -z $1 ] && exit 0
|
||||
[ ! -z "$1" ] && _switch $@
|
||||
[ ! -z "$1" ] && exit 0
|
||||
|
||||
echo ""
|
||||
echo "==== JOINER MENU ===="
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user