#!/usr/bin/env bash # --------------------------------------------------------------------------- # mp_common.sh — utilidades compartidas por los launchers de macOS/Linux # (start.command, stop.command, restart.command, start_persistent_profile.command # y setup_mac.command). # # No se ejecuta directamente: los demás scripts lo cargan con `source`. # Equivale a la lógica común que en Windows vive embebida en los .bat. # --------------------------------------------------------------------------- # Raíz del proyecto = carpeta donde vive este archivo. Resuelve symlinks para # que funcione aunque el .command se invoque desde otra ruta. SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)" SOURCE="$(readlink "$SOURCE")" [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" done PROJECT_DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)" cd "$PROJECT_DIR" || exit 1 VENV_DIR="$PROJECT_DIR/.venv" VENV_PY="$VENV_DIR/bin/python" # Versión mínima de Python que exige el proyecto (3.10+). PY_MIN_MAJOR=3 PY_MIN_MINOR=10 # Colorea solo si la salida es una terminal interactiva. if [ -t 1 ]; then C_RESET="\033[0m"; C_BOLD="\033[1m"; C_RED="\033[31m"; C_YEL="\033[33m"; C_GRN="\033[32m" else C_RESET=""; C_BOLD=""; C_RED=""; C_YEL=""; C_GRN="" fi info() { printf "${C_BOLD}[SISTEMA]${C_RESET} %s\n" "$1"; } ok() { printf "${C_GRN}[OK]${C_RESET} %s\n" "$1"; } warn() { printf "${C_YEL}[ADVERTENCIA]${C_RESET} %s\n" "$1"; } err() { printf "${C_RED}[ERROR]${C_RESET} %s\n" "$1" >&2; } # Imprime un encabezado tipo banner como los .bat de Windows. banner() { echo "===================================================" echo " $1" echo "===================================================" echo } # True si "$1 --version" reporta >= PY_MIN. _py_is_recent_enough() { local cmd="$1" "$cmd" -c "import sys; sys.exit(0 if sys.version_info[:2] >= ($PY_MIN_MAJOR, $PY_MIN_MINOR) else 1)" 2>/dev/null } # Localiza un intérprete del sistema 3.10+ para crear el venv. Prueba nombres # versionados explícitos (más fiables que 'python3' a secas en macOS, donde el # 'python3' del sistema suele ser viejo). Imprime la ruta o vacío. find_system_python() { local candidates=(python3.13 python3.12 python3.11 python3.10 python3 python) for c in "${candidates[@]}"; do if command -v "$c" >/dev/null 2>&1 && _py_is_recent_enough "$c"; then command -v "$c" return 0 fi done return 1 } # Devuelve el python del venv si existe; si no, vacío. Los launchers que # requieren dependencias instaladas deben llamar a require_venv en su lugar. venv_python() { if [ -x "$VENV_PY" ]; then echo "$VENV_PY" return 0 fi return 1 } # Garantiza que el venv exista; si no, da instrucciones y aborta. Imprime la # ruta del intérprete del venv por stdout (para capturarla con $(...)). require_venv() { if [ ! -x "$VENV_PY" ]; then err "No se encontró el entorno virtual (.venv)." err "Ejecuta primero (doble clic): setup_mac.command" return 1 fi echo "$VENV_PY" } # Pausa al final cuando el script se abrió con doble clic en Finder, para que la # ventana de Terminal no se cierre de golpe y el usuario pueda leer el resultado. # Si se ejecutó desde una terminal interactiva (uso avanzado), no estorba. hold_window() { echo read -r -p "Presiona ENTER para cerrar esta ventana..." _ || true }