113 lines
4.2 KiB
Bash
Executable File
113 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 初始化本机运行环境:Python 虚拟环境 + 后端依赖 + 种子数据(+ 前端依赖)。
|
||
#
|
||
# ./scripts/init.sh 准备后端与前端环境
|
||
# ./scripts/init.sh --no-web 只准备后端
|
||
#
|
||
# 可用环境变量:
|
||
# PIP_INDEX_URL 指定 pip/uv 的包源(默认走官方源,失败自动改用清华镜像)
|
||
# NPM_REGISTRY 指定 npm 包源(失败自动改用 npmmirror)
|
||
set -euo pipefail
|
||
|
||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
cd "$ROOT_DIR"
|
||
mkdir -p data
|
||
|
||
WITH_WEB=1
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--no-web) WITH_WEB=0 ;;
|
||
--web) WITH_WEB=1 ;;
|
||
-h|--help) sed -n '1,12p' "$0"; exit 0 ;;
|
||
*) echo "[init] 未知参数:$arg(可用:--no-web / --web)" >&2; exit 2 ;;
|
||
esac
|
||
done
|
||
|
||
# ---------- 1. 定位 uv(PATH → ~/.local/bin → ~/.cargo/bin) ----------
|
||
UV=""
|
||
for cand in uv "$HOME/.local/bin/uv" "$HOME/.cargo/bin/uv"; do
|
||
if command -v "$cand" >/dev/null 2>&1; then
|
||
UV="$(command -v "$cand")"
|
||
break
|
||
fi
|
||
done
|
||
|
||
# ---------- 2. 定位 Python 3.10+(系统 python3 常常太旧,优先带版本号的解释器) ----------
|
||
py_ok() { "$1" -c 'import sys; sys.exit(0 if sys.version_info >= (3, 10) else 1)' >/dev/null 2>&1; }
|
||
|
||
pick_python() {
|
||
for p in python3.13 python3.12 python3.11 python3.10 python3; do
|
||
if command -v "$p" >/dev/null 2>&1 && py_ok "$p"; then command -v "$p"; return 0; fi
|
||
done
|
||
for p in /opt/homebrew/bin/python3.1* /usr/local/bin/python3.1*; do
|
||
if [ -x "$p" ] && py_ok "$p"; then echo "$p"; return 0; fi
|
||
done
|
||
return 1
|
||
}
|
||
|
||
# ---------- 3. 虚拟环境 ----------
|
||
if [ -x backend/.venv/bin/python ]; then
|
||
echo "[init] 复用已有虚拟环境 backend/.venv($(backend/.venv/bin/python -V 2>&1))"
|
||
elif [ -n "$UV" ]; then
|
||
echo "[init] 使用 uv($UV)创建虚拟环境,优先 CPython 3.12…"
|
||
(cd backend && "$UV" venv .venv --python 3.12) 2>/dev/null || (cd backend && "$UV" venv .venv)
|
||
else
|
||
PY="$(pick_python || true)"
|
||
if [ -z "$PY" ]; then
|
||
echo "[init] 未找到 Python 3.10+(系统自带的 python3 版本过低)。推荐安装 uv 后重试:" >&2
|
||
echo " curl -LsSf https://astral.sh/uv/install.sh | sh" >&2
|
||
echo " 或 brew install python@3.12" >&2
|
||
exit 1
|
||
fi
|
||
echo "[init] 使用 $("$PY" -V 2>&1)($PY)创建虚拟环境…"
|
||
"$PY" -m venv backend/.venv
|
||
fi
|
||
|
||
# ---------- 4. 后端依赖(默认源失败后自动改用国内镜像) ----------
|
||
install_backend() {
|
||
if [ -n "$UV" ]; then
|
||
(cd backend && "$UV" pip install --python .venv/bin/python ${1:+--index-url "$1"} -r requirements.txt)
|
||
else
|
||
(cd backend && .venv/bin/pip install ${1:+-i "$1"} -r requirements.txt)
|
||
fi
|
||
}
|
||
|
||
if ! install_backend "${PIP_INDEX_URL:-}"; then
|
||
echo "[init] 默认包源安装失败,改用清华镜像重试…" >&2
|
||
install_backend https://pypi.tuna.tsinghua.edu.cn/simple
|
||
fi
|
||
|
||
# ---------- 5. 种子数据 ----------
|
||
if [ -f data/math.db ]; then
|
||
echo "[init] data/math.db 已存在,跳过种子数据(重建:cd backend && .venv/bin/python -m seed --force)"
|
||
else
|
||
(cd backend && .venv/bin/python -m seed)
|
||
fi
|
||
|
||
# ---------- 6. 前端依赖 ----------
|
||
if [ "$WITH_WEB" -eq 1 ]; then
|
||
if ! command -v node >/dev/null 2>&1; then
|
||
echo "[init] 未找到 Node.js,前端跳过。请安装 Node 20.19+ 或 22.12+ 后执行:cd frontend && npm install" >&2
|
||
else
|
||
if [ "$(node -p 'process.versions.node.split(".")[0]')" -lt 20 ]; then
|
||
echo "[init] 当前 Node $(node -v) 过低,Vite 8 需要 Node 20.19+ / 22.12+,前端可能无法启动。" >&2
|
||
fi
|
||
npm_install() {
|
||
if [ -n "${1:-}" ]; then (cd frontend && npm install --registry "$1"); else (cd frontend && npm install); fi
|
||
}
|
||
if [ -d frontend/node_modules ]; then
|
||
echo "[init] 前端依赖已存在,跳过 npm install"
|
||
elif ! npm_install "${NPM_REGISTRY:-}"; then
|
||
echo "[init] 默认 npm 源安装失败,改用 npmmirror 重试…" >&2
|
||
npm_install https://registry.npmmirror.com
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
echo
|
||
echo "[init] 环境就绪:"
|
||
echo " Python $(backend/.venv/bin/python -V 2>&1) → backend/.venv"
|
||
echo " Node $(node -v 2>/dev/null || echo '未安装')"
|
||
echo " 数据库 $ROOT_DIR/data/math.db"
|
||
echo "[init] 启动:./scripts/start.sh → http://localhost:5173"
|