123456set -e78FLAKE_URL="https://kepr.uk/nina/archive/HEAD.tar.gz"9RELEASES_URL="https://kepr.uk/api/nina/releases/latest"10INSTALL_DIR="${NINA_INSTALL_DIR:-$HOME/.local/bin}"11MIN_ZIG_MINOR=161213os="$(uname -s)"14arch="$(uname -m)"15case "${os}-${arch}" in16 Linux-x86_64) platform="linux-x86_64" ;;17 Linux-aarch64|Linux-arm64) platform="linux-aarch64" ;;18 Darwin-arm64) platform="macos-aarch64" ;;19 Darwin-x86_64) platform="macos-x86_64" ;;20 *)21 printf 'nina: unsupported platform %s-%s\n' "$os" "$arch" >&222 exit 1 ;;23esac2425have() { command -v "$1" >/dev/null 2>&1; }26say() { printf 'nina: %s\n' "$1"; }27die() { say "error: $1" >&2; exit 1; }28blank() { printf '\n'; }29is_nixos() { [ -e /etc/NIXOS ]; }3031fetch_text() {32 if have curl; then curl -fsSL "$1"33 elif have wget; then wget -qO- "$1"34 else die "curl or wget required"; fi35}3637fetch_file() {38 if have curl; then curl -fsSL "$1" -o "$2"39 elif have wget; then wget -qO "$2" "$1"40 else die "curl or wget required"; fi41}42434445banner() {46 cat <<'BANNER'4748 _ __ _ _ __ __ _49 | '_ \ (_)| '_ \ / _` |50 | | | || || | | || (_| |51 |_| |_||_||_| |_| \__,_|5253 NixOS Intuitive Navigation Assistant · kepr.uk/nina5455BANNER56}57585960fetch_source() {61 srcdir="$(mktemp -d /tmp/nina-src.XXXXXX)"62 say "fetching source from Kepr..."63 fetch_file "$FLAKE_URL" "${srcdir}/nina.tar.gz" \64 || die "could not download source archive — check your connection"65 tar -xzf "${srcdir}/nina.tar.gz" -C "$srcdir" --strip-components=1 \66 || die "could not extract source archive"67 printf '%s' "$srcdir"68}69707172install_binary() {73 say "fetching release metadata..."74 meta="$(fetch_text "$RELEASES_URL" 2>/dev/null)" || return 175 [ -n "$meta" ] || return 17677 if have python3; then78 version="$(printf '%s' "$meta" | python3 -c "79import sys, json80d = json.load(sys.stdin)81print(d.get('version') or '')82" 2>/dev/null)"83 dl_url="$(printf '%s' "$meta" | python3 -c "84import sys, json85d = json.load(sys.stdin)86print((d.get('platforms') or {}).get('${platform}', {}).get('url') or '')87" 2>/dev/null)"88 cksum="$(printf '%s' "$meta" | python3 -c "89import sys, json90d = json.load(sys.stdin)91p = (d.get('platforms') or {}).get('${platform}', {})92raw = p.get('blake3') or p.get('checksum') or ''93print(raw[len('blake3:'):] if raw.startswith('blake3:') else raw)94" 2>/dev/null)"95 elif have jq; then96 version="$(printf '%s' "$meta" | jq -r '.version // empty')"97 dl_url="$(printf '%s' "$meta" | jq -r ".platforms.\"${platform}\".url // empty")"98 cksum_raw="$(printf '%s' "$meta" | jq -r ".platforms.\"${platform}\".blake3 // .platforms.\"${platform}\".checksum // empty")"99 cksum="${cksum_raw#blake3:}"100 else101 version="$(printf '%s' "$meta" | grep -o '"version":"[^"]*"' | sed 's/"version":"//;s/"//')"102 plat_block="$(printf '%s' "$meta" | grep -o "\"${platform}\":{[^}]*}" | head -1)"103 dl_url="$(printf '%s' "$plat_block" | grep -o '"url":"[^"]*"' | sed 's/"url":"//;s/"//')"104 cksum=""105 fi106107 [ -n "$dl_url" ] || return 1108 [ -n "$version" ] || version="latest"109110 say "downloading nina ${version} for ${platform}..."111 tmpfile="$(mktemp /tmp/nina.XXXXXX)"112 fetch_file "$dl_url" "$tmpfile" || { rm -f "$tmpfile"; return 1; }113114 if [ -n "$cksum" ] && have b3sum; then115 actual="$(b3sum --no-names "$tmpfile" 2>/dev/null | awk '{print $1}')"116 if [ "$actual" != "$cksum" ]; then117 say "checksum mismatch — aborting"118 rm -f "$tmpfile"119 return 1120 fi121 say "checksum verified"122 fi123124 chmod +x "$tmpfile"125 mkdir -p "$INSTALL_DIR"126 mv "$tmpfile" "${INSTALL_DIR}/nina"127 say "installed nina ${version} → ${INSTALL_DIR}/nina"128 return 0129}130131132133nixos_profile_install() {134 have nix || return 1135 say "installing via nix profile install..."136 blank137 if nix profile install "$FLAKE_URL"; then138 return 0139 fi140 blank141 say "nix profile install failed. Common causes:"142 say " flakes not enabled — add to /etc/nix/nix.conf or ~/.config/nix/nix.conf:"143 say " experimental-features = nix-command flakes"144 say " once nina is installed: nina setup enables this automatically"145 blank146 return 1147}148149150151nixos_shell_build() {152 have nix-shell || return 1153 say "opening nix-shell with zig_0_16 and building nina from source..."154 blank155 srcdir="$(fetch_source)"156 nix-shell -p zig_0_16 \157 --run "cd '${srcdir}' && zig build -Doptimize=ReleaseSafe" \158 || die "build failed — see output above"159 mkdir -p "$INSTALL_DIR"160 cp "${srcdir}/zig-out/bin/nina" "${INSTALL_DIR}/nina"161 chmod +x "${INSTALL_DIR}/nina"162 blank163 say "installed from source → ${INSTALL_DIR}/nina"164 say "note: this binary was built outside of nix — adopt ~/nina.nix into your"165 say "configuration.nix to make it nix-managed."166}167168169170generate_nixos_module() {171 172 cat > "$HOME/nina.nix" <<'NIXEOF'173# ~/nina.nix — generated by the nina installer174#175# Declares nina as a NixOS system package.176#177# Add to /etc/nixos/configuration.nix:178# imports = [ /home/YOUR_USER/nina.nix ];179# Then: sudo nixos-rebuild switch180#181# For flake-based configurations, add nina as a flake input instead:182# inputs.nina.url = "https://kepr.uk/nina/archive/HEAD.tar.gz";183# # in your modules: nina.nixosModules.default184# # then set: programs.nina.enable = true;185#186# To update nina: nina update187{ ... }:188{189 imports = [190 "${builtins.fetchTarball "https://kepr.uk/nina/archive/HEAD.tar.gz"}/nixos-module.nix"191 ];192 programs.nina.enable = true;193}194NIXEOF195 blank196 say "generated ~/nina.nix for system-wide installation:"197 say " 1. add to /etc/nixos/configuration.nix:"198 say " imports = [ /home/$(id -un)/nina.nix ];"199 say " 2. sudo nixos-rebuild switch"200}201202203204check_zig() {205 if ! have zig; then206 blank207 say "Zig not found. Building nina requires Zig 0.${MIN_ZIG_MINOR}+."208 blank209 say " Download: https://ziglang.org/download/"210 if is_nixos; then211 say " NixOS: nix-shell -p zig_0_16 --run 'sh install.sh'"212 fi213 blank214 die "Zig 0.${MIN_ZIG_MINOR}+ required"215 fi216217 zig_ver="$(zig version 2>/dev/null)"218 major="$(printf '%s' "$zig_ver" | cut -d. -f1)"219 minor="$(printf '%s' "$zig_ver" | cut -d. -f2)"220 ok=0221 [ "$major" -ge 1 ] 2>/dev/null && ok=1222 [ "$major" -eq 0 ] 2>/dev/null && [ "$minor" -ge "$MIN_ZIG_MINOR" ] 2>/dev/null && ok=1223224 if [ "$ok" -ne 1 ]; then225 blank226 say "found zig ${zig_ver}, but nina requires Zig 0.${MIN_ZIG_MINOR}+."227 if is_nixos; then228 say " run: nix-shell -p zig_0_16 --run 'sh install.sh'"229 else230 say " update: https://ziglang.org/download/"231 fi232 blank233 die "Zig 0.${MIN_ZIG_MINOR}+ required; found ${zig_ver}"234 fi235236 say "zig ${zig_ver} found"237}238239240241build_from_source() {242 say "building from source..."243 check_zig244245 if [ -f "build.zig" ] && [ -f "src/main.zig" ]; then246 srcdir="."247 else248 srcdir="$(fetch_source)"249 fi250251 (cd "$srcdir" && zig build -Doptimize=ReleaseSafe) \252 || die "build failed — see output above"253254 mkdir -p "$INSTALL_DIR"255 cp "${srcdir}/zig-out/bin/nina" "${INSTALL_DIR}/nina"256 chmod +x "${INSTALL_DIR}/nina"257 say "installed from source → ${INSTALL_DIR}/nina"258}259260261262check_path() {263 case ":${PATH}:" in264 *":${INSTALL_DIR}:"*) ;;265 *)266 blank267 say "${INSTALL_DIR} is not in your PATH. Add it:"268 say " export PATH=\"\${PATH}:${INSTALL_DIR}\""269 say " echo 'export PATH=\"\${PATH}:${INSTALL_DIR}\"' >> ~/.bashrc"270 if is_nixos; then271 say " NixOS: add to environment.sessionVariables in configuration.nix"272 fi273 ;;274 esac275}276277278279farewell() {280 printf '\n'281 printf ' thank you!! running nina update occasionally will keep me in tip top shape.\n'282 printf ' get started by running nina hello\n'283 printf '\n'284}285286287288banner289290if is_nixos; then291 say "NixOS detected"292 if nixos_profile_install; then293 generate_nixos_module294 farewell295 exit 0296 fi297 nixos_shell_build298 generate_nixos_module299 check_path300 farewell301 exit 0302fi303304305if install_binary; then306 check_path307 farewell308 exit 0309fi310311say "no pre-built binary for ${platform} — falling back to source build"312build_from_source313check_path314farewell