#!/bin/sh # install.sh — download and install a prebuilt rdbms-playground binary. # # Quick start (Linux / macOS): # curl -fsSL https://git.lazyeval.net/oli/rdbms-playground/raw/branch/main/scripts/install.sh | sh # # What it does: detects your OS + CPU, downloads the matching release binary # from the Gitea releases (Linux uses the fully-static musl build), verifies # its SHA-256 checksum, and installs it to ~/.local/bin. # # Environment overrides: # RDBMS_VERSION install a specific tag (e.g. v0.2.0) instead of the latest # RDBMS_INSTALL_DIR install directory (default: $HOME/.local/bin) # RDBMS_OS force the OS (testing): Linux | Darwin # RDBMS_ARCH force the CPU (testing): x86_64 | aarch64 # # Flags: # --print-target print the resolved target triple and exit (no download) # -h, --help print this help and exit # # Notes: # * Windows is not installable via this script (the binary is a .exe) — # use Scoop/winget (planned) or download the .exe from the releases page. # * macOS: a curl download is not quarantined by Gatekeeper, so the binary # runs without extra steps. (Developer-ID signing + notarization is a # separate, planned improvement for browser downloads.) # # POSIX sh — no bashisms, so it runs under the `sh` of `curl | sh`. set -eu REPO_BASE="https://git.lazyeval.net/oli/rdbms-playground" API_BASE="https://git.lazyeval.net/api/v1/repos/oli/rdbms-playground" BIN_NAME="rdbms-playground" PRINT_TARGET=0 err() { printf 'install: %s\n' "$1" >&2 exit 1 } info() { printf '%s\n' "$1" >&2; } usage() { # Lines 2..(first blank) of this file are the human-readable header. sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//' } # Resolve the Rust target triple for the current (or forced) platform. # Linux -> -unknown-linux-musl (the fully-static build) # macOS -> -apple-darwin detect_target() { os="${RDBMS_OS:-$(uname -s)}" arch="${RDBMS_ARCH:-$(uname -m)}" case "$os" in Linux | linux) os_part="unknown-linux-musl" ;; Darwin | darwin | macos | macOS) os_part="apple-darwin" ;; MINGW* | MSYS* | CYGWIN* | *Windows* | *windows*) err "Windows is not supported by this installer — use Scoop/winget (planned) or download the .exe from $REPO_BASE/releases" ;; *) err "unsupported operating system: $os" ;; esac case "$arch" in x86_64 | amd64) arch_part="x86_64" ;; aarch64 | arm64) arch_part="aarch64" ;; *) err "unsupported CPU architecture: $arch" ;; esac printf '%s-%s' "$arch_part" "$os_part" } # Download $1 to file $2 (curl or wget). download() { if command -v curl >/dev/null 2>&1; then curl -fsSL "$1" -o "$2" elif command -v wget >/dev/null 2>&1; then wget -qO "$2" "$1" else err "need either curl or wget on PATH" fi } # Fetch $1 to stdout (curl or wget). fetch() { if command -v curl >/dev/null 2>&1; then curl -fsSL "$1" elif command -v wget >/dev/null 2>&1; then wget -qO- "$1" else err "need either curl or wget on PATH" fi } # The release tag to install: $RDBMS_VERSION if set, else the latest release. resolve_version() { if [ -n "${RDBMS_VERSION:-}" ]; then printf '%s' "$RDBMS_VERSION" return fi json=$(fetch "$API_BASE/releases/latest") || err "could not query the latest release from $API_BASE" # Portable JSON scrape (no jq): the latest-release object carries exactly # one "tag_name": "" field. tag=$(printf '%s' "$json" | grep -o '"tag_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"$/\1/') [ -n "$tag" ] || err "could not parse the latest release tag" printf '%s' "$tag" } # Verify file $1 against sha256 sidecar $2 (format: " "). verify_checksum() { expected=$(awk '{print $1; exit}' "$2") if command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$1" | awk '{print $1}') elif command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$1" | awk '{print $1}') else info "warning: no sha256 tool found — skipping checksum verification" return 0 fi [ "$expected" = "$actual" ] || err "checksum mismatch (expected $expected, got $actual) — refusing to install" } main() { while [ $# -gt 0 ]; do case "$1" in --print-target) PRINT_TARGET=1 ;; -h | --help) usage exit 0 ;; *) err "unknown argument: $1 (try --help)" ;; esac shift done target=$(detect_target) if [ "$PRINT_TARGET" = "1" ]; then printf '%s\n' "$target" exit 0 fi version=$(resolve_version) asset="$BIN_NAME-$version-$target" url="$REPO_BASE/releases/download/$version/$asset" dir="${RDBMS_INSTALL_DIR:-$HOME/.local/bin}" tmp=$(mktemp -d 2>/dev/null) || err "could not create a temporary directory" trap 'rm -rf "$tmp"' EXIT INT TERM info "downloading $asset ..." download "$url" "$tmp/$BIN_NAME" || err "download failed: $url" download "$url.sha256" "$tmp/$BIN_NAME.sha256" || err "checksum download failed: $url.sha256" verify_checksum "$tmp/$BIN_NAME" "$tmp/$BIN_NAME.sha256" mkdir -p "$dir" || err "could not create install directory: $dir" chmod +x "$tmp/$BIN_NAME" mv "$tmp/$BIN_NAME" "$dir/$BIN_NAME" || err "could not install to $dir" info "installed $BIN_NAME $version -> $dir/$BIN_NAME" case ":${PATH:-}:" in *":$dir:"*) ;; *) info "note: $dir is not on your PATH. Add it, e.g.: export PATH=\"$dir:\$PATH\"" ;; esac } main "$@"