#!/usr/bin/env bash set -e REPO="monto-fe/smtp-probe" BINARY="smtp-probe" VERSION="${VERSION:-latest}" info() { echo -e "\033[1;34m$1\033[0m" >&2 } warn() { echo -e "\033[1;33m$1\033[0m" >&2 } error() { echo -e "\033[1;31m$1\033[0m" >&2 exit 1 } detect_os() { local os os="$(uname -s)" case "${os}" in Linux*) echo "linux";; Darwin*) echo "darwin";; MINGW*|MSYS*|CYGWIN*) echo "windows";; *) error "Unsupported operating system: ${os}";; esac } detect_arch() { local arch arch="$(uname -m)" case "${arch}" in x86_64|amd64) echo "amd64";; arm64|aarch64) echo "arm64";; *) error "Unsupported architecture: ${arch}";; esac } detect_install_dir() { if [ -n "${INSTALL_DIR}" ]; then echo "${INSTALL_DIR}" return fi local candidates=( /usr/local/bin /usr/bin "${HOME}/.local/bin" ) for dir in "${candidates[@]}"; do if [[ ":$PATH:" == *":${dir}:"* ]]; then if [ -w "${dir}" ] 2>/dev/null || [ "$(id -u)" = "0" ]; then echo "${dir}" return fi fi done echo "${HOME}/.local/bin" } get_latest_version() { curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' } download_binary() { local os="$1" local arch="$2" local version="$3" local url="https://github.com/${REPO}/releases/download/${version}/${BINARY}-${os}-${arch}.tar.gz" local tmp_dir tmp_dir="$(mktemp -d)" info "Downloading ${BINARY} ${version} for ${os}/${arch}..." if ! curl -fsSL -o "${tmp_dir}/${BINARY}.tar.gz" "${url}"; then error "Failed to download ${url}" fi tar -xzf "${tmp_dir}/${BINARY}.tar.gz" -C "${tmp_dir}" echo "${tmp_dir}/${BINARY}" } install_binary() { local binary_path="$1" local install_dir="$2" mkdir -p "${install_dir}" if [ -w "${install_dir}" ] 2>/dev/null; then mv "${binary_path}" "${install_dir}/${BINARY}" chmod +x "${install_dir}/${BINARY}" echo "${install_dir}" else warn "Permission denied for ${install_dir}, trying with sudo..." sudo mkdir -p "${install_dir}" sudo mv "${binary_path}" "${install_dir}/${BINARY}" sudo chmod +x "${install_dir}/${BINARY}" echo "${install_dir}" fi } ensure_in_path() { local install_dir="$1" if [[ ":$PATH:" == *":${install_dir}:"* ]]; then return 0 fi local shell_profile="" if [ -n "$ZSH_VERSION" ] || [ "$SHELL" = "/bin/zsh" ]; then shell_profile="${HOME}/.zshrc" elif [ -n "$BASH_VERSION" ] || [ "$SHELL" = "/bin/bash" ]; then shell_profile="${HOME}/.bashrc" else shell_profile="${HOME}/.profile" fi local path_line="export PATH=\"${install_dir}:\$PATH\"" if [ -f "${shell_profile}" ] && grep -qF "${install_dir}" "${shell_profile}" 2>/dev/null; then warn "\n${install_dir} already referenced in ${shell_profile}, but not in current PATH." warn "Run: source ${shell_profile}" return 0 fi echo "${path_line}" >> "${shell_profile}" export PATH="${install_dir}:${PATH}" info "Added ${install_dir} to PATH in ${shell_profile}" } main() { info "Installing ${BINARY}...\n" local os arch version target_dir tmp_binary install_dir os="$(detect_os)" arch="$(detect_arch)" target_dir="$(detect_install_dir)" if [ "${VERSION}" = "latest" ]; then version="$(get_latest_version)" if [ -z "${version}" ]; then error "Failed to fetch latest version" fi else version="${VERSION}" fi info "Detected: ${os}/${arch}" info "Version: ${version}" info "Install target: ${target_dir}\n" tmp_binary="$(download_binary "${os}" "${arch}" "${version}")" install_dir="$(install_binary "${tmp_binary}" "${target_dir}")" rm -rf "$(dirname "${tmp_binary}")" ensure_in_path "${install_dir}" info "\n✓ ${BINARY} ${version} installed successfully to ${install_dir}/${BINARY}\n" info "Run 'smtp-probe --help' to get started.\n" } main "$@"