Files

104 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
repository_root=$(cd "$(dirname "$0")/.." && pwd)
install_directory="${THT_INSTALL_DIRECTORY:-/usr/local/bin}"
staging_root=$(mktemp -d)
trap 'rm -rf "$staging_root"' EXIT HUP INT TERM
fail() {
echo "install-tht.sh: $*" >&2
exit 1
}
sha256() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" | awk '{print $1}'
elif command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$1" | awk '{print $1}'
else
fail "SHA-256 verification requires sha256sum or shasum"
fi
}
platform_artifact_name() {
local system architecture
system=$(uname -s)
architecture=$(uname -m)
case "$system" in
Darwin) system=darwin ;;
Linux) system=linux ;;
*) fail "unsupported operating system: $system (supported: macOS and Linux)" ;;
esac
case "$architecture" in
x86_64|amd64) architecture=amd64 ;;
arm64|aarch64) architecture=arm64 ;;
*) fail "unsupported processor architecture: $architecture (supported: amd64 and arm64)" ;;
esac
printf 'tht-%s-%s\n' "$system" "$architecture"
}
validate_packaged_artifact() {
local artifact=$1 expected actual
expected=${THT_BUILD_ARTIFACT_SHA256:-}
[[ "$expected" =~ ^[[:xdigit:]]{64}$ ]] || fail "THT_BUILD_ARTIFACT_SHA256 must be a 64-character SHA-256 digest"
actual=$(sha256 "$artifact")
actual=$(printf '%s' "$actual" | tr '[:upper:]' '[:lower:]')
expected=$(printf '%s' "$expected" | tr '[:upper:]' '[:lower:]')
[[ "$actual" == "$expected" ]] || fail "packaged tht artifact checksum does not match"
}
build_artifact() {
local build_output="$staging_root/build"
mkdir -p "$build_output"
THT_THT_OUTPUT_DIRECTORY="$build_output" bash "$repository_root/scripts/build-tht.sh" --all >&2
printf '%s/%s\n' "$build_output" "$(platform_artifact_name)"
}
install_atomically() {
local destination_directory=$1 source_file=$2
local temporary_destination
if mkdir -p "$destination_directory" 2>/dev/null && [[ -w "$destination_directory" ]]; then
temporary_destination=$(mktemp "$destination_directory/.tht.XXXXXX")
cp "$source_file" "$temporary_destination"
chmod 0755 "$temporary_destination"
mv -f "$temporary_destination" "$destination_directory/tht"
return
fi
command -v sudo >/dev/null 2>&1 || fail "cannot write to $destination_directory and sudo is unavailable"
sudo sh -c '
set -eu
destination_directory=$1
source_file=$2
mkdir -p "$destination_directory"
temporary_destination=$(mktemp "$destination_directory/.tht.XXXXXX")
trap "rm -f \"$temporary_destination\"" EXIT HUP INT TERM
cp "$source_file" "$temporary_destination"
chmod 0755 "$temporary_destination"
mv -f "$temporary_destination" "$destination_directory/tht"
' sh "$destination_directory" "$source_file"
}
[[ "$install_directory" == /* ]] || fail "THT_INSTALL_DIRECTORY must be an absolute path"
artifact_name=$(platform_artifact_name)
if [[ -n "${THT_BUILD_ARTIFACT:-}" ]]; then
source_artifact=$THT_BUILD_ARTIFACT
[[ -f "$source_artifact" ]] || fail "THT_BUILD_ARTIFACT is not a regular file"
validate_packaged_artifact "$source_artifact"
else
source_artifact=$(build_artifact)
fi
[[ -s "$source_artifact" ]] || fail "native artifact is missing: $artifact_name"
staged_binary="$staging_root/tht"
cp "$source_artifact" "$staged_binary"
chmod 0755 "$staged_binary"
"$staged_binary" --help >/dev/null || fail "native artifact did not pass its help check"
install_atomically "$install_directory" "$staged_binary"
resolved_command=$(command -v tht || true)
[[ "$resolved_command" == "$install_directory/tht" ]] || fail "installed tht is not resolvable at $install_directory/tht; add $install_directory to PATH and open a new terminal"
"$install_directory/tht" --help >/dev/null || fail "installed tht did not pass its help check"
printf 'Installed tht at %s/tht\n' "$install_directory"