#!/bin/sh # Installs orc from https://dl.sieversii.ca/orc/. # # curl -fsSL https://orc.sieversii.ca/install.sh | sh # # What it does: picks the release for your platform, downloads it with its # checksum file and signature, checks the signature against the keys written # below and the archive against the checksum, then installs orc to # ~/.local/bin. No sudo. If any check fails, nothing is installed. # # Settings (optional): # ORC_VERSION=X.Y.Z install that version instead of the latest # ORC_INSTALL_DIR=DIR install there instead of ~/.local/bin # # Needs sh, curl, tar, ssh-keygen (OpenSSH 8.1 or newer) and shasum or # sha256sum. How to check a download by hand: https://orc.sieversii.ca/verify/ # # Generated from the shared install script template (script version # 1). # Everything is in one function, called on the last line, so a download cut # off part way runs nothing. orc_install() { set -eu app='orc' script_version='1' base='https://dl.sieversii.ca/orc' ua="$app-install/$script_version" namespace='orc-release' identity='orc-release' binary='orc' install_name='orc' say() { printf '%s\n' "$*"; } fail() { printf '%s install: %s\n' "$app" "$*" >&2 exit 1 } missing='' for tool in curl tar ssh-keygen mktemp; do command -v "$tool" >/dev/null 2>&1 || missing="$missing $tool" done if command -v shasum >/dev/null 2>&1; then sha256() { shasum -a 256 "$1"; } elif command -v sha256sum >/dev/null 2>&1; then sha256() { sha256sum "$1"; } else missing="$missing shasum-or-sha256sum" fi [ -z "$missing" ] || fail "missing:$missing. Install them and run this again. Nothing was installed." os=$(uname -s) arch=$(uname -m) # An Intel shell under Rosetta on Apple silicon still wants the arm64 build. if [ "$os" = Darwin ] && [ "$arch" = x86_64 ] && [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || true)" = 1 ]; then arch=arm64 fi case "$os/$arch" in Darwin/arm64 | Darwin/aarch64) target='aarch64-apple-darwin' os_label='macOS' ;; Linux/x86_64 | Linux/amd64) target='x86_64-unknown-linux-gnu' os_label='Linux' ;; Linux/aarch64 | Linux/arm64) target='aarch64-unknown-linux-gnu' os_label='Linux' ;; *) fail "there is no $app build for $os $arch. Builds exist for: macOS (Apple silicon), Linux (x86-64), Linux (arm64). Nothing was installed." ;; esac case $target in *-linux-gnu) if ldd --version 2>&1 | grep -qi musl; then fail "this $app build needs glibc (Debian bookworm or newer, or similar); this system uses musl. Nothing was installed." fi ;; esac tmp=$(mktemp -d 2>/dev/null || mktemp -d -t "$app-install") trap 'rm -rf "$tmp"' EXIT trap 'exit 1' HUP INT TERM # get URL FILE: prints the HTTP status; fails only when the host cannot be reached. get() { curl -sSL --proto '=https' --proto-redir '=https' -A "$ua" -o "$2" -w '%{http_code}' "$1" || fail "cannot reach $1. Nothing was installed." } need() { code=$(get "$1" "$2") [ "$code" = 200 ] || fail "downloading $1 failed (HTTP $code). Nothing was installed." } version=${ORC_VERSION:-} if [ -z "$version" ]; then code=$(get "$base/latest" "$tmp/latest") case $code in 200) ;; 404) fail "$app has no release on the download host yet. Nothing was installed. See https://orc.sieversii.ca/docs/ for news." ;; *) fail "downloading $base/latest failed (HTTP $code). Nothing was installed." ;; esac version=$(head -n 1 "$tmp/latest" | tr -d ' \r\n') fi version=${version#v} printf '%s\n' "$version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$' || fail "\"$version\" is not a version number. Nothing was installed." tarball="orc-${version}-${target}.tar.gz" sums="SHA256SUMS-${target}" sig="SHA256SUMS-${target}.sig" url="$base/$version" code=$(get "$url/$sums" "$tmp/$sums") case $code in 200) ;; 404) fail "no $os_label build in $app $version yet. Nothing was installed." ;; *) fail "downloading $url/$sums failed (HTTP $code). Nothing was installed." ;; esac need "$url/$sig" "$tmp/$sig" cat >"$tmp/allowed_signers" <<'ORC_TRUSTED_KEYS' orc-release namespaces="orc-release" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFU/ODg0J+LstSzNDO8EQGwIJwAwX9P2mpe0tbI1B4wu software-1 orc-release namespaces="orc-release" sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBOOiEywnb4pUGjcQoRa5U4oPxQV6CaMgetstDmyWtzq/uf3Ij3e737zNPHOPEGC72R3vcchdpQ2h7OYq9UMCV6UAAAAPc3NoOm9yYy1yZWxlYXNl physical-1 ORC_TRUSTED_KEYS if ! ssh-keygen -Y verify -f "$tmp/allowed_signers" -I "$identity" -n "$namespace" \ -s "$tmp/$sig" <"$tmp/$sums" >"$tmp/verify.log" 2>&1; then cat "$tmp/verify.log" >&2 fail "the signature on $sums is not from a trusted $app key (or ssh-keygen is older than OpenSSH 8.1). Nothing was installed." fi want=$(awk -v f="$tarball" '($2 == f || $2 == "*" f) && length($1) == 64 { print $1 }' "$tmp/$sums") [ -n "$want" ] || fail "$sums does not list $tarball. Nothing was installed." say "Downloading $app $version for $target..." need "$url/$tarball" "$tmp/$tarball" got=$(sha256 "$tmp/$tarball" | awk '{ print $1 }') [ "$got" = "$want" ] || fail "$tarball does not match its checksum (the download may be cut off or altered). Nothing was installed." mkdir "$tmp/x" tar -xzf "$tmp/$tarball" -C "$tmp/x" || fail "cannot unpack $tarball. Nothing was installed." [ -f "$tmp/x/$binary" ] || fail "$tarball has no $binary. Nothing was installed." dir=${ORC_INSTALL_DIR:-$HOME/.local/bin} mkdir -p "$dir" || fail "cannot create $dir. Nothing was installed." dest="$dir/$install_name" part="$dest.part.$$" if ! { cp "$tmp/x/$binary" "$part" && chmod 755 "$part" && mv -f "$part" "$dest"; }; then rm -f "$part" fail "cannot write $dest. Nothing was installed." fi say "Installed $app $version to $dest (signature and checksum checked)." case ":$PATH:" in *":$dir:"*) ;; *) say "" say "$dir is not on your PATH. Add this to your shell's startup file:" say " export PATH=\"$dir:\$PATH\"" ;; esac runtime_tools='git tmux claude' for tool in $runtime_tools; do command -v "$tool" >/dev/null 2>&1 || say "Note: $app also needs $tool, which is not on your PATH." done say "" say "Next:" say ' orc hooks install' say ' orc doctor' say ' orc --help' say " Docs: https://orc.sieversii.ca/docs/" } orc_install "$@"