| 1 | #!/bin/sh |
| 2 | # Installs bench51 (the bench51-gui desktop app and the bench51 terminal app) |
| 3 | # from the GitHub releases, on Linux and macOS. |
| 4 | # |
| 5 | # curl -fsSL https://raw.githubusercontent.com/krolyxon/bench51/master/install.sh | sh |
| 6 | # curl -fsSL https://raw.githubusercontent.com/krolyxon/bench51/master/install.sh | sh -s -- --dir /usr/local/bin |
| 7 | # |
| 8 | # Run with --help for all options. On Windows, use install.ps1. |
| 9 | |
| 10 | set -eu |
| 11 | |
| 12 | REPO=krolyxon/bench51 |
| 13 | VERSION=${BENCH51_VERSION:-latest} |
| 14 | DIR=${BENCH51_INSTALL_DIR:-$HOME/.local/bin} |
| 15 | ARCHIVE= |
| 16 | DESKTOP=1 |
| 17 | UNINSTALL=0 |
| 18 | |
| 19 | DATA=${XDG_DATA_HOME:-$HOME/.local/share} |
| 20 | APPS=$DATA/applications |
| 21 | ICONS=$DATA/icons/hicolor/scalable/apps |
| 22 | |
| 23 | usage() { |
| 24 | cat <<EOF |
| 25 | Install bench51 from https://github.com/$REPO/releases |
| 26 | |
| 27 | Usage: install.sh [options] |
| 28 | |
| 29 | --version <tag> release to install, e.g. v0.2.0 (default: latest) |
| 30 | --dir <path> where to put the binaries (default: ~/.local/bin) |
| 31 | --archive <file> install from a downloaded bench51-<target>.tar.gz |
| 32 | --no-desktop on Linux, skip the application menu entry and icon |
| 33 | --uninstall remove bench51 from --dir and the menu |
| 34 | -h, --help show this help |
| 35 | |
| 36 | The environment variables BENCH51_VERSION and BENCH51_INSTALL_DIR set the |
| 37 | defaults for --version and --dir. |
| 38 | EOF |
| 39 | } |
| 40 | |
| 41 | say() { printf 'bench51: %s\n' "$*"; } |
| 42 | die() { |
| 43 | printf 'bench51: error: %s\n' "$*" >&2 |
| 44 | exit 1 |
| 45 | } |
| 46 | |
| 47 | while [ $# -gt 0 ]; do |
| 48 | case $1 in |
| 49 | --version) [ $# -ge 2 ] || die "--version needs a value"; VERSION=$2; shift 2 ;; |
| 50 | --version=*) VERSION=${1#*=}; shift ;; |
| 51 | --dir) [ $# -ge 2 ] || die "--dir needs a value"; DIR=$2; shift 2 ;; |
| 52 | --dir=*) DIR=${1#*=}; shift ;; |
| 53 | --archive) [ $# -ge 2 ] || die "--archive needs a value"; ARCHIVE=$2; shift 2 ;; |
| 54 | --archive=*) ARCHIVE=${1#*=}; shift ;; |
| 55 | --no-desktop) DESKTOP=0; shift ;; |
| 56 | --uninstall) UNINSTALL=1; shift ;; |
| 57 | -h | --help) usage; exit 0 ;; |
| 58 | *) die "unknown option: $1 (see --help)" ;; |
| 59 | esac |
| 60 | done |
| 61 | |
| 62 | refresh_menu() { |
| 63 | if command -v update-desktop-database >/dev/null 2>&1; then |
| 64 | update-desktop-database -q "$APPS" 2>/dev/null || true |
| 65 | fi |
| 66 | } |
| 67 | |
| 68 | if [ "$UNINSTALL" = 1 ]; then |
| 69 | rm -f "$DIR/bench51" "$DIR/bench51-gui" "$APPS/bench51-gui.desktop" "$ICONS/bench51-gui.svg" |
| 70 | refresh_menu |
| 71 | say "removed bench51 from $DIR" |
| 72 | exit 0 |
| 73 | fi |
| 74 | |
| 75 | # ---- Which build fits this machine ---- |
| 76 | |
| 77 | os=$(uname -s) |
| 78 | arch=$(uname -m) |
| 79 | case $os in |
| 80 | Linux) os=unknown-linux-gnu ;; |
| 81 | Darwin) os=apple-darwin ;; |
| 82 | *) die "no prebuilt binaries for $os; on Windows use install.ps1" ;; |
| 83 | esac |
| 84 | case $arch in |
| 85 | x86_64 | amd64) arch=x86_64 ;; |
| 86 | aarch64 | arm64) arch=aarch64 ;; |
| 87 | *) die "no prebuilt binaries for $arch; build from source with: cargo install --git https://github.com/$REPO bench51-gui" ;; |
| 88 | esac |
| 89 | TARGET=$arch-$os |
| 90 | NAME=bench51-$TARGET.tar.gz |
| 91 | |
| 92 | download() { |
| 93 | if command -v curl >/dev/null 2>&1; then |
| 94 | curl --proto '=https' --tlsv1.2 -fsSL -o "$2" "$1" |
| 95 | elif command -v wget >/dev/null 2>&1; then |
| 96 | wget -q --https-only -O "$2" "$1" |
| 97 | else |
| 98 | die "neither curl nor wget is installed" |
| 99 | fi |
| 100 | } |
| 101 | |
| 102 | sha256() { |
| 103 | if command -v sha256sum >/dev/null 2>&1; then |
| 104 | sha256sum "$1" | cut -d ' ' -f 1 |
| 105 | elif command -v shasum >/dev/null 2>&1; then |
| 106 | shasum -a 256 "$1" | cut -d ' ' -f 1 |
| 107 | else |
| 108 | die "neither sha256sum nor shasum is installed to verify the download" |
| 109 | fi |
| 110 | } |
| 111 | |
| 112 | TMP=$(mktemp -d 2>/dev/null || mktemp -d -t bench51) |
| 113 | trap 'rm -rf "$TMP"' EXIT |
| 114 | trap 'exit 130' INT TERM |
| 115 | |
| 116 | # ---- Download and verify ---- |
| 117 | |
| 118 | if [ -z "$ARCHIVE" ]; then |
| 119 | if [ "$VERSION" = latest ]; then |
| 120 | BASE=https://github.com/$REPO/releases/latest/download |
| 121 | else |
| 122 | case $VERSION in v*) ;; *) VERSION=v$VERSION ;; esac |
| 123 | BASE=https://github.com/$REPO/releases/download/$VERSION |
| 124 | fi |
| 125 | say "downloading $NAME ($VERSION)" |
| 126 | download "$BASE/$NAME" "$TMP/$NAME" || die "could not download $BASE/$NAME" |
| 127 | download "$BASE/SHA256SUMS" "$TMP/SHA256SUMS" || die "could not download the checksums" |
| 128 | expected=$(grep " [* ]*$NAME\$" "$TMP/SHA256SUMS" | cut -d ' ' -f 1) |
| 129 | [ -n "$expected" ] || die "$NAME is not listed in SHA256SUMS" |
| 130 | [ "$(sha256 "$TMP/$NAME")" = "$expected" ] || die "checksum mismatch for $NAME" |
| 131 | ARCHIVE=$TMP/$NAME |
| 132 | fi |
| 133 | [ -f "$ARCHIVE" ] || die "no such archive: $ARCHIVE" |
| 134 | |
| 135 | mkdir "$TMP/x" |
| 136 | tar -xzf "$ARCHIVE" -C "$TMP/x" |
| 137 | SRC=$(find "$TMP/x" -type f -name bench51-gui | head -n 1) |
| 138 | [ -n "$SRC" ] || die "the archive has no bench51-gui" |
| 139 | SRC=$(dirname "$SRC") |
| 140 | [ -f "$SRC/bench51" ] || die "the archive has no bench51" |
| 141 | |
| 142 | # ---- Install ---- |
| 143 | |
| 144 | mkdir -p "$DIR" |
| 145 | for bin in bench51 bench51-gui; do |
| 146 | cp "$SRC/$bin" "$DIR/$bin.tmp" |
| 147 | chmod 755 "$DIR/$bin.tmp" |
| 148 | mv -f "$DIR/$bin.tmp" "$DIR/$bin" |
| 149 | done |
| 150 | say "installed bench51 and bench51-gui to $DIR" |
| 151 | |
| 152 | if [ "$DESKTOP" = 1 ] && [ "$(uname -s)" = Linux ] && [ -f "$SRC/share/applications/bench51-gui.desktop" ]; then |
| 153 | mkdir -p "$APPS" "$ICONS" |
| 154 | # Launchers don't always see ~/.local/bin on PATH: point at the binary. |
| 155 | exec_path=$(printf '%s' "$DIR/bench51-gui" | sed 's/[\\&|]/\\&/g') |
| 156 | sed "s|^Exec=bench51-gui|Exec=\"$exec_path\"|" \ |
| 157 | "$SRC/share/applications/bench51-gui.desktop" >"$APPS/bench51-gui.desktop" |
| 158 | cp "$SRC/share/icons/hicolor/scalable/apps/bench51-gui.svg" "$ICONS/bench51-gui.svg" |
| 159 | refresh_menu |
| 160 | say "added bench51 to the application menu" |
| 161 | fi |
| 162 | |
| 163 | "$DIR/bench51" --version |
| 164 | case ":$PATH:" in |
| 165 | *":$DIR:"*) say "run bench51-gui for the desktop app, or bench51 in a terminal" ;; |
| 166 | *) say "$DIR is not on your PATH; add it, e.g. in ~/.profile: export PATH=\"$DIR:\$PATH\"" ;; |
| 167 | esac |