feat(cli): install tht as a system command
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
#!/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,,}" == "${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"
|
||||
Reference in New Issue
Block a user