From bb0eb3189b52922e893c12100c8aa76cc58897af Mon Sep 17 00:00:00 2001 From: Uber Veng Date: Fri, 22 May 2026 01:58:08 +0700 Subject: [PATCH] added install & uninstall scripts --- README.md | 61 +++++++++++++++++++++++++-- install.sh | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++ uninstall.sh | 74 +++++++++++++++++++++++++++++++++ 3 files changed, 247 insertions(+), 3 deletions(-) create mode 100755 install.sh create mode 100755 uninstall.sh diff --git a/README.md b/README.md index bad915e..bbbda93 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,59 @@ # Ostiary — удалённый запуск скриптов -Консольный клиент с текстовым интерфейсом (TUI) на Rust. Загружает иерархическое меню с сервера и позволяет запускать bash-скрипты, скачивать файлы и выполнять HTTP-запросы прямо из терминале. Все диалоги (выбор из списка, подтверждение, ввод текста) реализованы внутри интерфейса — никаких сырых `read -p` в терминале. +Консольный клиент с текстовым интерфейсом (TUI) на Rust. Загружает иерархическое меню с сервера и позволяет запускать bash-скрипты, скачивать файлы и выполнять HTTP-запросы прямо из терминала. Все диалоги (выбор из списка, подтверждение, ввод текста) реализованы внутри интерфейса — никаких сырых `read -p` в терминале. + +--- + +## Установка + +### Быстрая установка (Linux / macOS) + +```bash +curl -fsSL https://git.vainend.com/admin/ostiary/raw/branch/master/install.sh | bash +``` + +Скрипт автоматически определяет ОС и архитектуру, скачивает последний стабильный релиз и устанавливает бинарник в `/usr/local/bin/ostiary` (или `~/.local/bin/` если нет прав). + +### Ручная установка + +Скачать нужный бинарник со страницы [Releases](https://git.vainend.com/admin/ostiary/releases): + +| Файл | Платформа | +|---|---| +| `ostiary-linux-x86_64` | Linux x86-64 | +| `ostiary-linux-aarch64` | Linux ARM64 | +| `ostiary-macos-aarch64` | macOS Apple Silicon | +| `ostiary-macos-x86_64` | macOS Intel | + +```bash +chmod +x ostiary-linux-x86_64 +sudo mv ostiary-linux-x86_64 /usr/local/bin/ostiary +``` + +### Удаление + +```bash +curl -fsSL https://git.vainend.com/admin/ostiary/raw/branch/master/uninstall.sh | bash +``` + +Или вручную: + +```bash +sudo rm /usr/local/bin/ostiary +rm -rf ~/.config/ostiary +``` + +### Переменные окружения для install.sh + +| Переменная | По умолчанию | Описание | +|---|---|---| +| `OSTIARY_API` | `https://git.vainend.com/api/v1/repos/admin/ostiary` | Базовый URL Gitea API | +| `INSTALL_DIR` | `/usr/local/bin` | Куда установить бинарник | + +Пример с кастомным каталогом: +```bash +INSTALL_DIR=~/.local/bin bash install.sh +``` --- @@ -497,9 +550,9 @@ server/ --- -## Сборка +## Сборка релиза -Скрипт `release.sh` собирает бинарники для всех платформ сразу: +Скрипт `release.sh` собирает бинарники для всех платформ сразу и кладёт их в `dist/`: ```bash cd Ostiary @@ -509,6 +562,8 @@ cd Ostiary # → dist/ostiary-macos-aarch64 ``` +После сборки загрузите файлы из `dist/` в [новый релиз Gitea](https://git.vainend.com/admin/ostiary/releases/new). Имена файлов должны точно совпадать с тем, что скачивает `install.sh`. + **Вручную — Linux:** ```bash cargo build --release diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..35e05fd --- /dev/null +++ b/install.sh @@ -0,0 +1,115 @@ +#!/bin/bash +set -e + +# ── Configuration ──────────────────────────────────────────────────────────── +BINARY="ostiary" +REPO_API="${OSTIARY_API:-https://git.vainend.com/api/v1/repos/admin/ostiary}" +INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}" + +# ── Colors ─────────────────────────────────────────────────────────────────── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' +CYAN='\033[0;36m'; NC='\033[0m' + +info() { echo -e "${CYAN}[ostiary]${NC} $*"; } +ok() { echo -e "${GREEN}[ostiary]${NC} $*"; } +warn() { echo -e "${YELLOW}[ostiary]${NC} $*"; } +die() { echo -e "${RED}[ostiary]${NC} $*" >&2; exit 1; } + +# ── Detect OS ──────────────────────────────────────────────────────────────── +case "$(uname -s)" in + Linux) OS="linux" ;; + Darwin) OS="macos" ;; + *) die "Unsupported OS: $(uname -s)" ;; +esac + +# ── Detect architecture ────────────────────────────────────────────────────── +case "$(uname -m)" in + x86_64) ARCH="x86_64" ;; + aarch64|arm64) ARCH="aarch64" ;; + *) die "Unsupported architecture: $(uname -m)" ;; +esac + +ASSET="${BINARY}-${OS}-${ARCH}" +info "Platform: ${OS}-${ARCH}" + +# ── HTTP helper ────────────────────────────────────────────────────────────── +if command -v curl &>/dev/null; then + fetch() { curl -fsSL "$1"; } + fetch_file() { curl -fsSL -o "$2" "$1"; } + http_code() { curl -o /dev/null -sLw "%{http_code}" "$1"; } +elif command -v wget &>/dev/null; then + fetch() { wget -qO- "$1"; } + fetch_file() { wget -qO "$2" "$1"; } + http_code() { wget -q --server-response -O /dev/null "$1" 2>&1 \ + | awk '/^ HTTP/{code=$2} END{print code}'; } +else + die "curl or wget is required" +fi + +# ── Fetch latest release tag ───────────────────────────────────────────────── +# Uses /releases/latest which returns the newest non-prerelease, non-draft release. +info "Fetching latest release info..." + +LATEST_JSON=$(fetch "${REPO_API}/releases/latest") \ + || die "Failed to reach Gitea API: ${REPO_API}" + +VERSION=$(printf '%s' "$LATEST_JSON" \ + | grep -o '"tag_name":"[^"]*"' \ + | head -1 \ + | cut -d'"' -f4) + +[ -z "$VERSION" ] && die "Could not parse version from API response" + +ok "Latest version: ${VERSION}" + +# ── Build download URL ─────────────────────────────────────────────────────── +# Strip /api/v1/repos from the API base to get the Gitea web URL: +# https://git.vainend.com/api/v1/repos/admin/ostiary +# → https://git.vainend.com/admin/ostiary +BASE_URL=$(printf '%s' "$REPO_API" | sed 's|/api/v1/repos||') +DOWNLOAD_URL="${BASE_URL}/releases/download/${VERSION}/${ASSET}" + +info "Downloading ${DOWNLOAD_URL}..." + +# Quick existence check before downloading the full binary +CODE=$(http_code "$DOWNLOAD_URL") +[ "$CODE" = "200" ] || die "Asset not found (HTTP ${CODE}): ${ASSET}\nCheck that the release contains a file named '${ASSET}'" + +# ── Download to temp file ──────────────────────────────────────────────────── +TMP=$(mktemp) +trap 'rm -f "$TMP"' EXIT + +fetch_file "$DOWNLOAD_URL" "$TMP" || die "Download failed" +chmod +x "$TMP" + +# ── Install ────────────────────────────────────────────────────────────────── +do_install() { + local dest="$1/$BINARY" + if [ -w "$1" ]; then + mv "$TMP" "$dest" + ok "Installed → $dest" + return 0 + elif command -v sudo &>/dev/null; then + warn "Writing to $1 requires sudo..." + sudo mv "$TMP" "$dest" + ok "Installed → $dest" + return 0 + fi + return 1 +} + +if ! do_install "$INSTALL_DIR"; then + FALLBACK="$HOME/.local/bin" + warn "${INSTALL_DIR} is not writable and sudo is unavailable" + warn "Installing to ${FALLBACK} instead" + mkdir -p "$FALLBACK" + mv "$TMP" "$FALLBACK/$BINARY" + ok "Installed → $FALLBACK/$BINARY" + if [[ ":$PATH:" != *":$FALLBACK:"* ]]; then + warn "Add to your shell profile:" + warn " export PATH=\"\$HOME/.local/bin:\$PATH\"" + fi +fi + +echo "" +ok "Done! Run: $BINARY" diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 0000000..fc80c5a --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,74 @@ +#!/bin/bash +set -e + +BINARY="ostiary" +CONFIG_DIR="$HOME/.config/$BINARY" + +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' +CYAN='\033[0;36m'; NC='\033[0m' + +info() { echo -e "${CYAN}[ostiary]${NC} $*"; } +ok() { echo -e "${GREEN}[ostiary]${NC} $*"; } +warn() { echo -e "${YELLOW}[ostiary]${NC} $*"; } + +# ── Find binary ────────────────────────────────────────────────────────────── +BINARY_PATH=$(command -v "$BINARY" 2>/dev/null || true) + +removed_binary=false + +if [ -n "$BINARY_PATH" ]; then + info "Found binary: $BINARY_PATH" + read -rp " Remove $BINARY_PATH? [y/N] " answer + if [[ "$answer" =~ ^[Yy]$ ]]; then + BIN_DIR=$(dirname "$BINARY_PATH") + if [ -w "$BIN_DIR" ]; then + rm "$BINARY_PATH" + elif command -v sudo &>/dev/null; then + sudo rm "$BINARY_PATH" + else + warn "Cannot remove $BINARY_PATH (no write permission and no sudo)" + fi + ok "Binary removed" + removed_binary=true + fi +else + # Check common locations manually + for loc in /usr/local/bin /usr/bin "$HOME/.local/bin"; do + if [ -f "$loc/$BINARY" ]; then + info "Found binary: $loc/$BINARY" + read -rp " Remove $loc/$BINARY? [y/N] " answer + if [[ "$answer" =~ ^[Yy]$ ]]; then + if [ -w "$loc" ]; then + rm "$loc/$BINARY" + elif command -v sudo &>/dev/null; then + sudo rm "$loc/$BINARY" + else + warn "Cannot remove $loc/$BINARY" + fi + ok "Binary removed" + removed_binary=true + fi + break + fi + done +fi + +if ! $removed_binary; then + warn "Binary not found in PATH" +fi + +# ── Config directory ───────────────────────────────────────────────────────── +if [ -d "$CONFIG_DIR" ]; then + echo "" + info "Config directory: $CONFIG_DIR" + read -rp " Remove config and saved settings? [y/N] " answer + if [[ "$answer" =~ ^[Yy]$ ]]; then + rm -rf "$CONFIG_DIR" + ok "Config removed" + else + ok "Config kept at $CONFIG_DIR" + fi +fi + +echo "" +ok "Done"