#!/bin/sh # obm install script - curl | sh one-liner installer # Usage: curl -fsSL https://raw.githubusercontent.com/openboatmobile/obm/main/scripts/install.sh | sh # Or: curl -fsSL https://raw.githubusercontent.com/openboatmobile/obm/main/scripts/install.sh | sh -s -- v1.2.3 set -e # Configuration GITHUB_REPO="openboatmobile/obm" BINARY_NAME="obm" INSTALL_DIR_DEFAULT="/usr/local/bin" # Colors for output (only if terminal) if [ -t 1 ]; then RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color else RED='' GREEN='' YELLOW='' BLUE='' NC='' fi info() { printf "${BLUE}==>${NC} %s\n" "$1" } success() { printf "${GREEN}✓${NC} %s\n" "$1" } warn() { printf "${YELLOW}!${NC} %s\n" "$1" >&2 } error() { printf "${RED}✗${NC} %s\n" "$1" >&2 exit 1 } # Detect operating system detect_os() { case "$(uname -s)" in Linux*) echo "linux";; Darwin*) echo "darwin";; CYGWIN*) echo "windows";; MINGW*) echo "windows";; MSYS*) echo "windows";; *) error "Unsupported OS: $(uname -s)";; esac } # Detect architecture detect_arch() { arch="$(uname -m)" case "$arch" in x86_64|amd64) echo "amd64";; aarch64|arm64) echo "arm64";; armv7l|armv7) echo "arm64";; # Map armv7 to arm64 (may not work) armv6) echo "arm64";; # Map armv6 to arm64 (may not work) i386|i686) echo "amd64";; # Map 32-bit to amd64 (may not work) *) error "Unsupported architecture: $arch";; esac } # Get latest release version from GitHub API get_latest_version() { api_url="https://api.github.com/repos/${GITHUB_REPO}/releases/latest" # Try curl first, fall back to wget if command -v curl >/dev/null 2>&1; then version=$(curl -fsSL "$api_url" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') elif command -v wget >/dev/null 2>&1; then version=$(wget -qO- "$api_url" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') else error "Neither curl nor wget found. Please install one of them." fi if [ -z "$version" ]; then error "Could not determine latest version" fi echo "$version" } # Download the binary download_binary() { version="$1" os="$2" arch="$3" dest="$4" # Build download URL platform="${os}-${arch}" if [ "$os" = "windows" ]; then archive_name="obm-${platform}.zip" binary_name="obm.exe" else archive_name="obm-${platform}.tar.gz" binary_name="obm" fi download_url="https://github.com/${GITHUB_REPO}/releases/download/${version}/${archive_name}" info "Downloading $archive_name..." # Create temp directory tmp_dir=$(mktemp -d) trap 'rm -rf "$tmp_dir"' EXIT archive_path="${tmp_dir}/${archive_name}" # Download if command -v curl >/dev/null 2>&1; then if ! curl -fsSL "$download_url" -o "$archive_path"; then error "Failed to download from $download_url" fi elif command -v wget >/dev/null 2>&1; then if ! wget -q "$download_url" -O "$archive_path"; then error "Failed to download from $download_url" fi fi # Verify download if [ ! -f "$archive_path" ] || [ ! -s "$archive_path" ]; then error "Download failed or file is empty" fi info "Extracting..." # Extract if [ "$os" = "windows" ]; then if command -v unzip >/dev/null 2>&1; then if ! unzip -q "$archive_path" -d "$tmp_dir"; then error "Failed to extract zip archive" fi else error "unzip not found. Please install unzip." fi else if ! tar -xzf "$archive_path" -C "$tmp_dir"; then error "Failed to extract tar.gz archive" fi fi # Find the binary (it may be in a subdirectory or at root) extracted_binary=$(find "$tmp_dir" -name "$binary_name" -type f | head -n1) if [ -z "$extracted_binary" ]; then error "Binary not found in archive" fi # Move to destination mv "$extracted_binary" "$dest" chmod +x "$dest" } # Check if we have write permission to install directory check_install_dir() { dir="$1" if [ -d "$dir" ]; then # Directory exists, check write permission if [ ! -w "$dir" ]; then return 1 fi else # Directory doesn't exist, check parent parent=$(dirname "$dir") if [ ! -w "$parent" ]; then return 1 fi fi return 0 } # Main installation logic main() { version="" # Parse arguments while [ $# -gt 0 ]; do case "$1" in v*) version="$1" shift ;; *) warn "Unknown argument: $1" shift ;; esac done # Detect platform os=$(detect_os) arch=$(detect_arch) info "Detected platform: ${os}-${arch}" # Get version if not specified if [ -z "$version" ]; then info "Fetching latest version..." version=$(get_latest_version) fi info "Installing ${BINARY_NAME} ${version}" # Determine install directory install_dir="" binary_path="" # Try default locations in order for dir in "$INSTALL_DIR_DEFAULT" "/usr/bin" "$HOME/.local/bin" "$HOME/bin"; do if check_install_dir "$dir"; then install_dir="$dir" break fi done # If no writable system directory, use home directory if [ -z "$install_dir" ]; then info "No writable system directory found" # Create ~/.local/bin if it doesn't exist install_dir="$HOME/.local/bin" mkdir -p "$install_dir" success "Created $install_dir" # Check if ~/.local/bin is in PATH case ":$PATH:" in *":$install_dir:"*) ;; *) warn "~/.local/bin is not in your PATH" warn "Add 'export PATH=\"\$HOME/.local/bin:\$PATH\"' to your shell config" ;; esac fi binary_path="${install_dir}/${BINARY_NAME}" # Check for existing installation if [ -f "$binary_path" ]; then warn "Removing existing installation at $binary_path" rm -f "$binary_path" fi # Download and install download_binary "$version" "$os" "$arch" "$binary_path" # Verify installation if [ ! -f "$binary_path" ]; then error "Installation failed - binary not found at $binary_path" fi success "Installed ${BINARY_NAME} to ${binary_path}" # Show version installed_version=$("$binary_path" version 2>/dev/null || echo "unknown") if [ "$installed_version" != "unknown" ]; then success "Version: $installed_version" fi # Final message echo "" success "Installation complete!" info "Run '${BINARY_NAME} --help' to get started" # Reminder about PATH if needed case ":$PATH:" in *":$install_dir:"*) ;; *) echo "" warn "To use ${BINARY_NAME}, add ${install_dir} to your PATH:" echo " export PATH=\"${install_dir}:\$PATH\"" echo "" warn "Or add to your shell config (~/.bashrc, ~/.zshrc):" echo " echo 'export PATH=\"${install_dir}:\$PATH\"' >> ~/.bashrc" ;; esac } # Run main main "$@"