#!/bin/sh # Install the DUAL CLI. # # curl -fsSL https://get.dual.network | sh # # Environment: # DUAL_VERSION install a specific tag instead of the latest, e.g. v1.2.0 # DUAL_INSTALL_DIR where to put the binary (default: $HOME/.local/bin) # DUAL_REPO release repository (default: DUALorg/dual-cli) set -eu REPO="${DUAL_REPO:-DUALorg/dual-cli}" BIN=dual INSTALL_DIR="${DUAL_INSTALL_DIR:-$HOME/.local/bin}" die() { printf '%s\n' "error: $*" >&2; exit 1; } command -v curl >/dev/null 2>&1 || die "curl is required" command -v tar >/dev/null 2>&1 || die "tar is required" # Pick the checksum tool. Linux ships sha256sum, macOS ships shasum. if command -v sha256sum >/dev/null 2>&1; then checksum() { sha256sum "$1" | awk '{print $1}'; } elif command -v shasum >/dev/null 2>&1; then checksum() { shasum -a 256 "$1" | awk '{print $1}'; } else die "need sha256sum or shasum to verify the download" fi os=$(uname -s | tr '[:upper:]' '[:lower:]') case "$os" in darwin|linux) ;; *) die "unsupported operating system: $os" ;; esac arch=$(uname -m) case "$arch" in x86_64|amd64) arch=amd64 ;; arm64|aarch64) arch=arm64 ;; *) die "unsupported architecture: $arch" ;; esac version="${DUAL_VERSION:-}" if [ -z "$version" ]; then version=$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" \ | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1) [ -n "$version" ] || die "could not find the latest release of $REPO" fi tarball="${BIN}_${version}_${os}_${arch}.tar.gz" base="https://github.com/$REPO/releases/download/$version" tmp=$(mktemp -d) # shellcheck disable=SC2064 trap "rm -rf '$tmp'" EXIT INT TERM printf 'downloading %s %s (%s/%s)\n' "$BIN" "$version" "$os" "$arch" curl -fsSL -o "$tmp/$tarball" "$base/$tarball" || die "download failed: $base/$tarball" curl -fsSL -o "$tmp/checksums.txt" "$base/checksums.txt" || die "download failed: $base/checksums.txt" # Verifying is not optional: this script runs whatever it downloads. expected=$(awk -v f="$tarball" '$2 == f || $2 == "*" f {print $1}' "$tmp/checksums.txt" | head -1) [ -n "$expected" ] || die "checksums.txt has no entry for $tarball" actual=$(checksum "$tmp/$tarball") [ "$expected" = "$actual" ] || die "checksum mismatch for $tarball expected $expected got $actual" tar -xzf "$tmp/$tarball" -C "$tmp" [ -f "$tmp/$BIN" ] || die "the archive does not contain $BIN" mkdir -p "$INSTALL_DIR" cp "$tmp/$BIN" "$INSTALL_DIR/$BIN.tmp" chmod 0755 "$INSTALL_DIR/$BIN.tmp" mv -f "$INSTALL_DIR/$BIN.tmp" "$INSTALL_DIR/$BIN" printf 'installed %s to %s\n' "$BIN" "$INSTALL_DIR/$BIN" case ":${PATH}:" in *":$INSTALL_DIR:"*) printf 'run "%s help" to get started\n' "$BIN" ;; *) printf '\n%s is not on your PATH. Add this to your shell profile:\n\n export PATH="%s:$PATH"\n\n' "$INSTALL_DIR" "$INSTALL_DIR" ;; esac