install.sh

7.1 KB · raw

1#!/usr/bin/env sh2# nina install script3# Run:  curl -fsSL kepr.uk/nina/install.sh | sh4# Or:   NINA_INSTALL_DIR=/usr/local/bin sh install.sh5#6# Downloads the pre-built binary from Kepr for your platform.7# Falls back to building from source (requires Zig 0.16+) if unavailable.89set -e1011RELEASES_URL="https://kepr.uk/api/nina/releases/latest"12SOURCE_URL="https://kepr.uk/nina/archive/HEAD.tar.gz"13INSTALL_DIR="${NINA_INSTALL_DIR:-$HOME/.local/bin}"14MIN_ZIG_MINOR=161516# Detect platform17os="$(uname -s)"18arch="$(uname -m)"19case "${os}-${arch}" in20  Linux-x86_64)               platform="linux-x86_64"  ;;21  Linux-aarch64|Linux-arm64)  platform="linux-aarch64" ;;22  Darwin-arm64)               platform="macos-aarch64" ;;23  Darwin-x86_64)              platform="macos-x86_64"  ;;24  *)25    printf 'nina install: unsupported platform %s-%s\n' "$os" "$arch" >&226    printf '  build from source with Zig 0.%s+:\n' "$MIN_ZIG_MINOR" >&227    printf '    zig build -Doptimize=ReleaseSafe\n' >&228    exit 1 ;;29esac3031have() { command -v "$1" >/dev/null 2>&1; }32say()  { printf 'nina install: %s\n' "$1"; }33die()  { say "error: $1" >&2; exit 1; }3435fetch_text() {36  if have curl;   then curl -fsSL "$1"37  elif have wget; then wget -qO- "$1"38  else die "curl or wget is required"; fi39}4041fetch_file() {42  if have curl;   then curl -fsSL "$1" -o "$2"43  elif have wget; then wget -qO  "$2" "$1"44  else die "curl or wget is required"; fi45}4647# ── binary install from Kepr ─────────────────────────────────────────────────4849install_binary() {50  say "fetching release metadata..."51  meta="$(fetch_text "$RELEASES_URL" 2>/dev/null)" || return 152  [ -n "$meta" ] || return 15354  if have python3; then55    version="$(printf '%s' "$meta" | python3 -c "56import sys, json57d = json.load(sys.stdin)58print(d.get('version') or '')59" 2>/dev/null)"60    dl_url="$(printf '%s' "$meta" | python3 -c "61import sys, json62d = json.load(sys.stdin)63print((d.get('platforms') or {}).get('${platform}', {}).get('url') or '')64" 2>/dev/null)"65    cksum="$(printf '%s' "$meta" | python3 -c "66import sys, json67d = json.load(sys.stdin)68p = (d.get('platforms') or {}).get('${platform}', {})69raw = p.get('blake3') or p.get('checksum') or ''70print(raw[len('blake3:'):] if raw.startswith('blake3:') else raw)71" 2>/dev/null)"72  elif have jq; then73    version="$(printf '%s' "$meta" | jq -r '.version // empty')"74    dl_url="$(printf '%s' "$meta" | jq -r ".platforms.\"${platform}\".url // empty")"75    cksum_raw="$(printf '%s' "$meta" | jq -r ".platforms.\"${platform}\".blake3 // .platforms.\"${platform}\".checksum // empty")"76    cksum="${cksum_raw#blake3:}"77  else78    # Minimal grep/sed fallback for compact JSON79    version="$(printf '%s' "$meta" | grep -o '"version":"[^"]*"' | sed 's/"version":"//;s/"//')"80    plat_block="$(printf '%s' "$meta" | grep -o "\"${platform}\":{[^}]*}" | head -1)"81    dl_url="$(printf '%s' "$plat_block" | grep -o '"url":"[^"]*"' | sed 's/"url":"//;s/"//')"82    cksum=""83  fi8485  [ -n "$dl_url" ] || return 186  [ -n "$version" ] || version="latest"8788  say "downloading nina ${version} for ${platform}..."89  tmpfile="$(mktemp /tmp/nina.XXXXXX)"90  fetch_file "$dl_url" "$tmpfile" || { rm -f "$tmpfile"; return 1; }9192  if [ -n "$cksum" ] && have b3sum; then93    actual="$(b3sum --no-names "$tmpfile" 2>/dev/null | awk '{print $1}')"94    if [ "$actual" != "$cksum" ]; then95      say "blake3 checksum mismatch — aborting"96      rm -f "$tmpfile"97      return 198    fi99    say "checksum verified"100  fi101102  chmod +x "$tmpfile"103  mkdir -p "$INSTALL_DIR"104  mv "$tmpfile" "${INSTALL_DIR}/nina"105  say "installed nina ${version} → ${INSTALL_DIR}/nina"106  return 0107}108109# ── Zig version check ─────────────────────────────────────────────────────────110111check_zig() {112  if ! have zig; then113    say ""114    say "Zig not found. Building nina from source requires Zig 0.${MIN_ZIG_MINOR} or later."115    say ""116    say "  NixOS:"117    say "    nix profile install 'nixpkgs#zig_0_16'   # if your channel has it"118    say "    nix-shell -p zig_0_16 --run 'sh install.sh'"119    say "    # or add 'pkgs.zig_0_16' to environment.systemPackages and rebuild"120    say ""121    say "  Direct download: https://ziglang.org/download/"122    say ""123    die "Zig 0.${MIN_ZIG_MINOR}+ required for source build"124  fi125126  zig_ver="$(zig version 2>/dev/null)"127  major="$(printf '%s' "$zig_ver" | cut -d. -f1)"128  minor="$(printf '%s' "$zig_ver" | cut -d. -f2)"129130  ok=0131  [ "$major" -ge 1 ] 2>/dev/null && ok=1132  [ "$major" -eq 0 ] 2>/dev/null && [ "$minor" -ge "$MIN_ZIG_MINOR" ] 2>/dev/null && ok=1133134  if [ "$ok" -ne 1 ]; then135    say ""136    say "Found zig ${zig_ver}, but nina requires Zig 0.${MIN_ZIG_MINOR} or later."137    say ""138    say "  NixOS: the system 'zig' package is ${zig_ver}. To get 0.16:"139    say "    nix profile install 'nixpkgs#zig_0_16'"140    say "    nix-shell -p zig_0_16 --run 'sh install.sh'"141    say "    # or check nixpkgs-unstable if your stable channel lacks zig_0_16"142    say ""143    say "  Direct download: https://ziglang.org/download/"144    say ""145    die "Zig 0.${MIN_ZIG_MINOR}+ required; found ${zig_ver}"146  fi147148  say "zig ${zig_ver} found"149}150151# ── source build fallback ─────────────────────────────────────────────────────152153build_from_source() {154  say "falling back to build from source..."155  check_zig156157  if [ -f "build.zig" ] && [ -f "src/main.zig" ]; then158    srcdir="."159  else160    say "fetching source archive from Kepr..."161    srcdir="$(mktemp -d /tmp/nina-src.XXXXXX)"162    fetch_file "$SOURCE_URL" "${srcdir}/nina.tar.gz" \163      || die "could not download source archive"164    tar -xzf "${srcdir}/nina.tar.gz" -C "$srcdir" --strip-components=1 \165      || die "could not extract source archive"166  fi167168  say "building (this may take a moment)..."169  (cd "$srcdir" && zig build -Doptimize=ReleaseSafe) \170    || die "build failed — see output above for details"171172  mkdir -p "$INSTALL_DIR"173  cp "${srcdir}/zig-out/bin/nina" "${INSTALL_DIR}/nina"174  chmod +x "${INSTALL_DIR}/nina"175  say "installed from source → ${INSTALL_DIR}/nina"176}177178# ── PATH reminder ─────────────────────────────────────────────────────────────179180check_path() {181  case ":${PATH}:" in182    *":${INSTALL_DIR}:"*) ;;183    *)184      say ""185      say "${INSTALL_DIR} is not in your PATH. Add it:"186      say "  export PATH=\"\${PATH}:${INSTALL_DIR}\""187      say "  echo 'export PATH=\"\${PATH}:${INSTALL_DIR}\"' >> ~/.bashrc"188      say "  # NixOS: add '${INSTALL_DIR}' to environment.sessionVariables in configuration.nix"189      ;;190  esac191}192193# ── main ──────────────────────────────────────────────────────────────────────194195if install_binary; then196  check_path197  exit 0198fi199200say "pre-built binary unavailable for ${platform} — trying source build"201build_from_source202check_path