#!/bin/sh set -eu INSTALL_DIR="${AMIKA_INSTALL_DIR:-/usr/local/bin}" GITHUB_REPO="gofixpoint/amika" DEFAULT_VERSION="0.8.1" INSTALL_VERSION="$DEFAULT_VERSION" DRY_RUN=false usage() { cat <&2 exit 1 fi INSTALL_VERSION="$2" shift ;; --dry-run) DRY_RUN=true ;; *) echo "Unknown argument: $arg" >&2 usage >&2 exit 1 ;; esac shift done } detect_platform() { OS="$(uname -s)" case "$OS" in Linux) OS="linux" ;; Darwin) OS="darwin" ;; *) echo "Error: unsupported operating system: $OS" >&2 exit 1 ;; esac ARCH="$(uname -m)" case "$ARCH" in x86_64|amd64) ARCH="amd64" ;; aarch64|arm64) ARCH="arm64" ;; *) echo "Error: unsupported architecture: $ARCH" >&2 exit 1 ;; esac } set_install_version() { VERSION="${INSTALL_VERSION#v}" TAG="amika@v${VERSION}" echo "Installing amika release: ${TAG}" } download_and_extract() { TMPDIR_INSTALL="$(mktemp -d)" trap 'rm -rf "$TMPDIR_INSTALL"' EXIT echo "Downloading ${DOWNLOAD_URL}..." fetch_url "$DOWNLOAD_URL" > "${TMPDIR_INSTALL}/${ARCHIVE_NAME}" verify_checksum "${TMPDIR_INSTALL}/${ARCHIVE_NAME}" echo "Extracting..." tar -xzf "${TMPDIR_INSTALL}/${ARCHIVE_NAME}" -C "$TMPDIR_INSTALL" BINARY_PATH="${TMPDIR_INSTALL}/${ARCHIVE_BASE}/amika" if [ ! -f "$BINARY_PATH" ]; then echo "Error: expected binary not found at ${ARCHIVE_BASE}/amika in archive" >&2 exit 1 fi # Remove macOS quarantine attribute if present if [ "$OS" = "darwin" ]; then xattr -d com.apple.quarantine "$BINARY_PATH" 2>/dev/null || true fi } install_binary() { ensure_install_dir DEST_PATH="${INSTALL_DIR}/amika" if [ -w "$INSTALL_DIR" ]; then install -m 0755 "$BINARY_PATH" "$DEST_PATH" else echo "Installing to ${DEST_PATH} (requires sudo)..." sudo install -m 0755 "$BINARY_PATH" "$DEST_PATH" fi } ensure_install_dir() { if [ -d "$INSTALL_DIR" ]; then return 0 fi if [ -e "$INSTALL_DIR" ]; then echo "Error: install path exists and is not a directory: $INSTALL_DIR" >&2 exit 1 fi if mkdir -p "$INSTALL_DIR" 2>/dev/null; then return 0 fi echo "Creating install directory ${INSTALL_DIR} (requires sudo)..." sudo mkdir -p "$INSTALL_DIR" } verify_checksum() { archive_path="$1" checksums_path="${TMPDIR_INSTALL}/checksums.txt" echo "Verifying checksum..." fetch_url "$CHECKSUMS_URL" > "$checksums_path" checksum_line="$(grep " ${ARCHIVE_NAME}\$" "$checksums_path" || true)" if [ -z "$checksum_line" ]; then echo "Error: checksum for ${ARCHIVE_NAME} not found in checksums.txt" >&2 exit 1 fi expected_checksum="$(printf '%s\n' "$checksum_line" | awk '{print $1}')" actual_checksum="$(compute_sha256 "$archive_path")" if [ "$expected_checksum" != "$actual_checksum" ]; then echo "Error: checksum mismatch for ${ARCHIVE_NAME}" >&2 exit 1 fi } compute_sha256() { file_path="$1" if command -v sha256sum >/dev/null 2>&1; then sha256sum "$file_path" | awk '{print $1}' elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$file_path" | awk '{print $1}' else echo "Error: neither sha256sum nor shasum found. Please install one of them." >&2 exit 1 fi } fetch_url() { url="$1" if command -v curl >/dev/null 2>&1; then curl -fsSL "$url" elif command -v wget >/dev/null 2>&1; then wget -qO- "$url" else echo "Error: neither curl nor wget found. Please install one of them." >&2 exit 1 fi } main "$@"