update nice visuel
This commit is contained in:
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deprecated alias — use docker-db-export.sh on prod, or local-db-export.sh on your laptop.
|
||||
# This wrapper keeps the old name for existing docs / muscle memory.
|
||||
set -euo pipefail
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
if [[ -f "$DIR/../docker-compose.yml" ]] && command -v docker >/dev/null 2>&1 \
|
||||
&& docker compose -f "$DIR/../docker-compose.yml" ps -q casegambling >/dev/null 2>&1; then
|
||||
echo "Note: forwarding to docker-db-export.sh (Docker detected)." >&2
|
||||
exec "$DIR/docker-db-export.sh" "$@"
|
||||
fi
|
||||
echo "Note: forwarding to local-db-export.sh." >&2
|
||||
exec "$DIR/local-db-export.sh" "$@"
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Deprecated alias — use docker-db-import.sh (Docker) or local-db-import.sh (laptop).
|
||||
set -euo pipefail
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
if [[ -f "$DIR/../docker-compose.yml" ]] && command -v docker >/dev/null 2>&1 \
|
||||
&& docker compose -f "$DIR/../docker-compose.yml" ps -aq casegambling >/dev/null 2>&1; then
|
||||
echo "Note: forwarding to docker-db-import.sh (Docker detected)." >&2
|
||||
exec "$DIR/docker-db-import.sh" "$@"
|
||||
fi
|
||||
echo "Note: forwarding to local-db-import.sh." >&2
|
||||
exec "$DIR/local-db-import.sh" "$@"
|
||||
@@ -5,30 +5,38 @@
|
||||
# Usage:
|
||||
# ./scripts/local-db-import.sh ./backups/casegambling-YYYYMMDD-HHMMSS
|
||||
# ./scripts/local-db-import.sh ./backups/casegambling-YYYYMMDD-HHMMSS.tar.gz
|
||||
# ./scripts/local-db-import.sh ./backups/….tar.gz <username> # player-only merge
|
||||
#
|
||||
# Typical flow (prod → laptop):
|
||||
# # on prod:
|
||||
# ./scripts/docker-db-export.sh
|
||||
# # copy the .tar.gz here, then:
|
||||
# ./scripts/local-db-import.sh ./backups/casegambling-….tar.gz
|
||||
# # or only one player into the existing local DB:
|
||||
# ./scripts/local-db-import.sh ./backups/casegambling-….tar.gz SomePlayer
|
||||
#
|
||||
# Stop `npm run dev` before importing so SQLite is not locked.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
MERGE_PLAYER_SCRIPT="$ROOT/scripts/merge-player-db.sh"
|
||||
|
||||
if [[ -z "${1:-}" ]]; then
|
||||
echo "Usage: $0 <backup-dir-or-tar.gz>" >&2
|
||||
if [[ -z "${1:-}" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
echo "Usage: $0 <backup-dir-or-tar.gz> [username]" >&2
|
||||
echo "Example: $0 ./backups/casegambling-20260116-203000.tar.gz" >&2
|
||||
echo " $0 ./backups/casegambling-20260116-203000.tar.gz SomePlayer" >&2
|
||||
echo "Create a backup from Docker: ./scripts/docker-db-export.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_ARG="$1"
|
||||
USERNAME="${2:-}"
|
||||
|
||||
# Resolve backup path from the caller's cwd
|
||||
if [[ "$1" = /* ]]; then
|
||||
SRC="$1"
|
||||
if [[ "$BACKUP_ARG" = /* ]]; then
|
||||
SRC="$BACKUP_ARG"
|
||||
else
|
||||
SRC="$(pwd)/$1"
|
||||
SRC="$(pwd)/$BACKUP_ARG"
|
||||
fi
|
||||
|
||||
LOCAL_DB="${LOCAL_DB:-$ROOT/server/prisma/dev.db}"
|
||||
@@ -49,6 +57,25 @@ is_archive() {
|
||||
esac
|
||||
}
|
||||
|
||||
copy_player_avatar() {
|
||||
local avatar_url="$1"
|
||||
local uploads_src="$2"
|
||||
local uploads_dst="$3"
|
||||
[[ -z "$avatar_url" || ! -d "$uploads_src" ]] && return 0
|
||||
local rel="${avatar_url#/}"
|
||||
rel="${rel#uploads/}"
|
||||
rel="${rel#./}"
|
||||
case "$rel" in
|
||||
''|http:*|https:*|*..*) return 0 ;;
|
||||
esac
|
||||
local src_file="$uploads_src/$rel"
|
||||
if [[ -f "$src_file" ]]; then
|
||||
mkdir -p "$uploads_dst/$(dirname "$rel")"
|
||||
cp -f "$src_file" "$uploads_dst/$rel"
|
||||
echo "==> Copied avatar upload: $rel"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ -f "$SRC" ]] && is_archive "$SRC"; then
|
||||
echo "==> Extracting $(basename "$SRC")"
|
||||
TMP="$(mktemp -d)"
|
||||
@@ -84,6 +111,35 @@ if [[ -z "$DB" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Player-only merge into existing local DB ─────────────────────────────────
|
||||
if [[ -n "$USERNAME" ]]; then
|
||||
if [[ ! -f "$LOCAL_DB" ]]; then
|
||||
echo "Error: local DB not found: $LOCAL_DB" >&2
|
||||
echo "Tip: run a full import first (without username), or start the app once." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -x "$MERGE_PLAYER_SCRIPT" ]]; then
|
||||
echo "Error: merge helper missing or not executable: $MERGE_PLAYER_SCRIPT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Drop WAL/SHM so we merge against the real file contents
|
||||
rm -f "${LOCAL_DB}-wal" "${LOCAL_DB}-shm"
|
||||
|
||||
"$MERGE_PLAYER_SCRIPT" "$DB" "$LOCAL_DB" "$USERNAME"
|
||||
AVATAR_URL="$(sqlite3 "$DB" "SELECT avatarUrl FROM User WHERE username = '${USERNAME//\'/\'\'}' LIMIT 1;" 2>/dev/null || true)"
|
||||
if [[ -d "$SRC/uploads" ]]; then
|
||||
copy_player_avatar "${AVATAR_URL:-}" "$SRC/uploads" "$LOCAL_UPLOADS"
|
||||
fi
|
||||
|
||||
echo "==> Done (player-only)."
|
||||
echo " db: $LOCAL_DB"
|
||||
echo " Tip: stop npm run dev before import if the DB was locked; then restart:"
|
||||
echo " npm run dev"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Full import (replace local DB + uploads) ─────────────────────────────────
|
||||
mkdir -p "$(dirname "$LOCAL_DB")"
|
||||
|
||||
echo "==> Importing database → $LOCAL_DB"
|
||||
|
||||
Executable
+251
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env bash
|
||||
# Merge one player's rows from a source SQLite DB into a target SQLite DB.
|
||||
#
|
||||
# Usage (sourced or executed):
|
||||
# ./scripts/merge-player-db.sh <source.db> <target.db> <username>
|
||||
#
|
||||
# Replaces any existing target user with the same username.
|
||||
# Copies (when present in both DBs): User, InventoryItem, Transaction,
|
||||
# PaymentOrder, CaseKeyProgress, CatalogEntry, PrestigeLog, UserAchievement.
|
||||
# Skips multiplayer state (Jackpot*/Duel*).
|
||||
# Tolerates older backups missing newer tables/columns (e.g. PaymentOrder).
|
||||
#
|
||||
# Requires matching Item / Case / Achievement ids in both DBs (same catalog lineage).
|
||||
# Requires sqlite3.
|
||||
set -euo pipefail
|
||||
|
||||
SRC_DB="${1:-}"
|
||||
DST_DB="${2:-}"
|
||||
USERNAME="${3:-}"
|
||||
|
||||
if [[ -z "$SRC_DB" || -z "$DST_DB" || -z "$USERNAME" ]]; then
|
||||
echo "Usage: $0 <source.db> <target.db> <username>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$SRC_DB" ]]; then
|
||||
echo "Error: source DB not found: $SRC_DB" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$DST_DB" ]]; then
|
||||
echo "Error: target DB not found: $DST_DB" >&2
|
||||
echo "Tip: run a full import once first, or start the app so the DB exists." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v sqlite3 >/dev/null 2>&1; then
|
||||
echo "Error: sqlite3 is required for player-only import" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sql_quote() {
|
||||
local s="$1"
|
||||
s="${s//\'/\'\'}"
|
||||
printf "'%s'" "$s"
|
||||
}
|
||||
|
||||
table_exists() {
|
||||
local db="$1"
|
||||
local table="$2"
|
||||
local n
|
||||
n="$(sqlite3 "$db" "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=$(sql_quote "$table");")"
|
||||
[[ "$n" -gt 0 ]]
|
||||
}
|
||||
|
||||
# Column names for a table (space-separated), excluding names passed after $2
|
||||
table_cols() {
|
||||
local db="$1"
|
||||
local table="$2"
|
||||
shift 2
|
||||
local -A skip=()
|
||||
local e col
|
||||
for e in "$@"; do
|
||||
skip["$e"]=1
|
||||
done
|
||||
while IFS='|' read -r _ col _; do
|
||||
[[ -n "$col" && -z "${skip[$col]:-}" ]] && printf '%s\n' "$col"
|
||||
done < <(sqlite3 -separator '|' "$db" "PRAGMA table_info($(sql_quote "$table"));")
|
||||
}
|
||||
|
||||
# Intersection of columns present in BOTH DBs, preserving destination order.
|
||||
common_cols() {
|
||||
local table="$1"
|
||||
shift
|
||||
local -A src_set=()
|
||||
local col
|
||||
while IFS= read -r col; do
|
||||
[[ -n "$col" ]] && src_set["$col"]=1
|
||||
done < <(table_cols "$SRC_DB" "$table" "$@")
|
||||
|
||||
local -a out=()
|
||||
while IFS= read -r col; do
|
||||
[[ -n "$col" && -n "${src_set[$col]:-}" ]] && out+=("$col")
|
||||
done < <(table_cols "$DST_DB" "$table" "$@")
|
||||
|
||||
local IFS=', '
|
||||
echo "${out[*]}"
|
||||
}
|
||||
|
||||
count_rows() {
|
||||
local table="$1"
|
||||
local qtable="$1"
|
||||
[[ "$table" == "Transaction" ]] && qtable='"Transaction"'
|
||||
if table_exists "$SRC_DB" "$table"; then
|
||||
sqlite3 "$SRC_DB" "SELECT COUNT(*) FROM $qtable WHERE userId = $SRC_UID;"
|
||||
else
|
||||
echo "skip"
|
||||
fi
|
||||
}
|
||||
|
||||
SRC_UID="$(sqlite3 "$SRC_DB" "SELECT id FROM User WHERE username = $(sql_quote "$USERNAME") LIMIT 1;")"
|
||||
if [[ -z "$SRC_UID" ]]; then
|
||||
echo "Error: no user with username '$USERNAME' in source DB" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "==> Merging player '$USERNAME' (source id=$SRC_UID)"
|
||||
echo " source: $SRC_DB"
|
||||
echo " target: $DST_DB"
|
||||
|
||||
N_INV="$(count_rows InventoryItem)"
|
||||
N_TX="$(count_rows Transaction)"
|
||||
N_PAY="$(count_rows PaymentOrder)"
|
||||
N_KEY="$(count_rows CaseKeyProgress)"
|
||||
N_CAT="$(count_rows CatalogEntry)"
|
||||
N_PRE="$(count_rows PrestigeLog)"
|
||||
N_ACH="$(count_rows UserAchievement)"
|
||||
echo " rows: inventory=$N_INV tx=$N_TX payments=$N_PAY keys=$N_KEY catalog=$N_CAT prestige=$N_PRE achievements=$N_ACH"
|
||||
|
||||
USER_COLS="$(common_cols User id)"
|
||||
if [[ -z "$USER_COLS" ]]; then
|
||||
echo "Error: no common User columns between source and target" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INV_COLS="$(common_cols InventoryItem id userId)"
|
||||
TX_COLS="$(common_cols Transaction id userId)"
|
||||
if [[ -z "$INV_COLS" || -z "$TX_COLS" ]]; then
|
||||
echo "Error: InventoryItem / Transaction schema mismatch" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PAY_COLS=""
|
||||
if table_exists "$SRC_DB" PaymentOrder && table_exists "$DST_DB" PaymentOrder; then
|
||||
PAY_COLS="$(common_cols PaymentOrder userId)"
|
||||
fi
|
||||
KEY_COLS=""
|
||||
table_exists "$SRC_DB" CaseKeyProgress && table_exists "$DST_DB" CaseKeyProgress && KEY_COLS="$(common_cols CaseKeyProgress id userId)"
|
||||
CAT_COLS=""
|
||||
table_exists "$SRC_DB" CatalogEntry && table_exists "$DST_DB" CatalogEntry && CAT_COLS="$(common_cols CatalogEntry id userId)"
|
||||
PRE_COLS=""
|
||||
table_exists "$SRC_DB" PrestigeLog && table_exists "$DST_DB" PrestigeLog && PRE_COLS="$(common_cols PrestigeLog id userId)"
|
||||
ACH_COLS=""
|
||||
table_exists "$SRC_DB" UserAchievement && table_exists "$DST_DB" UserAchievement && ACH_COLS="$(common_cols UserAchievement id userId)"
|
||||
|
||||
SQL_EXTRA_DELETE=""
|
||||
SQL_EXTRA_INSERT=""
|
||||
|
||||
if [[ -n "$PAY_COLS" ]]; then
|
||||
SQL_EXTRA_DELETE+="
|
||||
DELETE FROM PaymentOrder
|
||||
WHERE id IN (SELECT id FROM src.PaymentOrder WHERE userId = $SRC_UID);
|
||||
"
|
||||
SQL_EXTRA_INSERT+="
|
||||
INSERT INTO PaymentOrder ($PAY_COLS, userId)
|
||||
SELECT $PAY_COLS, (SELECT newId FROM _merge_uid)
|
||||
FROM src.PaymentOrder WHERE userId = $SRC_UID;
|
||||
"
|
||||
else
|
||||
echo " note: PaymentOrder absent in backup — skipped (osu top-up orders)"
|
||||
fi
|
||||
|
||||
if [[ -n "$KEY_COLS" ]]; then
|
||||
SQL_EXTRA_INSERT+="
|
||||
INSERT INTO CaseKeyProgress (userId, $KEY_COLS)
|
||||
SELECT (SELECT newId FROM _merge_uid), $KEY_COLS
|
||||
FROM src.CaseKeyProgress WHERE userId = $SRC_UID;
|
||||
"
|
||||
fi
|
||||
|
||||
if [[ -n "$CAT_COLS" ]]; then
|
||||
SQL_EXTRA_INSERT+="
|
||||
INSERT INTO CatalogEntry (userId, $CAT_COLS)
|
||||
SELECT (SELECT newId FROM _merge_uid), $CAT_COLS
|
||||
FROM src.CatalogEntry WHERE userId = $SRC_UID;
|
||||
"
|
||||
fi
|
||||
|
||||
if [[ -n "$PRE_COLS" ]]; then
|
||||
SQL_EXTRA_INSERT+="
|
||||
INSERT INTO PrestigeLog (userId, $PRE_COLS)
|
||||
SELECT (SELECT newId FROM _merge_uid), $PRE_COLS
|
||||
FROM src.PrestigeLog WHERE userId = $SRC_UID;
|
||||
"
|
||||
fi
|
||||
|
||||
if [[ -n "$ACH_COLS" ]]; then
|
||||
SQL_EXTRA_INSERT+="
|
||||
INSERT INTO UserAchievement (userId, $ACH_COLS)
|
||||
SELECT (SELECT newId FROM _merge_uid), $ACH_COLS
|
||||
FROM src.UserAchievement WHERE userId = $SRC_UID;
|
||||
"
|
||||
fi
|
||||
|
||||
SQL_CLEANUP=""
|
||||
table_exists "$DST_DB" JackpotRound && SQL_CLEANUP+="
|
||||
UPDATE JackpotRound SET winnerUserId = NULL
|
||||
WHERE winnerUserId IN (SELECT id FROM User WHERE username = $(sql_quote "$USERNAME"));
|
||||
"
|
||||
table_exists "$DST_DB" DuelRoom && SQL_CLEANUP+="
|
||||
UPDATE DuelRoom SET winnerUserId = NULL
|
||||
WHERE winnerUserId IN (SELECT id FROM User WHERE username = $(sql_quote "$USERNAME"));
|
||||
DELETE FROM DuelRoom
|
||||
WHERE creatorId IN (SELECT id FROM User WHERE username = $(sql_quote "$USERNAME"));
|
||||
"
|
||||
table_exists "$DST_DB" JackpotDeposit && SQL_CLEANUP+="
|
||||
DELETE FROM JackpotDeposit
|
||||
WHERE userId IN (SELECT id FROM User WHERE username = $(sql_quote "$USERNAME"));
|
||||
"
|
||||
table_exists "$DST_DB" DuelDeposit && SQL_CLEANUP+="
|
||||
DELETE FROM DuelDeposit
|
||||
WHERE userId IN (SELECT id FROM User WHERE username = $(sql_quote "$USERNAME"));
|
||||
"
|
||||
|
||||
sqlite3 "$DST_DB" <<SQL
|
||||
PRAGMA foreign_keys = ON;
|
||||
ATTACH DATABASE $(sql_quote "$SRC_DB") AS src;
|
||||
|
||||
BEGIN;
|
||||
|
||||
$SQL_CLEANUP
|
||||
DELETE FROM User WHERE username = $(sql_quote "$USERNAME");
|
||||
|
||||
$SQL_EXTRA_DELETE
|
||||
|
||||
INSERT INTO User ($USER_COLS)
|
||||
SELECT $USER_COLS
|
||||
FROM src.User WHERE id = $SRC_UID;
|
||||
|
||||
CREATE TEMP TABLE _merge_uid AS
|
||||
SELECT id AS newId FROM User WHERE username = $(sql_quote "$USERNAME") LIMIT 1;
|
||||
|
||||
INSERT INTO InventoryItem (userId, $INV_COLS)
|
||||
SELECT (SELECT newId FROM _merge_uid), $INV_COLS
|
||||
FROM src.InventoryItem WHERE userId = $SRC_UID;
|
||||
|
||||
INSERT INTO "Transaction" (userId, $TX_COLS)
|
||||
SELECT (SELECT newId FROM _merge_uid), $TX_COLS
|
||||
FROM src."Transaction" WHERE userId = $SRC_UID;
|
||||
|
||||
$SQL_EXTRA_INSERT
|
||||
|
||||
DROP TABLE _merge_uid;
|
||||
|
||||
COMMIT;
|
||||
DETACH DATABASE src;
|
||||
SQL
|
||||
|
||||
NEW_UID="$(sqlite3 "$DST_DB" "SELECT id FROM User WHERE username = $(sql_quote "$USERNAME") LIMIT 1;")"
|
||||
echo "==> Player merged as target id=$NEW_UID"
|
||||
echo " (jackpot/duel deposits & rooms not imported)"
|
||||
@@ -3,8 +3,9 @@
|
||||
# Run this on the machine that runs docker compose.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/docker-db-import.sh ./backups/casegambling-YYYYMMDD-HHMMSS
|
||||
# ./scripts/docker-db-import.sh ./backups/casegambling-YYYYMMDD-HHMMSS.tar.gz
|
||||
# ./scripts/xdocker-db-import.sh ./backups/casegambling-YYYYMMDD-HHMMSS
|
||||
# ./scripts/xdocker-db-import.sh ./backups/casegambling-YYYYMMDD-HHMMSS.tar.gz
|
||||
# ./scripts/xdocker-db-import.sh ./backups/….tar.gz <username> # player-only merge
|
||||
#
|
||||
# Expects a backup from docker-db-export.sh or local-db-export.sh
|
||||
# (prod.db or dev.db + uploads/).
|
||||
@@ -24,18 +25,24 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${1:-}" ]]; then
|
||||
echo "Usage: $0 <backup-dir-or-tar.gz>" >&2
|
||||
MERGE_PLAYER_SCRIPT="$ROOT/scripts/merge-player-db.sh"
|
||||
|
||||
if [[ -z "${1:-}" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
echo "Usage: $0 <backup-dir-or-tar.gz> [username]" >&2
|
||||
echo "Example: $0 ./backups/casegambling-20260116-203000.tar.gz" >&2
|
||||
echo " $0 ./backups/casegambling-20260116-203000.tar.gz SomePlayer" >&2
|
||||
echo "Create a backup first: ./scripts/docker-db-export.sh (or local-db-export.sh)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_ARG="$1"
|
||||
USERNAME="${2:-}"
|
||||
|
||||
# Resolve backup path from the caller's cwd (before any cd)
|
||||
if [[ "$1" = /* ]]; then
|
||||
SRC="$1"
|
||||
if [[ "$BACKUP_ARG" = /* ]]; then
|
||||
SRC="$BACKUP_ARG"
|
||||
else
|
||||
SRC="$(pwd)/$1"
|
||||
SRC="$(pwd)/$BACKUP_ARG"
|
||||
fi
|
||||
|
||||
cd "$ROOT"
|
||||
@@ -52,10 +59,14 @@ fi
|
||||
SERVICE="${SERVICE:-casegambling}"
|
||||
|
||||
TMP=""
|
||||
WORK=""
|
||||
cleanup() {
|
||||
if [[ -n "$TMP" && -d "$TMP" ]]; then
|
||||
rm -rf "$TMP"
|
||||
fi
|
||||
if [[ -n "$WORK" && -d "$WORK" ]]; then
|
||||
rm -rf "$WORK"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
@@ -66,6 +77,25 @@ is_archive() {
|
||||
esac
|
||||
}
|
||||
|
||||
copy_player_avatar_docker() {
|
||||
local avatar_url="$1"
|
||||
local uploads_src="$2"
|
||||
[[ -z "$avatar_url" || ! -d "$uploads_src" ]] && return 0
|
||||
local rel="${avatar_url#/}"
|
||||
rel="${rel#uploads/}"
|
||||
rel="${rel#./}"
|
||||
case "$rel" in
|
||||
''|http:*|https:*|*..*) return 0 ;;
|
||||
esac
|
||||
local src_file="$uploads_src/$rel"
|
||||
if [[ -f "$src_file" ]]; then
|
||||
"${COMPOSE[@]}" run --rm --no-deps --entrypoint sh "$SERVICE" -c \
|
||||
"mkdir -p /app/uploads/$(dirname "$rel")" >/dev/null
|
||||
"${COMPOSE[@]}" cp "$src_file" "$SERVICE:/app/uploads/$rel"
|
||||
echo "==> Copied avatar upload: $rel"
|
||||
fi
|
||||
}
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "Error: docker not found" >&2
|
||||
exit 1
|
||||
@@ -109,6 +139,58 @@ fi
|
||||
echo "==> Ensuring compose service exists"
|
||||
"${COMPOSE[@]}" up -d --no-start "$SERVICE" >/dev/null
|
||||
|
||||
# ── Player-only merge into existing Docker DB ────────────────────────────────
|
||||
if [[ -n "$USERNAME" ]]; then
|
||||
if [[ ! -x "$MERGE_PLAYER_SCRIPT" ]]; then
|
||||
echo "Error: merge helper missing or not executable: $MERGE_PLAYER_SCRIPT" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v sqlite3 >/dev/null 2>&1; then
|
||||
echo "Error: sqlite3 is required on the host for player-only import" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Stopping $SERVICE (safe SQLite merge)"
|
||||
"${COMPOSE[@]}" stop "$SERVICE" >/dev/null 2>&1 || true
|
||||
|
||||
WORK="$(mktemp -d)"
|
||||
TARGET_DB="$WORK/prod.db"
|
||||
|
||||
echo "==> Fetching current /data/prod.db"
|
||||
if ! "${COMPOSE[@]}" cp "$SERVICE:/data/prod.db" "$TARGET_DB" 2>/dev/null; then
|
||||
echo "Error: could not copy /data/prod.db from $SERVICE" >&2
|
||||
echo "Tip: run a full import once first so the volume has a database." >&2
|
||||
exit 1
|
||||
fi
|
||||
"${COMPOSE[@]}" run --rm --no-deps --entrypoint sh "$SERVICE" -c \
|
||||
'rm -f /data/prod.db-wal /data/prod.db-shm' >/dev/null
|
||||
|
||||
"$MERGE_PLAYER_SCRIPT" "$DB" "$TARGET_DB" "$USERNAME"
|
||||
|
||||
echo "==> Writing merged database → /data/prod.db"
|
||||
"${COMPOSE[@]}" cp "$TARGET_DB" "$SERVICE:/data/prod.db"
|
||||
|
||||
AVATAR_URL="$(sqlite3 "$DB" "SELECT avatarUrl FROM User WHERE username = '${USERNAME//\'/\'\'}' LIMIT 1;" 2>/dev/null || true)"
|
||||
if [[ -d "$SRC/uploads" ]]; then
|
||||
copy_player_avatar_docker "${AVATAR_URL:-}" "$SRC/uploads"
|
||||
fi
|
||||
|
||||
echo "==> Starting $SERVICE"
|
||||
"${COMPOSE[@]}" start "$SERVICE" 2>/dev/null || "${COMPOSE[@]}" up -d "$SERVICE"
|
||||
|
||||
HOST_PORT_VAL="${HOST_PORT:-}"
|
||||
if [[ -z "$HOST_PORT_VAL" && -f "$ENV_FILE" ]]; then
|
||||
HOST_PORT_VAL="$(grep -E '^HOST_PORT=' "$ENV_FILE" 2>/dev/null | cut -d= -f2- | tr -d '"' || true)"
|
||||
fi
|
||||
HOST_PORT_VAL="${HOST_PORT_VAL:-3009}"
|
||||
|
||||
echo "==> Done (player-only)."
|
||||
echo " App: http://localhost:${HOST_PORT_VAL}"
|
||||
echo " Logs: ${COMPOSE[*]} logs -f --tail=50"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Full import (replace Docker DB + uploads) ────────────────────────────────
|
||||
echo "==> Stopping $SERVICE (safe SQLite replace)"
|
||||
"${COMPOSE[@]}" stop "$SERVICE" >/dev/null 2>&1 || true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user