123456789set -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=16151617os="$(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}46474849install_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 79 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}108109110111check_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}150151152153build_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}177178179180check_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}192193194195if install_binary; then196 check_path197 exit 0198fi199200say "pre-built binary unavailable for ${platform} — trying source build"201build_from_source202check_path