feat: rename Nitro-V3 to Octane, add auto-setup and old Nitro cleanup

- Rename all references from Nitro-V3/Nitro_Render_V3 to Octane/Octane-Renderer
- Update default paths to /var/www/Octane and /var/www/Octane-Renderer
- Update ASCII art banner from NITRO to OCTANE
- Add GIT_REPO_CLIENT and GIT_REPO_RENDERER constants (configurable via .env)
- Add auto_setup_missing_repos() - clones, installs deps, and builds frontend
- Add cmd_setup command (menu option 22 / CLI: setup/init)
- Preflight check now auto-clones missing repos instead of dying
- Add cmd_cleanup_old_nitro() - detects old Nitro dirs and safely removes them:
  Updates symlinks, nginx configs, and systemd services before deletion
- Add cmd_cleanup_old_nitro command (menu option 23 / CLI: cleanup-nitro)
- Add translations for NL, FR, ES, DE, IT
- Update notification text to [Octane Update]
This commit is contained in:
openhands committed 2026-08-25 15:15:17 +02:00
1 parent 1a0d20fae5
commit 3a76dbdb97
1 file changed
+396 -50
+396 -50
View File
@@ -2,7 +2,7 @@
set -Eeo pipefail
# ╔══════════════════════════════════════════════════════════════════════════════╗
# ║ SMaRT — Emulator / Nitro-V3 / Nitro-V3-Render ║
# ║ SMaRT — Emulator / Octane / Octane-Renderer ║
# ║ Updater & Manager by Remco ║
# ╚══════════════════════════════════════════════════════════════════════════════╝
@@ -111,16 +111,19 @@ EMULATOR_REPO="${NITRO_EMULATOR_REPO:-$EMULATOR_DIR}"
EMULATOR_MODULE="${NITRO_EMULATOR_MODULE:-$EMULATOR_DIR/Emulator}"
SQL_DIR="${NITRO_SQL_DIR:-$EMULATOR_DIR/Database/Database Updates}"
GAMEDATA_CONF_DIR="${NITRO_GAMEDATA_DIR:-/var/www/Gamedata/config}"
NITRO_SRC_DIR="${NITRO_CLIENT_DIR:-/var/www/Nitro-V3/public/configuration}"
NITRO_SRC_DIR="${NITRO_CLIENT_DIR:-/var/www/Octane/public/configuration}"
BACKUP_DIR="${NITRO_BACKUP_DIR:-$EMULATOR_DIR/Database/Database Updates/backups}"
NITRO_CLIENT="${NITRO_CLIENT_SRC:-/var/www/Nitro-V3}"
NITRO_RENDERER="${NITRO_RENDERER_SRC:-/var/www/Nitro_Render_V3}"
NITRO_CLIENT="${NITRO_CLIENT_SRC:-/var/www/Octane}"
NITRO_RENDERER="${NITRO_RENDERER_SRC:-/var/www/Octane-Renderer}"
NITRO_BRANCH="${NITRO_BRANCH:-}"
# Dedicated per-repo yarn cache folders. The renderer + client installs run in
# parallel and yarn 1.22 has no cache locking, so a single shared cache gets
# corrupted and node_modules is left incomplete (vite/pixi.js missing) while
# yarn still exits 0. Isolating each repo's cache via --cache-folder prevents
# that race entirely.
# GitHub repository URLs for auto-setup (used when repos are missing)
GIT_REPO_CLIENT="${NITRO_GIT_CLIENT:-https://github.com/duckietm/Octane.git}"
GIT_REPO_RENDERER="${NITRO_GIT_RENDERER:-https://github.com/duckietm/Octane-Renderer.git}"
YARN_CACHE_DIR="${NITRO_YARN_CACHE_DIR:-/var/www/.yarn-cache}"
mkdir -p "$YARN_CACHE_DIR" 2>/dev/null || true
MIN_DISK_GB="${NITRO_MIN_DISK_GB:-5}"
@@ -175,7 +178,7 @@ load_language() {
["Quick Update — current branch"]="Snelle Update — huidige branch"
["Full Update (choose branch)"]="Volledige Update (kies branch)"
["Emulator Only"]="Alleen Emulator"
["Nitro-V3 Client Only"]="Alleen Nitro-V3 Client"
["Octane Client Only"]="Alleen Octane Client"
["Renderer Only"]="Alleen Renderer"
["Configs Only"]="Alleen Configuraties"
["Dev Mode (skip builds, only configs)"]="Dev Modus (skip builds, alleen configs)"
@@ -194,13 +197,15 @@ load_language() {
["View Git Stashes"]="Bekijk Git Stashes"
["Exit"]="Afsluiten"
["Flyaway Repair"]="Vliegende Reparatie"
["Auto-setup missing repos"]="Automatisch ontbrekende repos installeren"
["Cleanup old Nitro dirs"]="Oude Nitro mappen opruimen"
["Rebuild Frontend"]="Frontend Herbouwen"
["Rebuild Emulator"]="Emulator Herbouwen"
["Select [0-20]"]="Selecteer [0-21]"
["Select [0-23]"]="Selecteer [0-23]"
["Press Enter to continue..."]="Druk op Enter om door te gaan..."
["Goodbye!"]="Tot ziens!"
# ── HELP ──────────────────────────────────────────────
["SMaRT — Emulator / Nitro-V3 / Nitro-V3-Render Updater & Manager"]="SMaRT — Emulator / Nitro-V3 / Nitro-V3-Render Updater & Beheerder"
["SMaRT — Emulator / Octane / Octane-Renderer Updater & Manager"]="SMaRT — Emulator / Octane / Octane-Renderer Updater & Beheerder"
["USAGE:"]="GEBRUIK:"
["COMMANDS:"]="COMMANDO'S:"
["Open menu (default)"]="Open menu (standaard)"
@@ -229,8 +234,8 @@ load_language() {
["Unknown:"]="Onbekend:"
# ── STEP HEADERS ──────────────────────────────────────
["Update & Build Emulator"]="Update & Bouw Emulator"
["Update Nitro_Render_V3"]="Update Nitro_Render_V3"
["Update & Build Nitro-V3"]="Update & Bouw Nitro-V3"
["Update Octane-Renderer"]="Update Octane-Renderer"
["Update & Build Octane"]="Update & Bouw Octane"
["Sync Configurations"]="Synchroniseer Configuraties"
["Cleanup"]="Opschonen"
["Set Permissions"]="Stel Permissies in"
@@ -271,11 +276,11 @@ load_language() {
["Database connected"]="Database verbonden"
["Emulator: already up to date"]="Emulator: al up-to-date"
["Renderer: already up to date"]="Renderer: al up-to-date"
["Nitro-V3: already up to date"]="Nitro-V3: al up-to-date"
["Octane: already up to date"]="Octane: al up-to-date"
["Emulator JAR backed up"]="Emulator JAR geback-upt"
["Nitro-V3 dist backed up"]="Nitro-V3 dist geback-upt"
["Octane dist backed up"]="Octane dist geback-upt"
["Emulator JAR restored"]="Emulator JAR hersteld"
["Nitro-V3 dist restored"]="Nitro-V3 dist hersteld"
["Octane dist restored"]="Octane dist hersteld"
["Renderer dependencies installed"]="Renderer afhankelijkheden geïnstalleerd"
["No repo updates; skipping parallel builds"]="Geen repo-updates; parallel bouwen overgeslagen"
["Dev mode: skipping builds, syncing configs only"]="Dev modus: builds overgeslagen, alleen configs synchroniseren"
@@ -426,7 +431,7 @@ load_language() {
["Site:"]="Site:"
["Branch:"]="Branch:"
["Emulator:"]="Emulator:"
["Nitro-V3:"]="Nitro-V3:"
["Octane:"]="Octane:"
["Renderer:"]="Renderer:"
["Service:"]="Service:"
["Socket:"]="Socket:"
@@ -454,7 +459,7 @@ load_language() {
["COMPLETED WITH %s ERROR(S)"]="VOLTOOID MET %s FOUT(EN)"
["Duration:"]="Duur:"
["Updates:"]="Updates:"
["Nitro build:"]="Nitro build:"
["Octane build:"]="Octane build:"
["Warnings:"]="Waarschuwingen:"
["Repos:"]="Repos:"
["Yes"]="Ja"
@@ -468,7 +473,7 @@ load_language() {
["Quick Update — current branch"]="Mise à jour rapide — branche actuelle"
["Full Update (choose branch)"]="Mise à jour complète (choisir branche)"
["Emulator Only"]="Émulateur uniquement"
["Nitro-V3 Client Only"]="Client Nitro-V3 uniquement"
["Octane Client Only"]="Client Octane uniquement"
["Renderer Only"]="Rendu uniquement"
["Configs Only"]="Configs uniquement"
["Dev Mode (skip builds, only configs)"]="Mode Dev (sans builds, configs seulement)"
@@ -487,9 +492,11 @@ load_language() {
["View Git Stashes"]="Voir les stashs Git"
["Exit"]="Quitter"
["Flyaway Repair"]="Réparation Flyaway"
["Auto-setup missing repos"]="Installation auto des repos manquants"
["Cleanup old Nitro dirs"]="Nettoyer les anciens répertoires Nitro"
["Rebuild Frontend"]="Reconstruire le Frontend"
["Rebuild Emulator"]="Reconstruire l'Emulateur"
["Select [0-20]"]="Sélectionner [0-21]"
["Select [0-23]"]="Sélectionner [0-23]"
["Press Enter to continue..."]="Appuyez sur Entrée pour continuer..."
["Goodbye!"]="Au revoir !"
["Start update?"]="Lancer la mise à jour ?"
@@ -500,8 +507,8 @@ load_language() {
["OPTIONS:"]="OPTIONS :"
# ── STEP HEADERS ──────────────────────────────────────
["Update & Build Emulator"]="Mise à jour & Construction Émulateur"
["Update Nitro_Render_V3"]="Mise à jour Nitro_Render_V3"
["Update & Build Nitro-V3"]="Mise à jour & Construction Nitro-V3"
["Update Octane-Renderer"]="Mise à jour Octane-Renderer"
["Update & Build Octane"]="Mise à jour & Construction Octane"
["Sync Configurations"]="Synchroniser les configurations"
["Cleanup"]="Nettoyage"
["Set Permissions"]="Définir les permissions"
@@ -553,7 +560,7 @@ load_language() {
["Quick Update — current branch"]="Actualización rápida — rama actual"
["Full Update (choose branch)"]="Actualización completa (elegir rama)"
["Emulator Only"]="Solo Emulador"
["Nitro-V3 Client Only"]="Solo Cliente Nitro-V3"
["Octane Client Only"]="Solo Cliente Octane"
["Renderer Only"]="Solo Renderizador"
["Configs Only"]="Solo Configuraciones"
["Dev Mode (skip builds, only configs)"]="Modo Dev (sin builds, solo configs)"
@@ -572,9 +579,11 @@ load_language() {
["View Git Stashes"]="Ver Stashes Git"
["Exit"]="Salir"
["Flyaway Repair"]="Reparación Flyaway"
["Auto-setup missing repos"]="Auto-instalar repos faltantes"
["Cleanup old Nitro dirs"]="Limpiar directorios Nitro antiguos"
["Rebuild Frontend"]="Reconstruir Frontend"
["Rebuild Emulator"]="Reconstruir Emulador"
["Select [0-20]"]="Seleccionar [0-21]"
["Select [0-23]"]="Seleccionar [0-23]"
["Press Enter to continue..."]="Presione Enter para continuar..."
["Goodbye!"]="¡Hasta luego!"
["Start update?"]="¿Iniciar actualización?"
@@ -601,7 +610,7 @@ load_language() {
["Quick Update — current branch"]="Schnellupdate — aktueller Branch"
["Full Update (choose branch)"]="Vollständiges Update (Branch wählen)"
["Emulator Only"]="Nur Emulator"
["Nitro-V3 Client Only"]="Nur Nitro-V3 Client"
["Octane Client Only"]="Nur Octane Client"
["Renderer Only"]="Nur Renderer"
["Configs Only"]="Nur Konfigurationen"
["Dev Mode (skip builds, only configs)"]="Dev-Modus (ohne Builds, nur Konfigs)"
@@ -620,9 +629,11 @@ load_language() {
["View Git Stashes"]="Git-Stashes anzeigen"
["Exit"]="Beenden"
["Flyaway Repair"]="Flyaway-Reparatur"
["Auto-setup missing repos"]="Fehlende Repos automatisch einrichten"
["Cleanup old Nitro dirs"]="Alte Nitro-Verzeichnisse aufräumen"
["Rebuild Frontend"]="Frontend neu bauen"
["Rebuild Emulator"]="Emulator neu bauen"
["Select [0-20]"]="Auswählen [0-21]"
["Select [0-23]"]="Auswählen [0-23]"
["Press Enter to continue..."]="Drücken Sie Enter zum Fortfahren..."
["Goodbye!"]="Auf Wiedersehen!"
["Start update?"]="Update starten?"
@@ -649,7 +660,7 @@ load_language() {
["Quick Update — current branch"]="Aggiornamento rapido — ramo attuale"
["Full Update (choose branch)"]="Aggiornamento completo (scegli ramo)"
["Emulator Only"]="Solo Emulatore"
["Nitro-V3 Client Only"]="Solo Client Nitro-V3"
["Octane Client Only"]="Solo Client Octane"
["Renderer Only"]="Solo Renderer"
["Configs Only"]="Solo Configurazioni"
["Dev Mode (skip builds, only configs)"]="Modalità Dev (senza build, solo configs)"
@@ -668,9 +679,11 @@ load_language() {
["View Git Stashes"]="Vedi Stash Git"
["Exit"]="Esci"
["Flyaway Repair"]="Riparazione Flyaway"
["Auto-setup missing repos"]="Auto-installazione repo mancanti"
["Cleanup old Nitro dirs"]="Pulisci vecchie cartelle Nitro"
["Rebuild Frontend"]="Ricostruisci Frontend"
["Rebuild Emulator"]="Ricostruisci Emulatore"
["Select [0-20]"]="Seleziona [0-21]"
["Select [0-23]"]="Seleziona [0-23]"
["Press Enter to continue..."]="Premi Invio per continuare..."
["Goodbye!"]="Arrivederci!"
["Start update?"]="Avviare aggiornamento?"
@@ -844,7 +857,7 @@ notify() {
python3 -c "
import json, os
payload = {
'text': '[Nitro Update] ' + os.environ['N_STATUS'],
'text': '[Octane Update] ' + os.environ['N_STATUS'],
'attachments': [{
'color': 'good' if os.environ['N_STATUS'] == 'SUCCESS' else 'danger',
'fields': [
@@ -1169,7 +1182,7 @@ backup_binaries() {
local client_dist="$NITRO_CLIENT/dist"
if [ -d "$client_dist" ]; then
cp -r "$client_dist" "$BINARY_BACKUP_DIR/client-dist" 2>/dev/null || true
ok "Nitro-V3 dist backed up"
ok "Octane dist backed up"
fi
}
@@ -1190,7 +1203,305 @@ restore_binaries() {
local client_dist="$NITRO_CLIENT/dist"
rm -rf "$client_dist" 2>/dev/null || true
cp -r "$BINARY_BACKUP_DIR/client-dist" "$client_dist" 2>/dev/null || true
ok "Nitro-V3 dist restored"
ok "Octane dist restored"
fi
}
# =============================================================================
# OLD NITRO CLEANUP
# =============================================================================
cmd_cleanup_old_nitro() {
step 1 1 "Cleanup Old Nitro"
echo ""
local www_dir="/var/www"
local old_dirs=()
local current_client="$NITRO_CLIENT"
local current_renderer="$NITRO_RENDERER"
# Scan for old Nitro directories that are NOT the current active ones
for candidate in "$www_dir"/Nitro-V3 "$www_dir"/Nitro_Render_V3 "$www_dir"/Nitro_Render "$www_dir"/Nitro "$www_dir"/Nitro-V3-*; do
[ -d "$candidate" ] || continue
[ "$(realpath "$candidate" 2>/dev/null)" = "$(realpath "$current_client" 2>/dev/null)" ] && continue
[ "$(realpath "$candidate" 2>/dev/null)" = "$(realpath "$current_renderer" 2>/dev/null)" ] && continue
old_dirs+=("$candidate")
done
if [ ${#old_dirs[@]} -eq 0 ]; then
ok "No old Nitro directories found"
else
echo -e " ${C_YELLOW}${C_BOLD}Found ${#old_dirs[@]} old Nitro director(y/ies):${C_RESET}"
echo ""
local total_size=0
for d in "${old_dirs[@]}"; do
local sz=$(du -sh "$d" 2>/dev/null | cut -f1)
local files=$(find "$d" -type f 2>/dev/null | wc -l)
echo -e " ${C_RED}✗${C_RESET} ${C_BOLD}$(basename "$d")${C_RESET} ${C_DIM}($sz, $files files)${C_RESET}"
local bytes=$(du -sb "$d" 2>/dev/null | cut -f1)
total_size=$((total_size + bytes))
done
echo ""
echo -e " ${C_CYAN}Total space: $(numfmt --to=iec "$total_size" 2>/dev/null || echo "${total_size}B")${C_RESET}"
echo ""
# ── STEP 1: Migrate symlinks pointing to old dirs ──
echo -e " ${C_BOLD}Checking symlinks...${C_RESET}"
local symlinks_fixed=0
local root_cmd=""
[ "$(id -u)" -eq 0 ] || root_cmd="sudo -n"
for old_dir in "${old_dirs[@]}"; do
local old_name=$(basename "$old_dir")
# Determine the correct new target
local new_target=""
case "$old_name" in
Nitro-V3|Nitro-V3-*) new_target="$current_client" ;;
Nitro_Render_V3|Nitro_Render) new_target="$current_renderer" ;;
esac
[ -z "$new_target" ] && continue
# Find all symlinks on the system pointing to the old dir
while IFS= read -r link; do
[ -z "$link" ] && continue
local link_target=$(readlink -f "$link" 2>/dev/null)
case "$link_target" in
*"$old_name"*|*"$old_dir"*)
echo -e " ${C_GREEN}${E_ARROW}${C_RESET} $link → $new_target"
$root_cmd ln -sfn "$new_target" "$link" 2>/dev/null && symlinks_fixed=$((symlinks_fixed + 1)) || warn "Could not update symlink: %s" "$link"
;;
esac
done < <(find /var/www /etc/nginx /etc/systemd /opt -maxdepth 4 -type l 2>/dev/null)
done
[ "$symlinks_fixed" -gt 0 ] && ok "Updated %s symlink(s)" "$symlinks_fixed" || ok "No symlinks to update"
# ── STEP 2: Update nginx configs referencing old paths ──
echo ""
echo -e " ${C_BOLD}Checking nginx configs...${C_RESET}"
local nginx_fixed=0
for conf in /etc/nginx/sites-enabled/*.conf /etc/nginx/sites-available/*.conf /etc/nginx/conf.d/*.conf; do
[ -f "$conf" ] || continue
local needs_update=false
for old_dir in "${old_dirs[@]}"; do
grep -q "$old_dir" "$conf" 2>/dev/null && needs_update=true && break
done
if [ "$needs_update" = true ]; then
local bak="$conf.bak-nitro-cleanup-$(date +%s)"
$root_cmd cp "$conf" "$bak" 2>/dev/null || true
for old_dir in "${old_dirs[@]}"; do
local old_name=$(basename "$old_dir")
local new_target=""
case "$old_name" in
Nitro-V3|Nitro-V3-*) new_target="$current_client" ;;
Nitro_Render_V3|Nitro_Render) new_target="$current_renderer" ;;
esac
[ -z "$new_target" ] && continue
$root_cmd sed -i "s|$old_dir|$new_target|g" "$conf" 2>/dev/null && nginx_fixed=$((nginx_fixed + 1))
done
echo -e " ${C_GREEN}${E_ARROW}${C_RESET} Updated: $(basename "$conf")"
fi
done
[ "$nginx_fixed" -gt 0 ] && ok "Updated %s nginx reference(s) (backups created)" "$nginx_fixed" || ok "No nginx configs to update"
# ── STEP 3: Update systemd service files referencing old paths ──
echo ""
echo -e " ${C_BOLD}Checking systemd services...${C_RESET}"
local svc_fixed=0
for svc_file in /etc/systemd/system/*.service /etc/systemd/system/emulator.service.d/*.conf; do
[ -f "$svc_file" ] || continue
local needs_update=false
for old_dir in "${old_dirs[@]}"; do
grep -q "$old_dir" "$svc_file" 2>/dev/null && needs_update=true && break
done
if [ "$needs_update" = true ]; then
local bak="$svc_file.bak-nitro-cleanup-$(date +%s)"
$root_cmd cp "$svc_file" "$bak" 2>/dev/null || true
for old_dir in "${old_dirs[@]}"; do
local old_name=$(basename "$old_dir")
local new_target=""
case "$old_name" in
Nitro-V3|Nitro-V3-*) new_target="$current_client" ;;
Nitro_Render_V3|Nitro_Render) new_target="$current_renderer" ;;
esac
[ -z "$new_target" ] && continue
$root_cmd sed -i "s|$old_dir|$new_target|g" "$svc_file" 2>/dev/null && svc_fixed=$((svc_fixed + 1))
done
echo -e " ${C_GREEN}${E_ARROW}${C_RESET} Updated: $(basename "$svc_file")"
fi
done
[ "$svc_fixed" -gt 0 ] && $root_cmd systemctl daemon-reload 2>/dev/null
[ "$svc_fixed" -gt 0 ] && ok "Updated %s service reference(s)" "$svc_fixed" || ok "No systemd services to update"
# ── STEP 4: Check for any other file references ──
echo ""
echo -e " ${C_BOLD}Checking other file references...${C_RESET}"
local other_refs=0
for old_dir in "${old_dirs[@]}"; do
local old_name=$(basename "$old_dir")
local refs=$(grep -rl "$old_name" /var/www/atom-nexst/*.sh /var/www/atom-nexst/.env 2>/dev/null | grep -v "update-Nitrov3.sh" | wc -l)
other_refs=$((other_refs + refs))
if [ "$refs" -gt 0 ]; then
echo -e " ${C_YELLOW}${E_WARN}${C_RESET} $refs file(s) still reference ${C_BOLD}$old_name${C_RESET}"
fi
done
[ "$other_refs" -gt 0 ] && warn "Some files still reference old names — check manually" || ok "No other references found"
# ── STEP 5: Remove old directories ──
echo ""
echo -e " ${C_BOLD}Summary:${C_RESET}"
echo -e " Symlinks updated: ${C_GREEN}$symlinks_fixed${C_RESET}"
echo -e " Nginx refs fixed: ${C_GREEN}$nginx_fixed${C_RESET}"
echo -e " Service refs fixed: ${C_GREEN}$svc_fixed${C_RESET}"
echo -e " Other refs: ${C_YELLOW}$other_refs${C_RESET}"
echo ""
if confirm "Now remove the old directories?"; then
for d in "${old_dirs[@]}"; do
local name=$(basename "$d")
spinner_start "Removing %s..." "$name"
if rm -rf "$d" 2>/dev/null; then
spinner_stop ok
ok "Removed %s" "$name"
else
spinner_stop fail
warn "Failed to remove %s" "$name"
fi
done
ok "Old Nitro cleanup completed"
else
info "Skipped — old directories kept"
fi
fi
# Also clean up old /tmp nitro files
local tmp_count=$(find /tmp -maxdepth 1 -name 'nitro-*' -o -name 'epicnext-*' 2>/dev/null | wc -l)
if [ "$tmp_count" -gt 0 ]; then
echo ""
echo -e " ${C_YELLOW}Found $tmp_count old temp file(s) in /tmp${C_RESET}"
if confirm "Clean /tmp nitro/epicnext files?"; then
rm -rf /tmp/nitro-* /tmp/epicnext-* 2>/dev/null || true
ok "Temp files cleaned"
fi
fi
# Clean up old log files (older than 30 days)
local old_logs=0
if [ -d "$LOG_DIR" ]; then
old_logs=$(find "$LOG_DIR" -name 'update-*.log' -mtime +30 2>/dev/null | wc -l)
if [ "$old_logs" -gt 0 ]; then
echo ""
echo -e " ${C_YELLOW}Found $old_logs old log file(s) (>30 days)${C_RESET}"
if confirm "Clean old logs?"; then
find "$LOG_DIR" -name 'update-*.log' -mtime +30 -exec rm -f {} \; 2>/dev/null || true
ok "Old logs cleaned"
fi
fi
fi
# Clean up old config backups (keep last 5)
if [ -d "$CONFIG_BACKUP_DIR" ]; then
local backup_count=$(find "$CONFIG_BACKUP_DIR" -maxdepth 1 -type d ! -name 'rollback' ! -name 'config-backups' 2>/dev/null | wc -l)
if [ "$backup_count" -gt 5 ]; then
local to_remove=$((backup_count - 5))
echo ""
echo -e " ${C_YELLOW}Found $backup_count config backups (keeping 5, removing $to_remove)${C_RESET}"
if confirm "Prune old config backups?"; then
find "$CONFIG_BACKUP_DIR" -maxdepth 1 -type d ! -name 'rollback' ! -name 'config-backups' -printf '%T@ %p\n' 2>/dev/null | sort -rn | tail -n +6 | sed 's/^[0-9.]* //' | xargs -r rm -rf || true
ok "Old config backups pruned"
fi
fi
fi
# Clean up old SQL backups (keep last 5)
if [ -d "$BACKUP_DIR" ]; then
local sql_count=$(find "$BACKUP_DIR" -maxdepth 1 -name '*.sql' 2>/dev/null | wc -l)
if [ "$sql_count" -gt 5 ]; then
local to_remove=$((sql_count - 5))
echo ""
echo -e " ${C_YELLOW}Found $sql_count SQL backups (keeping 5, removing $to_remove)${C_RESET}"
if confirm "Prune old SQL backups?"; then
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
ok "Old SQL backups pruned"
fi
fi
fi
echo ""
ok "Cleanup check completed"
}
# =============================================================================
# AUTO-SETUP (clone missing repos)
# =============================================================================
auto_setup_missing_repos() {
local cloned=false
if [ ! -d "$NITRO_CLIENT" ] || [ ! -d "$NITRO_CLIENT/.git" ]; then
echo ""
echo -e " ${C_YELLOW}${E_WARN}${C_RESET} ${C_BOLD}Octane client not found at $NITRO_CLIENT${C_RESET}"
info "Cloning Octane client from %s..." "$GIT_REPO_CLIENT"
spinner_start "Cloning Octane client..."
if git clone --depth 1 "$GIT_REPO_CLIENT" "$NITRO_CLIENT" >> "$LOG_FILE" 2>&1; then
spinner_stop ok
ok "Octane client cloned successfully"
cloned=true
else
spinner_stop fail
die "Failed to clone Octane client from %s" "$GIT_REPO_CLIENT"
fi
fi
if [ ! -d "$NITRO_RENDERER" ] || [ ! -d "$NITRO_RENDERER/.git" ]; then
echo ""
echo -e " ${C_YELLOW}${E_WARN}${C_RESET} ${C_BOLD}Octane renderer not found at $NITRO_RENDERER${C_RESET}"
info "Cloning Octane renderer from %s..." "$GIT_REPO_RENDERER"
spinner_start "Cloning Octane renderer..."
if git clone --depth 1 "$GIT_REPO_RENDERER" "$NITRO_RENDERER" >> "$LOG_FILE" 2>&1; then
spinner_stop ok
ok "Octane renderer cloned successfully"
cloned=true
else
spinner_stop fail
die "Failed to clone Octane renderer from %s" "$GIT_REPO_RENDERER"
fi
fi
if [ "$cloned" = true ]; then
echo ""
info "Installing dependencies for cloned repos..."
if [ -d "$NITRO_RENDERER" ] && [ -f "$NITRO_RENDERER/package.json" ]; then
spinner_start "Installing renderer deps..."
yarn_install_repo "$NITRO_RENDERER" --frozen-lockfile --prefer-offline >> "$LOG_FILE" 2>&1 || \
yarn_install_repo "$NITRO_RENDERER" >> "$LOG_FILE" 2>&1 || warn "Renderer yarn install failed"
spinner_stop ok
ok "Renderer dependencies installed"
fi
if [ -d "$NITRO_CLIENT" ] && [ -f "$NITRO_CLIENT/package.json" ]; then
spinner_start "Installing client deps..."
yarn_install_repo "$NITRO_CLIENT" --frozen-lockfile --prefer-offline >> "$LOG_FILE" 2>&1 || \
yarn_install_repo "$NITRO_CLIENT" >> "$LOG_FILE" 2>&1 || warn "Client yarn install failed"
spinner_stop ok
ok "Client dependencies installed"
spinner_start "Building client frontend..."
if yarn_run "$NITRO_CLIENT" build >> "$LOG_FILE" 2>&1; then
spinner_stop ok
ok "Client frontend built"
else
spinner_stop fail
warn "Client build failed — run update to retry"
fi
fi
mkdir -p "$NITRO_SRC_DIR" 2>/dev/null || true
mkdir -p "$NITRO_CLIENT/dist/custom-themes" 2>/dev/null || true
[ ! -f "$NITRO_CLIENT/dist/custom-themes/index.json" ] && echo '{"themes":[]}' > "$NITRO_CLIENT/dist/custom-themes/index.json"
fix_perms
echo ""
ok "Auto-setup completed — all repos ready"
else
ok "All repos already present"
fi
}
@@ -1209,6 +1520,16 @@ preflight_check() {
ok "All commands available"
# Auto-clone missing repos instead of dying
local missing_repos=false
for d in "$NITRO_RENDERER" "$NITRO_CLIENT"; do
[ -d "$d" ] && [ -d "$d/.git" ] || missing_repos=true
done
if [ "$missing_repos" = true ]; then
info "Missing repos detected — running auto-setup..."
auto_setup_missing_repos
fi
for d in "$EMULATOR_REPO" "$EMULATOR_MODULE" "$NITRO_RENDERER" "$NITRO_CLIENT" "$NITRO_SRC_DIR"; do
[ -d "$d" ] || die "Missing dir: $d"
done
@@ -1279,7 +1600,7 @@ EOJ
}
update_renderer() {
step 3 8 "Update Nitro_Render_V3"
step 3 8 "Update Octane-Renderer"
local grc=1
if git_update "$NITRO_RENDERER" "$NITRO_BRANCH"; then
grc=0
@@ -1291,7 +1612,7 @@ update_renderer() {
warn "Renderer update failed (git error)"
return 1
elif [ $grc -eq 0 ]; then
HAD_UPDATES=true; UPDATED_REPOS+=("Nitro_Render_V3")
HAD_UPDATES=true; UPDATED_REPOS+=("Octane-Renderer")
cd "$NITRO_RENDERER"
spinner_start "Installing deps..."
if ! yarn_install_repo "$NITRO_RENDERER" --frozen-lockfile --prefer-offline; then
@@ -1316,7 +1637,7 @@ update_renderer() {
}
update_client() {
step 4 8 "Update & Build Nitro-V3"
step 4 8 "Update & Build Octane"
local grc=1
if git_update "$NITRO_CLIENT" "$NITRO_BRANCH"; then
grc=0
@@ -1324,10 +1645,10 @@ update_client() {
grc=$?
fi
if [ $grc -eq 2 ]; then
warn "Nitro-V3 update failed (git error)"
warn "Octane update failed (git error)"
return 1
elif [ $grc -eq 0 ]; then
HAD_UPDATES=true; NITRO_BUILT=true; UPDATED_REPOS+=("Nitro-V3")
HAD_UPDATES=true; NITRO_BUILT=true; UPDATED_REPOS+=("Octane")
cd "$NITRO_CLIENT"
backup_binaries
ROLLBACK_NEEDED=true
@@ -1335,13 +1656,13 @@ update_client() {
# yarn 1 can "succeed" while leaving node_modules incomplete, so verify
# that the vite build binary actually exists before attempting a build.
if ! yarn_install_repo "$NITRO_CLIENT" --frozen-lockfile --prefer-offline; then
warn "Nitro-V3: yarn install failed — cleaning node_modules and retrying"
warn "Octane: yarn install failed — cleaning node_modules and retrying"
yarn_reset_repo "$NITRO_CLIENT"
yarn_install_repo "$NITRO_CLIENT" || { spinner_stop fail; git_revert_repo "$NITRO_CLIENT"; die "yarn install failed (see: %s)" "$LOG_FILE"; }
fi
cd "$NITRO_CLIENT"
if [ ! -x node_modules/.bin/vite ]; then
warn "Nitro-V3: vite missing after install — resetting repo cache and doing full install"
warn "Octane: vite missing after install — resetting repo cache and doing full install"
# Parallel yarn installs can corrupt a shared cache; resetting the
# repo's own cache folder guarantees a clean fetch from the registry.
yarn_reset_repo "$NITRO_CLIENT"
@@ -1359,7 +1680,7 @@ update_client() {
die "yarn build failed (see: %s)" "$LOG_FILE"
fi
else
info "Nitro-V3: already up to date"
info "Octane: already up to date"
fi
mkdir -p "$NITRO_CLIENT/dist/custom-themes"
[ ! -f "$NITRO_CLIENT/dist/custom-themes/index.json" ] && echo '{"themes":[]}' > "$NITRO_CLIENT/dist/custom-themes/index.json"
@@ -1678,7 +1999,7 @@ show_summary() {
echo -e " ${C_CYAN}╠══════════════════════════════════════════════════════════════════╣${C_RESET}"
printf " ${C_CYAN}║${C_RESET} $(_t "Duration:") %-46s${C_CYAN}║${C_RESET}\n" "$ef"
printf " ${C_CYAN}║${C_RESET} $(_t "Updates:") %-46s${C_CYAN}║${C_RESET}\n" "$([ "$HAD_UPDATES" = true ] && echo "$(_t "Yes")" || echo "$(_t "No")")"
printf " ${C_CYAN}║${C_RESET} $(_t "Nitro build:") %-46s${C_CYAN}║${C_RESET}\n" "$([ "$NITRO_BUILT" = true ] && echo "$(_t "Yes")" || echo "$(_t "No")")"
printf " ${C_CYAN}║${C_RESET} $(_t "Octane build:") %-46s${C_CYAN}║${C_RESET}\n" "$([ "$NITRO_BUILT" = true ] && echo "$(_t "Yes")" || echo "$(_t "No")")"
printf " ${C_CYAN}║${C_RESET} $(_t "Warnings:") %-46s${C_CYAN}║${C_RESET}\n" "$WARNINGS"
[ ${#UPDATED_REPOS[@]} -gt 0 ] && printf " ${C_CYAN}║${C_RESET} $(_t "Repos:") %-46s${C_CYAN}║${C_RESET}\n" "${UPDATED_REPOS[*]}"
echo -e " ${C_CYAN}╚══════════════════════════════════════════════════════════════════╝${C_RESET}"
@@ -1827,7 +2148,7 @@ cmd_status() {
done; box_bottom 56
echo ""
box_top "GIT REPOS" 56
for re in "Emulator:$EMULATOR_REPO" "Nitro-V3:$NITRO_CLIENT" "Render:$NITRO_RENDERER"; do
for re in "Emulator:$EMULATOR_REPO" "Octane:$NITRO_CLIENT" "Render:$NITRO_RENDERER"; do
local nm="${re%%:*}" pa="${re##*:}"
[ -d "$pa/.git" ] || continue
local br=$(cd "$pa" && git branch --show-current 2>/dev/null || echo "?")
@@ -1892,7 +2213,7 @@ cmd_health() {
fi
done
echo -e "\n ${C_BOLD}$(_t "Directories:")${C_RESET}"
checkw "Emulator" test -d "$EMULATOR_MODULE"; checkw "Nitro-V3" test -d "$NITRO_CLIENT"; checkw "Renderer" test -d "$NITRO_RENDERER"
checkw "Emulator" test -d "$EMULATOR_MODULE"; checkw "Octane" test -d "$NITRO_CLIENT"; checkw "Renderer" test -d "$NITRO_RENDERER"
checkw "$(_t "Gamedata config")" test -d "$GAMEDATA_CONF_DIR"; checkw "$(_t "Backup dir")" test -d "$BACKUP_DIR"
echo -e "\n ${C_BOLD}$(_t "Services:")${C_RESET}"
checkw "MariaDB" service_active mariadb; checkw "Nginx" service_active nginx; checkw "Redis" service_active redis-server
@@ -2046,6 +2367,21 @@ cmd_flyaway_repair() {
release_lock
}
# =============================================================================
# AUTO-SETUP COMMAND
# =============================================================================
cmd_setup() {
step 1 1 "Setup"
echo ""
acquire_lock
info "Site: %s | Branch: %s | Mode: %s" "${NITRO_SITE_URL:-?}" "$NITRO_BRANCH" "auto-setup"
info "Log: %s" "$LOG_FILE"
auto_setup_missing_repos
release_lock
}
# =============================================================================
# SERVICES
# =============================================================================
@@ -2109,7 +2445,7 @@ cmd_config() {
box_kv "Site:" "${NITRO_SITE_URL:-?}" 56
box_kv "Branch:" "$NITRO_BRANCH" 56
box_kv "Emulator:" "$EMULATOR_DIR" 56
box_kv "Nitro-V3:" "$NITRO_CLIENT" 56
box_kv "Octane:" "$NITRO_CLIENT" 56
box_kv "Renderer:" "$NITRO_RENDERER" 56
box_kv "Database:" "$DB_NAME @ $DB_HOST:$DB_PORT" 56
box_kv "Service:" "$EMULATOR_SERVICE" 56
@@ -2169,7 +2505,7 @@ cmd_clean() {
cmd_gitlog() {
step 1 1 "Git Commit History"
echo ""
echo -e " ${C_BOLD}1)${C_RESET} $(_t "Emulator") ${C_BOLD}2)${C_RESET} $(_t "Nitro-V3") ${C_BOLD}3)${C_RESET} $(_t "Renderer")"
echo -e " ${C_BOLD}1)${C_RESET} $(_t "Emulator") ${C_BOLD}2)${C_RESET} $(_t "Octane") ${C_BOLD}3)${C_RESET} $(_t "Renderer")"
echo -en "\n $(_t "Select:") "; local c; read -rt 30 c
local repo=""
case "$c" in 1) repo="$EMULATOR_REPO" ;; 2) repo="$NITRO_CLIENT" ;; 3) repo="$NITRO_RENDERER" ;; *) return ;; esac
@@ -2303,15 +2639,15 @@ 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} SMaRT v${SCRIPT_VERSION} — Emulator / Nitro-V3 / Nitro-V3-Render${C_CYAN} ║"
echo -e " ║ ${C_GOLD}${C_BOLD} SMaRT v${SCRIPT_VERSION} — Emulator / Octane / Octane-Renderer${C_CYAN} ║"
echo -e " ║ ${C_WHITE}${C_BOLD} Updater & Manager by Remco — epicnabbo.nl${C_CYAN} ║"
echo " ╠═══════════════════════════════════════════════════════════════════════════╣"
echo -e " ║ ${C_DIM}$(_t "Branch:") ${C_CYAN}${NITRO_BRANCH}${C_DIM} (${#branches[@]} $(_t "branches")) │ $(date '+%H:%M')${C_CYAN} ║"
@@ -2322,7 +2658,7 @@ cmd_interactive() {
echo -e " ${C_GREEN}${C_BOLD}1)${C_RESET} ${E_ROCKET} $(_t "Quick Update — current branch")"
echo -e " ${C_GREEN}${C_BOLD}2)${C_RESET} ${E_BOLT} $(_t "Full Update (choose branch)")"
echo -e " ${C_GREEN}${C_BOLD}3)${C_RESET} ${E_GEAR} $(_t "Emulator Only")"
echo -e " ${C_GREEN}${C_BOLD}4)${C_RESET} ${E_GEAR} $(_t "Nitro-V3 Client Only")"
echo -e " ${C_GREEN}${C_BOLD}4)${C_RESET} ${E_GEAR} $(_t "Octane Client Only")"
echo -e " ${C_GREEN}${C_BOLD}5)${C_RESET} ${E_GEAR} $(_t "Renderer Only")"
echo -e " ${C_GREEN}${C_BOLD}6)${C_RESET} ${E_GEAR} $(_t "Configs Only")"
echo -e " ${C_GREEN}${C_BOLD}19)${C_RESET} ${E_BOLT} $(_t "Dev Mode (skip builds, only configs)")"
@@ -2344,10 +2680,12 @@ cmd_interactive() {
echo -e " ${C_BLUE}${C_BOLD}18)${C_RESET} ${E_CLOCK} $(_t "Cron Scheduler")"
echo -e " ${C_BLUE}${C_BOLD}20)${C_RESET} ${E_GIT} $(_t "View Git Stashes")"
echo -e " ${C_RED}${C_BOLD}21)${C_RESET} ${E_WRENCH} $(_t "Flyaway Repair")"
echo -e " ${C_GREEN}${C_BOLD}22)${C_RESET} ${E_ROCKET} $(_t "Auto-setup missing repos")"
echo -e " ${C_YELLOW}${C_BOLD}23)${C_RESET} ${E_BROOM} $(_t "Cleanup old Nitro dirs")"
echo ""
echo -e " ${C_RED}${C_BOLD}0)${C_RESET} $(_t "Exit")"
echo ""
echo -en " ${C_CYAN}${C_BOLD}$(_t "Select [0-21]")${C_RESET}: "
echo -en " ${C_CYAN}${C_BOLD}$(_t "Select [0-23]")${C_RESET}: "
local choice; read -rt 30 choice
case "$choice" in
@@ -2386,6 +2724,8 @@ cmd_interactive() {
19) SELECTIVE_UPDATE="dev"; (pick_branch_and_update) || warn "Dev mode had errors" ;;
20) (cmd_stash) ;;
21) (cmd_flyaway_repair) ;;
22) (cmd_setup) ;;
23) (cmd_cleanup_old_nitro) ;;
0|q|Q) echo -e "\n ${C_GREEN}$(_t "Goodbye!")${C_RESET}"; cursor_show; exit 0 ;;
*) warn "Invalid selection" ;;
esac
@@ -2401,7 +2741,7 @@ cmd_interactive() {
# =============================================================================
show_help() {
echo ""
echo -e " ${C_GOLD}${C_BOLD}$(_t "SMaRT — Emulator / Nitro-V3 / Nitro-V3-Render Updater & Manager")${C_RESET}"
echo -e " ${C_GOLD}${C_BOLD}$(_t "SMaRT — Emulator / Octane / Octane-Renderer 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}$(_t "USAGE:")${C_RESET} $SCRIPT_NAME <command> [options]"
@@ -2424,6 +2764,8 @@ show_help() {
echo -e " ${C_GREEN}schedule${C_RESET} $(_t "Cron setup")"
echo -e " ${C_GREEN}stash${C_RESET} $(_t "View git stashes")"
echo -e " ${C_GREEN}repair${C_RESET} $(_t "Flyaway Repair")"
echo -e " ${C_GREEN}setup${C_RESET} $(_t "Auto-setup missing repos")"
echo -e " ${C_GREEN}cleanup-nitro${C_RESET} $(_t "Cleanup old Nitro dirs")"
echo ""
echo -e " ${C_BOLD}$(_t "OPTIONS:")${C_RESET}"
echo -e " ${C_CYAN}--branch, -b${C_RESET} $(_t "Branch (auto-detects)")"
@@ -2460,6 +2802,8 @@ main() {
clean|cl) cmd="clean" ;;
stash|stashes) cmd="stash" ;;
repair|flyaway) cmd="repair" ;;
setup|init) cmd="setup" ;;
cleanup-nitro|oldnitro) cmd="cleanup-nitro" ;;
help|-h|--help) cmd="help" ;;
version|-V|--version) echo "v${SCRIPT_VERSION} (build ${SCRIPT_BUILD})"; exit 0 ;;
--branch|-b) shift; NITRO_BRANCH="$1" ;;
@@ -2535,6 +2879,8 @@ main() {
schedule) cmd_schedule ;;
stash) cmd_stash ;;
repair) cmd_flyaway_repair ;;
setup) cmd_setup ;;
cleanup-nitro) cmd_cleanup_old_nitro ;;
help) show_help ;;
esac