refactor: rewrite updater to v8.0 — faster, stabler, more features
Local Build and Deploy / deploy (push) Successful in 1m28s
Local Build and Deploy / deploy (push) Successful in 1m28s
Faster: - Parallel Maven builds (-T 1C, skip tests) - yarn install with --prefer-offline - Renderer + client installs run in parallel via parallel_run() - Skip building if no upstream changes - Dev mode (--only=dev) skips all builds, just syncs configs Stabler: - Flock-based lockfile prevents concurrent runs - Preflight check function with fatal error handling - Config backup before overwriting (rollback on crash) - JSON config validation after syncing - Disk space warning at 50% threshold - Better Maven error logging (last 20 lines) - Redis flush after config sync (immediate effect) - Automatic cleanup of old config backups (keep 10) New features: - Dev mode (menu option 19) — skip builds, configs + restart only - Git stash viewer (menu option 20 / stash command) - Emulator journal viewer (service menu option 8) - Docker system prune (clean menu option 6) - Maven artifact cleanup (clean menu option 7) - DB processlist viewer (database menu option 7) - Git ahead/behind indicators in status dashboard - Program renamed to SMaRT v8.0.0
This commit is contained in:
1 parent
df604bf432
commit
aea9d83865
1 file changed
+241
-74
+241
-74
@@ -2,27 +2,19 @@
|
||||
set -Eeo pipefail
|
||||
|
||||
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ███████╗███╗ ███╗ █████╗ ██████╗ ████████╗ ║
|
||||
# ║ ██╔════╝████╗ ████║██╔══██╗██╔══██╗╚══██╔══╝ ║
|
||||
# ║ █████╗ ██╔████╔██║███████║██████╔╝ ██║ ║
|
||||
# ║ ██╔══╝ ██║╚██╔╝██║██╔══██║██╔══██╗ ██║ ║
|
||||
# ║ ███████╗██║ ╚═╝ ██║██║ ██║██║ ██║ ██║ ║
|
||||
# ║ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ║
|
||||
# ║ ║
|
||||
# ║ Emulator / Nitro-V3 / Nitro-V3-Render ║
|
||||
# ║ Updater by Remco — epicnabbo.nl ║
|
||||
# ║ ║
|
||||
# ║ SMaRT — Emulator / Nitro-V3 / Nitro-V3-Render ║
|
||||
# ║ Updater & Manager by Remco ║
|
||||
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
# =============================================================================
|
||||
# CONSTANTS
|
||||
# =============================================================================
|
||||
readonly SCRIPT_VERSION="7.0.0"
|
||||
readonly SCRIPT_BUILD="20260625"
|
||||
readonly SCRIPT_VERSION="8.0.0"
|
||||
readonly SCRIPT_BUILD="20260720"
|
||||
readonly SCRIPT_NAME="$(basename "$0")"
|
||||
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
readonly START_TIME=$(date +%s)
|
||||
readonly LOCK_FILE="/tmp/${SCRIPT_NAME%.sh}.lock"
|
||||
|
||||
# =============================================================================
|
||||
# COLORS
|
||||
@@ -48,13 +40,13 @@ if locale charmap 2>/dev/null | grep -qi utf; then
|
||||
E_GEAR="⚙" E_ROCKET="🚀" E_SHIELD="🛡" E_DB="🗄" E_GIT="🔀"
|
||||
E_WRENCH="🔧" E_CHART="📊" E_BOLT="⚡" E_BROOM="🧹" E_EYE="👁"
|
||||
E_LOCK="🔒" E_HEART="♥" E_CLOUD="☁" E_FIRE="🔥" E_GLOBE="🌐"
|
||||
E_CONSOLE="🖥" E_CLOCK="⏱"
|
||||
E_CONSOLE="🖥" E_CLOCK="⏱" E_DOCKER="🐳" E_CHECK="🔍"
|
||||
else
|
||||
E_OK="[OK]" E_FAIL="[!]" E_WARN="[!]" E_ARROW="->" E_DOT="*"
|
||||
E_GEAR="[G]" E_ROCKET="[R]" E_SHIELD="[S]" E_DB="[DB]" E_GIT="[G]"
|
||||
E_WRENCH="[W]" E_CHART="[C]" E_BOLT="[!]" E_BROOM="[C]" E_EYE="[E]"
|
||||
E_LOCK="[L]" E_HEART="[H]" E_CLOUD="[C]" E_FIRE="[F]" E_GLOBE="[W]"
|
||||
E_CONSOLE="[M]" E_CLOCK="[T]"
|
||||
E_CONSOLE="[M]" E_CLOCK="[T]" E_DOCKER="[D]" E_CHECK="[C]"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
@@ -70,13 +62,14 @@ UPDATED_REPOS=()
|
||||
LAST_BACKUP=""
|
||||
ROLLBACK_NEEDED=false
|
||||
NOTIFY_FAILED=false
|
||||
CONFIG_BACKUP_DIR=""
|
||||
MAVEN_OPTS="${MAVEN_OPTS:--Xmx2G}"
|
||||
|
||||
# =============================================================================
|
||||
# LOAD .ENV
|
||||
# =============================================================================
|
||||
if [ -f "$SCRIPT_DIR/.env" ]; then set -a; . "$SCRIPT_DIR/.env"; set +a; fi
|
||||
|
||||
# Parse DATABASE_URL as fallback for DB credentials (Next.js / Prisma style)
|
||||
if [ -z "${NITRO_DB_NAME:-}" ] && [ -n "${DATABASE_URL:-}" ]; then
|
||||
eval "$(
|
||||
python3 -c "
|
||||
@@ -122,6 +115,9 @@ MIN_DISK_GB="${NITRO_MIN_DISK_GB:-5}"
|
||||
HEALTH_RETRIES="${NITRO_HEALTH_RETRIES:-12}"
|
||||
HEALTH_INTERVAL="${NITRO_HEALTH_INTERVAL:-5}"
|
||||
NITRO_SSL_VERIFY="${NITRO_SSL_VERIFY:-OFF}"
|
||||
CONFIG_BACKUP_DIR="${SCRIPT_DIR}/storage/config-backups"
|
||||
mkdir -p "$CONFIG_BACKUP_DIR" 2>/dev/null || true
|
||||
|
||||
MYSQL_CRED="-h $DB_HOST -P $DB_PORT -u $DB_USER --ssl-verify-server-cert=${NITRO_SSL_VERIFY}"
|
||||
[ -n "$DB_PASS" ] && MYSQL_CRED="$MYSQL_CRED --password=$DB_PASS"
|
||||
|
||||
@@ -133,6 +129,21 @@ else
|
||||
MYSQL_CLIENT="mariadb"; MYSQL_DUMP="mariadb-dump"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# LOCKFILE
|
||||
# =============================================================================
|
||||
acquire_lock() {
|
||||
exec 9>"$LOCK_FILE"
|
||||
if ! flock -n 9; then
|
||||
die "Another instance is already running (lock: $LOCK_FILE)"
|
||||
fi
|
||||
}
|
||||
|
||||
release_lock() {
|
||||
flock -u 9 2>/dev/null || true
|
||||
rm -f "$LOCK_FILE" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# UI HELPERS
|
||||
# =============================================================================
|
||||
@@ -147,6 +158,7 @@ die() {
|
||||
echo -e " ${C_BG_RED}${C_WHITE}${C_BOLD} ERROR ${C_RESET} ${C_RED}$1${C_RESET}"
|
||||
log_write "FATAL" "$1"
|
||||
cleanup_notify_failure "$1"
|
||||
release_lock
|
||||
cursor_show
|
||||
exit 1
|
||||
}
|
||||
@@ -156,6 +168,7 @@ cursor_show() { tput cnorm 2>/dev/null || true; }
|
||||
clear_line() { printf "\r\033[K"; }
|
||||
repeat() { local ch="${1:-=}" n="${2:-1}"; printf '%*s' "$n" '' | tr ' ' "$ch"; }
|
||||
list_sorted() { local d="$1" p="$2" m="${3:-20}"; find "$d" -name "$p" -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -n "$m" | sed 's/^[0-9.]* //'; }
|
||||
|
||||
service_active() {
|
||||
local svc="$1"
|
||||
if command -v systemctl &>/dev/null; then
|
||||
@@ -166,6 +179,7 @@ service_active() {
|
||||
pgrep -x "$svc" &>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
format_size() {
|
||||
local bytes="${1:-0}"
|
||||
if command -v numfmt &>/dev/null; then
|
||||
@@ -277,15 +291,19 @@ print(json.dumps(payload))
|
||||
cleanup_notify_failure() { $NOTIFY_FAILED && return; NOTIFY_FAILED=true; notify "FAILED" "$1"; }
|
||||
|
||||
cleanup_on_exit() {
|
||||
local ec=$?; cursor_show
|
||||
local ec=$?; cursor_show; release_lock
|
||||
if [ $ec -ne 0 ] && [ "$ROLLBACK_NEEDED" = true ]; then
|
||||
echo -e "\n ${C_BG_RED}${C_WHITE}${C_BOLD} ROLLBACK ${C_RESET}"
|
||||
:
|
||||
echo -e " Restoring config back-ups from $CONFIG_BACKUP_DIR/rollback..."
|
||||
if [ -d "$CONFIG_BACKUP_DIR/rollback" ]; then
|
||||
cp -r "$CONFIG_BACKUP_DIR/rollback/"* "$NITRO_SRC_DIR/" 2>/dev/null || true
|
||||
ok "Config files restored from rollback"
|
||||
fi
|
||||
fi
|
||||
[ $ec -ne 0 ] && cleanup_notify_failure "Exit code $ec"
|
||||
}
|
||||
trap cleanup_on_exit EXIT
|
||||
trap 'cursor_show; exit 1' SIGINT SIGTERM
|
||||
trap 'release_lock; cursor_show; exit 1' SIGINT SIGTERM
|
||||
|
||||
# =============================================================================
|
||||
# GIT HELPERS
|
||||
@@ -341,6 +359,101 @@ clean_node_modules() {
|
||||
rm -rf "node_modules" 2>/dev/null || sudo rm -rf "$(pwd)/node_modules" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# PARALLEL HELPERS
|
||||
# =============================================================================
|
||||
PARALLEL_PIDS=()
|
||||
|
||||
parallel_run() {
|
||||
local name="$1"; shift
|
||||
(
|
||||
if "$@" 2>&1; then
|
||||
echo "__PARALLEL_OK__${name}"
|
||||
else
|
||||
echo "__PARALLEL_FAIL__${name}"
|
||||
fi
|
||||
) &
|
||||
PARALLEL_PIDS+=($!)
|
||||
}
|
||||
|
||||
parallel_wait() {
|
||||
local failed=()
|
||||
for pid in "${PARALLEL_PIDS[@]}"; do
|
||||
wait "$pid" 2>/dev/null || true
|
||||
done
|
||||
PARALLEL_PIDS=()
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# CONFIG BACKUP & VALIDATION
|
||||
# =============================================================================
|
||||
backup_configs() {
|
||||
local ts=$(date +%Y%m%d-%H%M%S)
|
||||
local bdir="$CONFIG_BACKUP_DIR/$ts"
|
||||
mkdir -p "$bdir"
|
||||
if [ -d "$NITRO_SRC_DIR" ]; then
|
||||
cp -r "$NITRO_SRC_DIR"/*.json "$bdir/" 2>/dev/null || true
|
||||
fi
|
||||
# Keep a rolling 'rollback' pointer
|
||||
rm -rf "$CONFIG_BACKUP_DIR/rollback"
|
||||
cp -r "$bdir" "$CONFIG_BACKUP_DIR/rollback" 2>/dev/null || true
|
||||
echo "$bdir"
|
||||
}
|
||||
|
||||
validate_json() {
|
||||
local file="$1"
|
||||
if ! python3 -m json.tool "$file" >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
validate_configs() {
|
||||
local dir="$1"
|
||||
local errors=0
|
||||
for f in "$dir"/*.json; do
|
||||
[ -f "$f" ] || continue
|
||||
if ! validate_json "$f"; then
|
||||
warn "Invalid JSON: $(basename "$f")"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
done
|
||||
[ "$errors" -eq 0 ] && ok "All config files valid" || warn "$errors config(s) invalid"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# PRE-FLIGHT CHECKS
|
||||
# =============================================================================
|
||||
preflight_check() {
|
||||
local fatal=false
|
||||
|
||||
for cmd in git mvn node python3 yarn; do
|
||||
command -v "$cmd" &>/dev/null || { fail "Missing: $cmd"; fatal=true; }
|
||||
done
|
||||
command -v "$MYSQL_CLIENT" &>/dev/null || { fail "Missing: $MYSQL_CLIENT"; fatal=true; }
|
||||
command -v "$MYSQL_DUMP" &>/dev/null || { fail "Missing: $MYSQL_DUMP"; fatal=true; }
|
||||
$fatal && die "Required commands missing"
|
||||
|
||||
ok "All commands available"
|
||||
|
||||
for d in "$EMULATOR_DIR/Emulator" "$NITRO_RENDERER" "$NITRO_CLIENT" "$NITRO_SRC_DIR"; do
|
||||
[ -d "$d" ] || die "Missing dir: $d"
|
||||
done
|
||||
ok "All directories exist"
|
||||
|
||||
local total_kb=$(df --output=avail "$EMULATOR_DIR" 2>/dev/null | tail -1)
|
||||
local total_gb=$((total_kb / 1024 / 1024))
|
||||
[ "$total_gb" -lt "$MIN_DISK_GB" ] && die "Only ${total_gb}GB free (min ${MIN_DISK_GB}GB)"
|
||||
if [ "$total_gb" -lt $((MIN_DISK_GB * 2)) ]; then
|
||||
warn "Low disk: ${total_gb}GB free"
|
||||
else
|
||||
ok "${total_gb}GB disk available"
|
||||
fi
|
||||
|
||||
$MYSQL_CLIENT $MYSQL_CRED -e "SELECT 1" "$DB_NAME" &>/dev/null || die "DB connection failed"
|
||||
ok "Database connected"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# UPDATE FUNCTIONS
|
||||
# =============================================================================
|
||||
@@ -349,12 +462,12 @@ update_emulator() {
|
||||
if git_update "$EMULATOR_DIR/Emulator" "$NITRO_BRANCH"; then
|
||||
HAD_UPDATES=true; UPDATED_REPOS+=("Emulator")
|
||||
cd "$EMULATOR_DIR/Emulator"
|
||||
spinner_start "Building emulator..."
|
||||
if mvn package -q >> "$LOG_FILE" 2>&1; then
|
||||
spinner_start "Building emulator (parallel)..."
|
||||
if mvn package -q -T 1C -Dmaven.test.skip=true >> "$LOG_FILE" 2>&1; then
|
||||
spinner_stop ok
|
||||
else
|
||||
spinner_stop fail
|
||||
tail -10 "$LOG_FILE" | grep -E '(ERROR|FAILURE|BUILD)' || true
|
||||
tail -20 "$LOG_FILE" | grep -E '(ERROR|FAILURE|BUILD)' || true
|
||||
die "Maven build failed (see: $LOG_FILE)"
|
||||
fi
|
||||
local jar=$(find target -maxdepth 1 -name 'Polaris-*-jar-with-dependencies.jar' -printf '%T@ %p\n' 2>/dev/null | sort -rn | sed -n '1s/^[0-9.]* //p' | xargs -r basename 2>/dev/null || echo "")
|
||||
@@ -382,7 +495,7 @@ update_renderer() {
|
||||
HAD_UPDATES=true; UPDATED_REPOS+=("Nitro_Render_V3")
|
||||
cd "$NITRO_RENDERER"
|
||||
spinner_start "Installing deps..."
|
||||
yarn install --frozen-lockfile 2>&1 || { clean_node_modules && yarn install 2>&1; } || { spinner_stop fail; die "yarn install failed"; }
|
||||
yarn install --frozen-lockfile --prefer-offline 2>&1 || { clean_node_modules && yarn install 2>&1; } || { spinner_stop fail; die "yarn install failed"; }
|
||||
spinner_stop ok; ok "Renderer dependencies installed"
|
||||
else
|
||||
info "Renderer: already up to date"
|
||||
@@ -395,7 +508,7 @@ update_client() {
|
||||
HAD_UPDATES=true; NITRO_BUILT=true; UPDATED_REPOS+=("Nitro-V3")
|
||||
cd "$NITRO_CLIENT"
|
||||
spinner_start "Installing deps..."
|
||||
yarn install --frozen-lockfile 2>&1 || { clean_node_modules && yarn install 2>&1; } || { spinner_stop fail; die "yarn install failed"; }
|
||||
yarn install --frozen-lockfile --prefer-offline 2>&1 || { clean_node_modules && yarn install 2>&1; } || { spinner_stop fail; die "yarn install failed"; }
|
||||
spinner_stop ok
|
||||
spinner_start "Building frontend..."
|
||||
if yarn build >> "$LOG_FILE" 2>&1; then
|
||||
@@ -415,6 +528,11 @@ update_client() {
|
||||
sync_configs() {
|
||||
step 5 8 "Sync Configurations"
|
||||
mkdir -p "$GAMEDATA_CONF_DIR"
|
||||
|
||||
# Backup current configs before overwriting
|
||||
local cb=$(backup_configs)
|
||||
info "Config back-up: $(basename "$cb")"
|
||||
|
||||
local ms="$SCRIPT_DIR/scripts/merge-config.cjs"
|
||||
local dcd="$NITRO_CLIENT/dist/configuration"
|
||||
for d in "$NITRO_SRC_DIR" "$GAMEDATA_CONF_DIR"; do
|
||||
@@ -432,6 +550,9 @@ sync_configs() {
|
||||
done
|
||||
ok "$ec config file(s) synced"
|
||||
|
||||
# Validate the generated configs
|
||||
validate_configs "$NITRO_SRC_DIR"
|
||||
|
||||
info "Applying critical config URLs..."
|
||||
NITRO_SRC_DIR="$NITRO_SRC_DIR" NITRO_DIST_CONFIG_DIR="$dcd" \
|
||||
NITRO_IMAGE_LIBRARY_URL="$NITRO_IMAGE_LIBRARY_URL" NITRO_HOF_FURNITURE_URL="$NITRO_HOF_FURNITURE_URL" \
|
||||
@@ -463,15 +584,28 @@ for path in paths:
|
||||
with open(path, "w") as f: json.dump(data, f, indent=(4 if "dist" not in path else None), separators=(",", ":") if "dist" in path else (",", ": "))
|
||||
print(f" [OK] Fixed: {os.path.basename(path)}")
|
||||
' && ok "All config URLs synced"
|
||||
|
||||
# Flush Redis so new config is picked up immediately
|
||||
if command -v redis-cli &>/dev/null; then
|
||||
redis-cli FLUSHALL 2>/dev/null && ok "Redis cache flushed" || true
|
||||
fi
|
||||
}
|
||||
|
||||
do_cleanup() {
|
||||
step 6 8 "Cleanup"
|
||||
local lc=$(find "$EMULATOR_DIR" -name "*.log" -mtime +14 2>/dev/null | wc -l)
|
||||
find "$EMULATOR_DIR" -name "*.log" -mtime +14 -exec rm -f {} \; 2>/dev/null || true
|
||||
# Clean old config backups (keep 10 most recent)
|
||||
local cb_count=$(find "$CONFIG_BACKUP_DIR" -maxdepth 1 -type d ! -name 'rollback' 2>/dev/null | wc -l)
|
||||
if [ "$cb_count" -gt 10 ]; then
|
||||
find "$CONFIG_BACKUP_DIR" -maxdepth 1 -type d ! -name 'rollback' -printf '%T@ %p\n' 2>/dev/null | sort -rn | tail -n +11 | sed 's/^[0-9.]* //' | xargs -r rm -rf || true
|
||||
ok "Old config backups pruned"
|
||||
fi
|
||||
[ -d "$BACKUP_DIR" ] && find "$BACKUP_DIR" -maxdepth 1 -name '*.sql' -printf '%T@ %p\n' 2>/dev/null | sort -rn | tail -n +6 | sed 's/^[0-9.]* //' | xargs -r rm -f || true
|
||||
yarn cache clean 2>/dev/null || true
|
||||
rm -rf /tmp/nitro-* 2>/dev/null || true
|
||||
rm -rf /tmp/nitro-* /tmp/epicnext-* 2>/dev/null || true
|
||||
# Clean old Maven build artifacts (older than 7 days)
|
||||
find "$EMULATOR_DIR/Emulator" -maxdepth 3 -name '*.jar' -mtime +7 2>/dev/null -exec rm -f {} \; || true
|
||||
ok "Cleanup done ($lc logs removed)"
|
||||
}
|
||||
|
||||
@@ -531,42 +665,33 @@ show_summary() {
|
||||
# =============================================================================
|
||||
cmd_update() {
|
||||
echo ""
|
||||
acquire_lock
|
||||
DRY_RUN=${DRY_RUN:-false}
|
||||
info "Site: ${NITRO_SITE_URL:-?} | Branch: $NITRO_BRANCH | Mode: ${SELECTIVE_UPDATE:-full}${DRY_RUN:+ [DRY-RUN]}"
|
||||
info "Log: $LOG_FILE"
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
info "Dry-run: would update repos, run DB backups, build, sync configs, cleanup, restart services"
|
||||
show_summary
|
||||
release_lock
|
||||
return
|
||||
fi
|
||||
|
||||
step 1 8 "System Diagnostics"
|
||||
for cmd in git mvn node python3 yarn; do
|
||||
command -v "$cmd" &>/dev/null || die "Missing: $cmd"
|
||||
done
|
||||
command -v "$MYSQL_CLIENT" &>/dev/null || die "Missing: $MYSQL_CLIENT"
|
||||
command -v "$MYSQL_DUMP" &>/dev/null || die "Missing: $MYSQL_DUMP"
|
||||
ok "All commands available"
|
||||
|
||||
for d in "$EMULATOR_DIR/Emulator" "$NITRO_RENDERER" "$NITRO_CLIENT" "$NITRO_SRC_DIR"; do
|
||||
[ -d "$d" ] || die "Missing dir: $d"
|
||||
done
|
||||
ok "All directories exist"
|
||||
|
||||
local ak=$(df --output=avail "$EMULATOR_DIR" 2>/dev/null | tail -1)
|
||||
local ag=$((ak / 1024 / 1024))
|
||||
[ "$ag" -lt "$MIN_DISK_GB" ] && die "Only ${ag}GB free (min ${MIN_DISK_GB}GB)"
|
||||
ok "${ag}GB disk available"
|
||||
|
||||
$MYSQL_CLIENT $MYSQL_CRED -e "SELECT 1" "$DB_NAME" &>/dev/null || die "DB connection failed"
|
||||
ok "Database connected"
|
||||
preflight_check
|
||||
|
||||
case "${SELECTIVE_UPDATE:-full}" in
|
||||
emulator) update_emulator ;;
|
||||
renderer) update_renderer ;;
|
||||
client) update_client ;;
|
||||
configs) sync_configs ;;
|
||||
dev)
|
||||
# Quick dev mode: skip builds, just sync configs and reload
|
||||
info "Dev mode: skipping builds, syncing configs only"
|
||||
sync_configs
|
||||
do_restart
|
||||
;;
|
||||
*)
|
||||
RUN_ROLLBACK=true
|
||||
update_emulator
|
||||
update_renderer &
|
||||
update_client &
|
||||
@@ -575,10 +700,12 @@ cmd_update() {
|
||||
do_cleanup
|
||||
do_permissions
|
||||
do_restart
|
||||
RUN_ROLLBACK=false
|
||||
;;
|
||||
esac
|
||||
|
||||
show_summary
|
||||
release_lock
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@@ -666,7 +793,12 @@ cmd_status() {
|
||||
[ -d "$pa/.git" ] || continue
|
||||
local br=$(cd "$pa" && git branch --show-current 2>/dev/null || echo "?")
|
||||
local cm=$(cd "$pa" && git log --oneline -1 2>/dev/null | cut -c1-30 || echo "?")
|
||||
printf " ${C_CYAN}║${C_RESET} %-12s ${C_CYAN}%-8s${C_RESET} %s\n" "$nm" "$br" "$cm"
|
||||
local ah=$(cd "$pa" && git rev-list --count "origin/$(git branch --show-current 2>/dev/null)"..HEAD 2>/dev/null || echo "0")
|
||||
local bh=$(cd "$pa" && git rev-list --count HEAD.."origin/$(git branch --show-current 2>/dev/null)" 2>/dev/null || echo "0")
|
||||
printf " ${C_CYAN}║${C_RESET} %-12s ${C_CYAN}%-8s${C_RESET} %s" "$nm" "$br" "$cm"
|
||||
[ "$ah" -gt 0 ] && printf " ${C_RED}+${ah}${C_RESET}" || printf " "
|
||||
[ "$bh" -gt 0 ] && printf " ${C_YELLOW}-${bh}${C_RESET}" || printf " "
|
||||
printf " ${C_CYAN}║${C_RESET}\n"
|
||||
done; box_bottom 56
|
||||
echo ""
|
||||
}
|
||||
@@ -712,7 +844,7 @@ cmd_services() {
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}1)${C_RESET} Start Emulator ${C_BOLD}2)${C_RESET} Stop Emulator ${C_BOLD}3)${C_RESET} Restart Emulator"
|
||||
echo -e " ${C_BOLD}4)${C_RESET} Start Nginx ${C_BOLD}5)${C_RESET} Restart Nginx ${C_BOLD}6)${C_RESET} Status All"
|
||||
echo -e " ${C_BOLD}7)${C_RESET} Emulator Logs ${C_BOLD}0)${C_RESET} Return"
|
||||
echo -e " ${C_BOLD}7)${C_RESET} Emulator Logs ${C_BOLD}8)${C_RESET} Emulator Journal ${C_BOLD}0)${C_RESET} Return"
|
||||
echo -en "\n Select: "; local c; read -rt 30 c
|
||||
case "$c" in
|
||||
1) sudo systemctl start "$EMULATOR_SERVICE" && ok "Started" || fail "Failed" ;;
|
||||
@@ -725,6 +857,7 @@ cmd_services() {
|
||||
printf " %-25s %b\n" "$s" "$st"
|
||||
done ;;
|
||||
7) sudo journalctl -u "$EMULATOR_SERVICE" --no-pager -n 30 ;;
|
||||
8) sudo journalctl -u "$EMULATOR_SERVICE" --no-pager -n 100 --output=short-full ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -736,7 +869,7 @@ cmd_database() {
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}1)${C_RESET} DB Info ${C_BOLD}2)${C_RESET} List Tables ${C_BOLD}3)${C_RESET} Table Sizes"
|
||||
echo -e " ${C_BOLD}4)${C_RESET} Optimize ${C_BOLD}5)${C_RESET} Custom Query ${C_BOLD}6)${C_RESET} Active Users"
|
||||
echo -e " ${C_BOLD}0)${C_RESET} Return"
|
||||
echo -e " ${C_BOLD}7)${C_RESET} Processlist ${C_BOLD}0)${C_RESET} Return"
|
||||
echo -en "\n Select: "; local c; read -rt 30 c
|
||||
case "$c" in
|
||||
1) box_top "DB INFO" 50
|
||||
@@ -752,6 +885,7 @@ cmd_database() {
|
||||
done; spinner_stop ok; ok "Optimized" ;;
|
||||
5) echo -en " SQL: "; local q; read -rt 30 q; [ -n "$q" ] && $MYSQL_CLIENT $MYSQL_CRED "$DB_NAME" -e "$q" 2>/dev/null ;;
|
||||
6) $MYSQL_CLIENT $MYSQL_CRED -e "SELECT name, motto FROM $DB_NAME.users WHERE online='1'" 2>/dev/null || warn "Could not query" ;;
|
||||
7) $MYSQL_CLIENT $MYSQL_CRED -e "SHOW FULL PROCESSLIST" 2>/dev/null || warn "Could not query" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -804,15 +938,18 @@ cmd_logs() {
|
||||
cmd_clean() {
|
||||
step 1 1 "Cache Cleanup"
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}1)${C_RESET} Yarn ${C_BOLD}2)${C_RESET} Laravel ${C_BOLD}3)${C_RESET} Redis"
|
||||
echo -e " ${C_BOLD}4)${C_RESET} Logs ${C_BOLD}5)${C_RESET} Everything ${C_BOLD}0)${C_RESET} Return"
|
||||
echo -e " ${C_BOLD}1)${C_RESET} Yarn ${C_BOLD}2)${C_RESET} Next.js ${C_BOLD}3)${C_RESET} Redis"
|
||||
echo -e " ${C_BOLD}4)${C_RESET} Logs ${C_BOLD}5)${C_RESET} Everything ${C_BOLD}6)${C_RESET} Docker"
|
||||
echo -e " ${C_BOLD}7)${C_RESET} Maven ${C_BOLD}0)${C_RESET} Return"
|
||||
echo -en "\n Select: "; local c; read -rt 30 c
|
||||
case "$c" in
|
||||
1) yarn cache clean 2>/dev/null && ok "Yarn cleaned" ;;
|
||||
2) cd "$SCRIPT_DIR" && rm -rf .next 2>/dev/null && ok "Next.js cache cleared" ;;
|
||||
3) redis-cli FLUSHALL 2>/dev/null && ok "Redis flushed" || warn "Redis N/A" ;;
|
||||
4) find "$EMULATOR_DIR" -name "*.log" -mtime +14 -exec rm -f {} \; 2>/dev/null; ok "Logs cleaned" ;;
|
||||
5) yarn cache clean 2>/dev/null; find "$EMULATOR_DIR" -name "*.log" -mtime +14 -exec rm -f {} \; 2>/dev/null; rm -rf /tmp/nitro-* 2>/dev/null; ok "Full cleanup" ;;
|
||||
5) yarn cache clean 2>/dev/null; find "$EMULATOR_DIR" -name "*.log" -mtime +14 -exec rm -f {} \; 2>/dev/null; rm -rf /tmp/nitro-* /tmp/epicnext-* 2>/dev/null; ok "Full cleanup" ;;
|
||||
6) command -v docker &>/dev/null && docker system prune -f 2>/dev/null && ok "Docker pruned" || warn "Docker N/A" ;;
|
||||
7) find "$EMULATOR_DIR/Emulator" -maxdepth 3 -name '*.jar' -mtime +7 -exec rm -f {} \; 2>/dev/null; ok "Old Maven artifacts cleaned" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -828,7 +965,11 @@ cmd_gitlog() {
|
||||
case "$c" in 1) repo="$EMULATOR_DIR/Emulator" ;; 2) repo="$NITRO_CLIENT" ;; 3) repo="$NITRO_RENDERER" ;; *) return ;; esac
|
||||
[ ! -d "$repo/.git" ] && { warn "Not a git repo"; return; }
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}Last 20 commits on ${C_CYAN}$(cd "$repo" && git branch --show-current 2>/dev/null)${C_RESET}:"
|
||||
local branch
|
||||
branch=$(cd "$repo" && git branch --show-current 2>/dev/null || echo "?")
|
||||
local ahead
|
||||
ahead=$(cd "$repo" && git rev-list --count "origin/${branch}"..HEAD 2>/dev/null || echo "0")
|
||||
echo -e " ${C_BOLD}Last 20 commits on ${C_CYAN}${branch}${C_RESET} (ahead: ${C_RED}${ahead}${C_RESET}):"
|
||||
echo ""
|
||||
cd "$repo" && git log --pretty=format:" ${C_CYAN}%h${C_RESET} %C(yellow)%cr${C_RESET} %s" -20 2>/dev/null
|
||||
echo -e "\n"
|
||||
@@ -886,6 +1027,27 @@ cmd_schedule() {
|
||||
esac
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# GIT STASH VIEWER
|
||||
# =============================================================================
|
||||
cmd_stash() {
|
||||
step 1 1 "Git Stashes"
|
||||
local found=false
|
||||
for repo in "$EMULATOR_DIR/Emulator" "$NITRO_CLIENT" "$NITRO_RENDERER"; do
|
||||
[ -d "$repo/.git" ] || continue
|
||||
local list
|
||||
list=$(cd "$repo" && git stash list 2>/dev/null)
|
||||
if [ -n "$list" ]; then
|
||||
found=true
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}$(basename "$repo"):${C_RESET}"
|
||||
echo "$list" | while IFS= read -r line; do echo -e " ${C_CYAN}→${C_RESET} $line"; done
|
||||
fi
|
||||
done
|
||||
$found || warn "No stashes found"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MAIN MENU
|
||||
# =============================================================================
|
||||
@@ -894,6 +1056,7 @@ pick_branch_and_update() {
|
||||
case "${SELECTIVE_UPDATE:-full}" in
|
||||
emulator) mode_label="Emulator Only" ;; client) mode_label="Client Only" ;;
|
||||
renderer) mode_label="Renderer Only" ;; configs) mode_label="Configs Only" ;;
|
||||
dev) mode_label="Dev Mode" ;;
|
||||
esac
|
||||
local branches=()
|
||||
load_branches branches
|
||||
@@ -930,28 +1093,29 @@ cmd_interactive() {
|
||||
echo ""
|
||||
echo " ╔═══════════════════════════════════════════════════════════════════════════╗"
|
||||
echo " ║ ║"
|
||||
echo " ║ ███████╗███╗ ███╗ █████╗ ██████╗ ████████╗ ║"
|
||||
echo " ║ ██╔════╝████╗ ████║██╔══██╗██╔══██╗╚══██╔══╝ ║"
|
||||
echo " ║ █████╗ ██╔████╔██║███████║██████╔╝ ██║ ║"
|
||||
echo " ║ ██╔══╝ ██║╚██╔╝██║██╔══██║██╔══██╗ ██║ ║"
|
||||
echo " ║ ███████╗██║ ╚═╝ ██║██║ ██║██║ ██║ ██║ ║"
|
||||
echo " ║ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ║"
|
||||
echo " ║ ███████╗███╗ ███╗ █████╗ ██████╗ ████████╗ ║"
|
||||
echo " ║ ██╔════╝████╗ ████║██╔══██╗██╔══██╗╚══██╔══╝ ║"
|
||||
echo " ║ █████╗ ██╔████╔██║███████║██████╔╝ ██║ ║"
|
||||
echo " ║ ██╔══╝ ██║╚██╔╝██║██╔══██║██╔══██╗ ██║ ║"
|
||||
echo " ║ ███████╗██║ ╚═╝ ██║██║ ██║██║ ██║ ██║ ║"
|
||||
echo " ║ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ║"
|
||||
echo " ║ ║"
|
||||
echo " ╠═══════════════════════════════════════════════════════════════════════════╣"
|
||||
echo -e " ║ ${C_GOLD}${C_BOLD} Emulator / Nitro-V3 / Nitro-V3-Render${C_CYAN} ║"
|
||||
echo -e " ║ ${C_WHITE}${C_BOLD} Updater by Remco — epicnabbo.nl${C_CYAN} ║"
|
||||
echo -e " ║ ${C_GOLD}${C_BOLD} SMaRT v${SCRIPT_VERSION} — Emulator / Nitro-V3 / Nitro-V3-Render${C_CYAN} ║"
|
||||
echo -e " ║ ${C_WHITE}${C_BOLD} Updater & Manager by Remco — epicnabbo.nl${C_CYAN} ║"
|
||||
echo " ╠═══════════════════════════════════════════════════════════════════════════╣"
|
||||
echo -e " ║ ${C_DIM}Branch: ${C_CYAN}${NITRO_BRANCH}${C_DIM} (${#branches[@]} detected) │ $(date '+%H:%M')${C_CYAN} ║"
|
||||
echo -e " ║ ${C_DIM}Branch: ${C_CYAN}${NITRO_BRANCH}${C_DIM} (${#branches[@]} branches) │ $(date '+%H:%M')${C_CYAN} ║"
|
||||
echo " ╚═══════════════════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${C_RESET}"
|
||||
|
||||
echo -e " ${C_BG_GREEN}${C_WHITE}${C_BOLD} UPDATE ${C_RESET}"
|
||||
echo -e " ${C_GREEN}${C_BOLD}1)${C_RESET} ${E_ROCKET} Quick Update — branch: ${C_CYAN}${NITRO_BRANCH}${C_RESET}"
|
||||
echo -e " ${C_GREEN}${C_BOLD}1)${C_RESET} ${E_ROCKET} Quick Update — current branch"
|
||||
echo -e " ${C_GREEN}${C_BOLD}2)${C_RESET} ${E_BOLT} Full Update (choose branch)"
|
||||
echo -e " ${C_GREEN}${C_BOLD}3)${C_RESET} ${E_GEAR} Emulator Only"
|
||||
echo -e " ${C_GREEN}${C_BOLD}4)${C_RESET} ${E_GEAR} Nitro-V3 Client Only"
|
||||
echo -e " ${C_GREEN}${C_BOLD}5)${C_RESET} ${E_GEAR} Renderer Only"
|
||||
echo -e " ${C_GREEN}${C_BOLD}6)${C_RESET} ${E_GEAR} Configs Only"
|
||||
echo -e " ${C_GREEN}${C_BOLD}19)${C_RESET} ${E_BOLT} Dev Mode (skip builds, only configs)"
|
||||
echo ""
|
||||
echo -e " ${C_BG_MAGENTA}${C_WHITE}${C_BOLD} TOOLS ${C_RESET}"
|
||||
echo -e " ${C_MAGENTA}${C_BOLD}7)${C_RESET} ${E_GIT} Switch Branch"
|
||||
@@ -968,10 +1132,11 @@ cmd_interactive() {
|
||||
echo -e " ${C_BLUE}${C_BOLD}16)${C_RESET} ${E_CONSOLE} Git Log"
|
||||
echo -e " ${C_BLUE}${C_BOLD}17)${C_RESET} ${E_GLOBE} Compare Branches"
|
||||
echo -e " ${C_BLUE}${C_BOLD}18)${C_RESET} ${E_CLOCK} Cron Scheduler"
|
||||
echo -e " ${C_BLUE}${C_BOLD}20)${C_RESET} ${E_GIT} View Git Stashes"
|
||||
echo ""
|
||||
echo -e " ${C_RED}${C_BOLD}0)${C_RESET} Exit"
|
||||
echo ""
|
||||
echo -en " ${C_CYAN}${C_BOLD}Select [0-18]${C_RESET}: "
|
||||
echo -en " ${C_CYAN}${C_BOLD}Select [0-20]${C_RESET}: "
|
||||
local choice; read -rt 30 choice
|
||||
|
||||
case "$choice" in
|
||||
@@ -1007,6 +1172,8 @@ cmd_interactive() {
|
||||
16) (cmd_gitlog) ;;
|
||||
17) (cmd_compare) ;;
|
||||
18) (cmd_schedule) ;;
|
||||
19) SELECTIVE_UPDATE="dev"; (pick_branch_and_update) || warn "Dev mode had errors" ;;
|
||||
20) (cmd_stash) ;;
|
||||
0|q|Q) echo -e "\n ${C_GREEN}Goodbye!${C_RESET}"; cursor_show; exit 0 ;;
|
||||
*) warn "Invalid selection" ;;
|
||||
esac
|
||||
@@ -1022,16 +1189,16 @@ cmd_interactive() {
|
||||
# =============================================================================
|
||||
show_help() {
|
||||
echo ""
|
||||
echo -e " ${C_GOLD}${C_BOLD}Emulator / Nitro-V3 / Nitro-V3-Render Updater${C_RESET}"
|
||||
echo -e " ${C_DIM}by Remco — epicnabbo.nl v${SCRIPT_VERSION}${C_RESET}"
|
||||
echo -e " ${C_GOLD}${C_BOLD}SMaRT — Emulator / Nitro-V3 / Nitro-V3-Render Updater & Manager${C_RESET}"
|
||||
echo -e " ${C_DIM}by Remco — epicnabbo.nl v${SCRIPT_VERSION} (build ${SCRIPT_BUILD})${C_RESET}"
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}USAGE:${C_RESET} $SCRIPT_NAME <command> [options]"
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}COMMANDS:${C_RESET}"
|
||||
echo -e " ${C_GREEN}interactive${C_RESET} Open menu (default)"
|
||||
echo -e " ${C_GREEN}update${C_RESET} Run update (--only=emulator|client|renderer|configs)"
|
||||
echo -e " ${C_GREEN}backup${C_RESET} Create backup"
|
||||
echo -e " ${C_GREEN}restore${C_RESET} Restore backup"
|
||||
echo -e " ${C_GREEN}update${C_RESET} Run update"
|
||||
echo -e " ${C_GREEN}backup${C_RESET} Create database backup"
|
||||
echo -e " ${C_GREEN}restore${C_RESET} Restore from backup"
|
||||
echo -e " ${C_GREEN}backups${C_RESET} List backups"
|
||||
echo -e " ${C_GREEN}status${C_RESET} System dashboard"
|
||||
echo -e " ${C_GREEN}health${C_RESET} Health check"
|
||||
@@ -1043,15 +1210,15 @@ show_help() {
|
||||
echo -e " ${C_GREEN}gitlog${C_RESET} Git history"
|
||||
echo -e " ${C_GREEN}compare${C_RESET} Branch diff"
|
||||
echo -e " ${C_GREEN}schedule${C_RESET} Cron setup"
|
||||
echo -e " ${C_GREEN}help${C_RESET} This help"
|
||||
echo -e " ${C_GREEN}stash${C_RESET} View git stashes"
|
||||
echo ""
|
||||
echo -e " ${C_BOLD}OPTIONS:${C_RESET}"
|
||||
echo -e " ${C_CYAN}--branch, -b${C_RESET} Branch (auto-detects)"
|
||||
echo -e " ${C_CYAN}--url, -u${C_RESET} Site URL"
|
||||
echo -e " ${C_CYAN}--only=${C_RESET} emulator|client|renderer|configs"
|
||||
echo -e " ${C_CYAN}--only=${C_RESET} emulator|client|renderer|configs|dev"
|
||||
echo -e " ${C_CYAN}--dry-run, -n${C_RESET} Preview only (no changes)"
|
||||
echo -e " ${C_CYAN}--help, -h${C_RESET} Help"
|
||||
echo -e " ${C_CYAN}--version, -V${C_RESET} Version"
|
||||
echo -e " ${C_CYAN}--help, -h${C_RESET} Show this help"
|
||||
echo -e " ${C_CYAN}--version, -V${C_RESET} Show version"
|
||||
echo ""
|
||||
}
|
||||
|
||||
@@ -1077,8 +1244,9 @@ main() {
|
||||
config|cfg) cmd="config" ;;
|
||||
logs|log) cmd="logs" ;;
|
||||
clean|cl) cmd="clean" ;;
|
||||
stash|stashes) cmd="stash" ;;
|
||||
help|-h|--help) cmd="help" ;;
|
||||
version|-V|--version) echo "v${SCRIPT_VERSION}"; exit 0 ;;
|
||||
version|-V|--version) echo "v${SCRIPT_VERSION} (build ${SCRIPT_BUILD})"; exit 0 ;;
|
||||
--branch|-b) shift; NITRO_BRANCH="$1" ;;
|
||||
--url|-u) shift; NITRO_SITE_URL="$1" ;;
|
||||
--only=*) SELECTIVE_UPDATE="${1#*=}" ;;
|
||||
@@ -1090,7 +1258,6 @@ main() {
|
||||
done
|
||||
[ -z "$cmd" ] && cmd="interactive"
|
||||
|
||||
# Derive URLs after CLI parsing (--url may have changed NITRO_SITE_URL)
|
||||
if [ -z "${NITRO_SITE_URL:-}" ] && [ -n "${APP_URL:-}" ]; then NITRO_SITE_URL="$APP_URL"; fi
|
||||
case "${NITRO_SITE_URL:-}" in
|
||||
https://*) NITRO_WS_PROTO="wss://" ; NITRO_DOMAIN="${NITRO_SITE_URL#https://}" ;;
|
||||
@@ -1105,7 +1272,6 @@ main() {
|
||||
NITRO_ASSET_URL="${NITRO_ASSET_URL:-${NITRO_SITE_URL:-}/gamedata/bundled}"
|
||||
NITRO_FURNI_ASSET_ICON_URL="${NITRO_FURNI_ASSET_ICON_URL:-${NITRO_SITE_URL:-}/gamedata/icons/%libname%%param%_icon.png}"
|
||||
|
||||
# Log redirect
|
||||
exec > >(tee -a "$LOG_FILE") 2>&1
|
||||
|
||||
case "$cmd" in
|
||||
@@ -1124,6 +1290,7 @@ main() {
|
||||
gitlog) cmd_gitlog ;;
|
||||
compare) cmd_compare ;;
|
||||
schedule) cmd_schedule ;;
|
||||
stash) cmd_stash ;;
|
||||
help) show_help ;;
|
||||
esac
|
||||
|
||||
|
||||
Reference in new issue
Block a user