#!/bin/sh main() ( set -eu fail() { printf '%s\n' "nevia: $*" >&2; exit 1; } valid_version() { case "$1" in ''|*[!0-9.]*) return 1 ;; esac printf '%s\n' "$1" | LC_ALL=C grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$' } for tool in curl tar mktemp grep awk uname mkdir chmod mv rm cat; do command -v "$tool" >/dev/null 2>&1 || fail "Required tool not found: $tool" done if command -v sha256sum >/dev/null 2>&1; then checksum() { sha256sum "$1"; } elif command -v shasum >/dev/null 2>&1; then checksum() { shasum -a 256 "$1"; } else fail "Required tool not found: sha256sum or shasum" fi case "$(uname -s):$(uname -m)" in Darwin:arm64|Darwin:aarch64) target=aarch64-apple-darwin ;; Darwin:x86_64) target=x86_64-apple-darwin ;; Linux:aarch64|Linux:arm64) target=aarch64-unknown-linux-musl ;; Linux:x86_64|Linux:amd64) target=x86_64-unknown-linux-musl ;; *) fail "Unsupported operating system or architecture" ;; esac base=${NEVIA_DOWNLOAD_BASE_URL-https://get.nevia.cloud} base=${base%/} # An explicit override permits loopback HTTP for tests, never remote HTTP. case "$base" in https://?*) protocols='=https' ;; http://*) authority=${base#http://} authority=${authority%%/*} port=${authority##*:} case "$port" in ''|*[!0-9]*) fail "Local HTTP requires an explicit numeric port" ;; esac case "$authority" in localhost:"$port"|127.0.0.1:"$port"|\[::1\]:"$port") protocols='=http,https' ;; *) fail "HTTP is only permitted for loopback test downloads" ;; esac ;; *) fail "Download base URL must use HTTPS (or loopback HTTP for tests)" ;; esac download() { curl --fail --silent --show-error --location \ --proto "$protocols" --proto-redir '=https' \ --connect-timeout 10 --max-time 120 --retry 2 --retry-max-time 240 \ "$base/$1" -o "$2" } tmp=$(mktemp -d) staged= trap 'rm -rf "$tmp"; if [ -n "$staged" ]; then rm -f "$staged"; fi' 0 trap 'exit 1' HUP INT TERM if [ "${NEVIA_VERSION+x}" = x ]; then version=$NEVIA_VERSION else download stable.txt "$tmp/stable.txt" version=$(cat "$tmp/stable.txt") fi valid_version "$version" || fail "Invalid version: expected MAJOR.MINOR.PATCH without a prefix" archive="nevia-$version-$target.tar.gz" download "releases/$version/$archive" "$tmp/$archive" download "releases/$version/checksums.txt" "$tmp/checksums.txt" # Count even malformed entries for this filename, so duplicates cannot hide # behind invalid hashes. Other targets' entries do not affect installation. expected=$(LC_ALL=C awk -v name="$archive" ' $NF == name { count++ if (NF == 2 && length($1) == 64 && $1 !~ /[^0-9a-fA-F]/ && $0 == $1 " " name) hash = tolower($1) } END { if (count != 1 || hash == "") exit 1; print hash } ' "$tmp/checksums.txt") || fail "Expected exactly one valid checksum for $archive" actual=$(checksum "$tmp/$archive") actual=${actual%% *} [ "$actual" = "$expected" ] || fail "Checksum mismatch for $archive" # Extract only the executable's contents; archive paths and links are never # materialized on disk. A missing/invalid executable fails before replacement. tar -xzOf "$tmp/$archive" nevia > "$tmp/nevia" install_dir=${NEVIA_INSTALL_DIR-"$HOME/.local/bin"} case "$install_dir" in /*) ;; '') fail "Install directory must not be empty" ;; *) install_dir="$PWD/$install_dir" ;; esac mkdir -p "$install_dir" [ ! -d "$install_dir/nevia" ] || fail "$install_dir/nevia is a directory" staged=$(mktemp "$install_dir/.nevia.XXXXXX") cat "$tmp/nevia" > "$staged" chmod 755 "$staged" reported=$("$staged" --version) || fail "Downloaded executable could not run" [ "$reported" = "nevia $version" ] || fail "Downloaded executable reports an unexpected version" mv -f "$staged" "$install_dir/nevia" staged= printf 'Installed nevia %s to %s/nevia\n' "$version" "$install_dir" case ":${PATH-}:" in *":$install_dir:"*) ;; *) # Quote custom paths so the suggested command can be copied safely. path_dir=$(printf '%s\n' "$install_dir" | awk '{gsub(/["\\$`]/, "\\\\&"); print}') printf '\nTo use nevia in this terminal (sh, bash or zsh), run:\n' printf ' export PATH="%s:$PATH"\n' "$path_dir" case "${SHELL-}" in */zsh) printf 'For future terminals, add that line to ~/.zshrc.\n' ;; */bash) printf 'For future terminals, add that line to ~/.bashrc.\n' ;; esac ;; esac ) main "$@"