robin/manage.sh
pyr0ball efec0a53ee feat(manage): manage.sh overhaul + exe-relative pattern loading + desktop entry
manage.sh:
- run: foreground execution with auto DISPLAY + RUST_LOG
- start/stop/restart/status: background daemon lifecycle
- logs: tail Robin log file
- build-debug: Rust-only build (no Node/npm needed)
- desktop-install/remove: system application menu entry
- autostart-enable/disable: XDG autostart entry
- install: build-debug + desktop-install + autostart-enable in one step
- uninstall: reverses install cleanly

patterns.rs:
- Add exe-relative candidates: binary-dir/patterns/ and binary-dir/../../patterns/
  This means the binary works from any working directory without requiring
  the user to cd into ~/robin/ first
2026-05-20 11:06:55 -07:00

265 lines
7.3 KiB
Bash
Executable file

#!/usr/bin/env bash
# Robin — manage.sh
# Usage: ./manage.sh <command>
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_NAME="robin"
RELEASE_BIN="$SCRIPT_DIR/src-tauri/target/release/$APP_NAME"
DEBUG_BIN="$SCRIPT_DIR/src-tauri/target/debug/$APP_NAME"
ICON="$SCRIPT_DIR/src-tauri/icons/128x128.png"
LOG_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/tech.circuitforge.robin/logs/Robin.log"
cmd="${1:-help}"
# ── Helpers ───────────────────────────────────────────────────────────────────
_find_binary() {
if [[ -f "$RELEASE_BIN" ]]; then
echo "$RELEASE_BIN"
elif [[ -f "$DEBUG_BIN" ]]; then
echo "$DEBUG_BIN"
else
echo ""
fi
}
_require_binary() {
local bin
bin="$(_find_binary)"
if [[ -z "$bin" ]]; then
echo "Robin binary not found. Run one of:"
echo " ./manage.sh build (release, requires Node + Tauri CLI)"
echo " ./manage.sh build-debug (debug, requires Rust only)"
exit 1
fi
echo "$bin"
}
# ── Commands ──────────────────────────────────────────────────────────────────
case "$cmd" in
run)
# Run the binary in the foreground (logs to terminal).
# Use this for manual testing; Ctrl+C to quit.
bin="$(_require_binary)"
echo "Starting Robin ($bin)..."
export DISPLAY="${DISPLAY:-:0}"
export RUST_LOG="${RUST_LOG:-robin_lib=info,warn}"
exec "$bin"
;;
start)
# Start Robin in the background (daemonised via nohup).
if pgrep -x "$APP_NAME" > /dev/null 2>&1; then
echo "Robin is already running (PID $(pgrep -x "$APP_NAME"))"
exit 0
fi
bin="$(_require_binary)"
echo "Starting Robin in background..."
export DISPLAY="${DISPLAY:-:0}"
export RUST_LOG="${RUST_LOG:-robin_lib=info,warn}"
mkdir -p "$(dirname "$LOG_FILE")"
nohup "$bin" >> "$LOG_FILE" 2>&1 &
echo "Started (PID $!). Logs: $LOG_FILE"
;;
stop)
if pgrep -x "$APP_NAME" > /dev/null 2>&1; then
pkill -x "$APP_NAME"
echo "Robin stopped."
else
echo "Robin is not running."
fi
;;
restart)
"$0" stop || true
sleep 1
"$0" start
;;
status)
if pgrep -x "$APP_NAME" > /dev/null 2>&1; then
echo "Robin is running (PID $(pgrep -x "$APP_NAME"))"
else
echo "Robin is not running."
fi
;;
logs)
if [[ -f "$LOG_FILE" ]]; then
tail -f "$LOG_FILE"
else
echo "No log file yet at $LOG_FILE"
echo "Start Robin first: ./manage.sh start"
fi
;;
dev)
echo "Starting Robin in dev mode (hot-reload)..."
cd "$SCRIPT_DIR"
npm run tauri dev
;;
build)
echo "Building Robin release binary + installers..."
cd "$SCRIPT_DIR"
npm run tauri build
;;
build-debug)
echo "Building Robin debug binary (Rust only, no Node needed)..."
cargo build --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml"
echo "Binary: $DEBUG_BIN"
;;
test)
echo "Running Rust tests..."
cargo test --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml" --lib
;;
install-deps)
echo "Installing system dependencies (Debian/Ubuntu/Mint)..."
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
libgtk-3-dev \
libssl-dev \
pkg-config
echo "Installing Rust dependencies..."
cargo fetch --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml"
;;
install-deps-arch)
echo "Installing system dependencies (Arch/Manjaro/CachyOS)..."
paru -S --needed \
webkit2gtk-4.1 \
libayatana-appindicator \
librsvg \
gtk3 \
openssl \
pkg-config
cargo fetch --manifest-path "$SCRIPT_DIR/src-tauri/Cargo.toml"
;;
desktop-install)
# Install .desktop entry so Robin appears in the system app menu.
bin="$(_require_binary)"
APPS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
mkdir -p "$APPS_DIR"
cat > "$APPS_DIR/robin.desktop" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=Robin
GenericName=Linux Migration Assistant
Comment=Helps you find your feet on Linux
Exec=$bin
Icon=$ICON
Categories=Utility;System;
StartupNotify=false
StartupWMClass=Robin
Keywords=linux;migration;help;assistant;
EOF
update-desktop-database "$APPS_DIR" 2>/dev/null || true
echo "Robin added to application menu."
echo "Entry: $APPS_DIR/robin.desktop"
;;
desktop-remove)
DESKTOP="${XDG_DATA_HOME:-$HOME/.local/share}/applications/robin.desktop"
if [[ -f "$DESKTOP" ]]; then
rm "$DESKTOP"
update-desktop-database "$(dirname "$DESKTOP")" 2>/dev/null || true
echo "Robin removed from application menu."
else
echo "No desktop entry found at $DESKTOP"
fi
;;
autostart-enable)
# Start Robin automatically when the desktop session begins.
bin="$(_require_binary)"
AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart"
mkdir -p "$AUTOSTART_DIR"
cat > "$AUTOSTART_DIR/robin.desktop" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=Robin
Comment=Helps you find your feet on Linux
Exec=$bin
Icon=$ICON
StartupNotify=false
X-GNOME-Autostart-enabled=true
Hidden=false
NoDisplay=false
EOF
echo "Robin will start automatically at login."
echo "Entry: $AUTOSTART_DIR/robin.desktop"
;;
autostart-disable)
AUTOSTART="${XDG_CONFIG_HOME:-$HOME/.config}/autostart/robin.desktop"
if [[ -f "$AUTOSTART" ]]; then
rm "$AUTOSTART"
echo "Robin autostart disabled."
else
echo "No autostart entry found at $AUTOSTART"
fi
;;
install)
# Full install: build-debug + desktop-install + autostart-enable
echo "=== Robin install ==="
"$0" build-debug
"$0" desktop-install
"$0" autostart-enable
echo ""
echo "Robin installed. It will start at next login."
echo "Start it now: ./manage.sh start"
;;
uninstall)
"$0" stop || true
"$0" desktop-remove || true
"$0" autostart-disable || true
echo "Robin uninstalled."
;;
help|*)
cat <<'EOF'
Robin — Linux migration companion
Usage: ./manage.sh <command>
Running:
run Run in foreground (logs to terminal, Ctrl+C to quit)
start Start in background
stop Stop background instance
restart Stop then start
status Show whether Robin is running
logs Tail the Robin log file
Building:
build-debug Build debug binary (Rust only, no Node/npm needed)
build Build release binary + .deb/.rpm/.AppImage (needs Node + Tauri CLI)
dev Start dev mode with hot-reload (needs Node + Tauri CLI)
test Run Rust unit tests
Installation:
install build-debug + desktop-install + autostart-enable
uninstall Remove desktop entry, autostart, and stop Robin
desktop-install Add Robin to the system application menu
desktop-remove Remove Robin from the application menu
autostart-enable Start Robin automatically at login
autostart-disable Stop Robin from starting at login
Dependencies:
install-deps Install system deps (Debian/Ubuntu/Mint)
install-deps-arch Install system deps (Arch/Manjaro/CachyOS)
EOF
;;
esac