#!/usr/bin/env bash # scripts/install/client.sh - install and setup all client related apps and environments set -euo pipefail ORIG_USER=${SUDO_USER:-$(id -un)} REF=${LESAVKA_REF:-master} REPO_URL=${LESAVKA_REPO_URL:-ssh://git@scm.bstein.dev:2242/bstein/lesavka.git} SRC=/var/src/lesavka export TMPDIR=${TMPDIR:-/var/tmp} log() { printf '==> %s\n' "$*" } require_command() { local cmd=$1 local pkg_hint=$2 if command -v "$cmd" >/dev/null 2>&1; then return 0 fi echo "❌ required command '$cmd' is unavailable after install (expected via $pkg_hint)" >&2 exit 1 } mkdir -p "$TMPDIR" log "1. Installing base packages" # Intentionally leave the host audio stack alone. Workstations often carry # tightly versioned PipeWire packages, and Lesavka should not force an audio # stack upgrade just to install the client. sudo pacman -Sq --needed --noconfirm \ git rustup protobuf gcc clang evtest base-devel libpulse \ gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav \ wmctrl qt6-tools wl-clipboard xclip xsel desktop-file-utils ensure_yay() { if command -v yay >/dev/null 2>&1; then if sudo -u "$ORIG_USER" yay --version >/dev/null 2>&1; then return fi fi sudo -u "$ORIG_USER" env TMPDIR="$TMPDIR" bash -c 'rm -rf "$TMPDIR/yay" && cd "$TMPDIR" && git clone --depth 1 https://aur.archlinux.org/yay.git && cd yay && makepkg -si --noconfirm' } log "1b. Installing grpcurl" if sudo pacman -Si grpcurl >/dev/null 2>&1; then sudo pacman -Sq --needed --noconfirm grpcurl else ensure_yay if ! sudo -u "$ORIG_USER" yay -S --needed --noconfirm grpcurl-bin; then log "grpcurl AUR install failed once, rebuilding yay and retrying" ensure_yay sudo -u "$ORIG_USER" yay -S --needed --noconfirm grpcurl-bin fi fi # 1c. input access log "1c. Ensuring input group access for $ORIG_USER" sudo usermod -aG input "$ORIG_USER" log "1d. Verifying runtime tools" require_command pactl "libpulse" require_command wmctrl "wmctrl" require_command qdbus6 "qt6-tools" if ! command -v wl-paste >/dev/null 2>&1 \ && ! command -v xclip >/dev/null 2>&1 \ && ! command -v xsel >/dev/null 2>&1; then echo "❌ no clipboard reader found after install (expected one of wl-clipboard/xclip/xsel)" >&2 exit 1 fi if ! sudo -u "$ORIG_USER" pactl info >/dev/null 2>&1; then echo "⚠️ pactl is installed, but no PulseAudio/PipeWire Pulse server is reachable right now." echo " Lesavka will still install, but local speaker/mic staging may stay empty until the host audio session is up." fi # 2. Rust tool-chain for both root & user log "2. Ensuring Rust toolchain" sudo rustup default stable sudo -u "$ORIG_USER" rustup default stable # 3. clone / update into a canonical workspace checkout log "3. Syncing source checkout for ref ${REF}" if [[ ! -d /var/src ]]; then sudo mkdir -p /var/src fi sudo chown "$ORIG_USER":"$ORIG_USER" /var/src if [[ -d $SRC/.git ]]; then sudo -u "$ORIG_USER" git -C "$SRC" fetch --all --tags --prune else sudo -u "$ORIG_USER" git clone "$REPO_URL" "$SRC" fi if sudo -u "$ORIG_USER" git -C "$SRC" rev-parse --verify --quiet "origin/$REF" >/dev/null; then sudo -u "$ORIG_USER" git -C "$SRC" checkout -B "$REF" "origin/$REF" else sudo -u "$ORIG_USER" git -C "$SRC" checkout --force "$REF" fi # 4. build log "4. Building client release binary" sudo -u "$ORIG_USER" env TMPDIR="$TMPDIR" bash -c "cd '$SRC/client' && cargo clean && cargo build --release" # 5. install binary log "5. Installing launchable client binaries" sudo install -Dm755 "$SRC/target/release/lesavka-client" /usr/local/bin/lesavka-client sudo ln -sf /usr/local/bin/lesavka-client /usr/local/bin/lesavka log "6. Registering desktop application" sudo install -Dm644 "$SRC/client/assets/icons/hicolor/1024x1024/apps/lesavka.png" \ /usr/share/icons/hicolor/1024x1024/apps/lesavka.png sudo install -Dm644 "$SRC/client/assets/icons/hicolor/1024x1024/apps/lesavka.png" \ /usr/share/pixmaps/lesavka.png sudo install -Dm644 "$SRC/client/assets/linux/lesavka.desktop" \ /usr/share/applications/lesavka.desktop if command -v update-desktop-database >/dev/null 2>&1; then sudo update-desktop-database /usr/share/applications fi if command -v gtk-update-icon-cache >/dev/null 2>&1; then sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true fi log "7. Removing legacy auto-start service" sudo systemctl disable --now lesavka-client.service >/dev/null 2>&1 || true sudo rm -f /etc/systemd/system/lesavka-client.service sudo systemctl daemon-reload echo echo "✅ lesavka-client install complete" echo " Binary: /usr/local/bin/lesavka-client" echo " Launch alias: /usr/local/bin/lesavka" echo " Desktop entry: /usr/share/applications/lesavka.desktop" echo " Build source: $SRC/target/release/lesavka-client" echo echo "Quick start:" echo " KDE menu: search for Lesavka" echo " Terminal: /usr/local/bin/lesavka"