#!/bin/bash # Cross-Platform Setup Script - Install Git, Node.js, and Python # This script will install essential development tools on macOS and Raspberry Pi (Linux ARM) set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Function to print colored output print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to detect operating system detect_os() { if [[ "$OSTYPE" == "darwin"* ]]; then OS="macos" print_status "Detected: macOS" elif [[ "$OSTYPE" == "linux-gnu"* ]]; then # Check if it's Raspberry Pi if [[ $(uname -m) == "armv"* ]] || [[ $(uname -m) == "aarch64" ]] || grep -q "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then OS="raspi" print_status "Detected: Raspberry Pi (Linux ARM)" else OS="linux" print_status "Detected: Linux (x86/x64)" fi else print_error "Unsupported operating system: $OSTYPE" print_status "This script supports macOS and Raspberry Pi only" exit 1 fi } # Function to update package manager update_packages() { if [[ "$OS" == "macos" ]]; then if command_exists brew; then print_status "Updating Homebrew..." brew update fi elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then print_status "Updating package lists..." sudo apt update fi } # Function to install package manager (Homebrew for Mac) install_package_manager() { if [[ "$OS" == "macos" ]]; then if command_exists brew; then print_success "Homebrew is already installed" else print_status "Installing Homebrew..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Add Homebrew to PATH for Apple Silicon Macs if [[ $(uname -m) == "arm64" ]]; then echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile eval "$(/opt/homebrew/bin/brew shellenv)" fi fi fi # For Raspberry Pi, apt is already available } # Function to install Git install_git() { if command_exists git; then print_success "Git is already installed: $(git --version)" else print_status "Installing Git..." if [[ "$OS" == "macos" ]]; then brew install git elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then sudo apt install -y git fi print_success "Git installed successfully: $(git --version)" fi } # Function to install Node.js install_nodejs() { if command_exists node; then print_success "Node.js is already installed: $(node --version)" print_status "npm version: $(npm --version)" else print_status "Installing Node.js..." if [[ "$OS" == "macos" ]]; then brew install node elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then # Install Node.js from NodeSource repository for better ARM support curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - sudo apt install -y nodejs fi print_success "Node.js installed successfully: $(node --version)" print_status "npm version: $(npm --version)" fi } # Function to install Python install_python() { if command_exists python3; then print_success "Python3 is already installed: $(python3 --version)" else print_status "Installing Python..." if [[ "$OS" == "macos" ]]; then brew install python elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then sudo apt install -y python3 python3-pip python3-venv fi print_success "Python installed successfully: $(python3 --version)" fi # Check if pip is available if command_exists pip3; then print_success "pip3 is available: $(pip3 --version)" else print_warning "pip3 not found, installing..." if [[ "$OS" == "macos" ]]; then python3 -m ensurepip --upgrade elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then sudo apt install -y python3-pip fi fi } # Function to install build essentials (mainly for Raspberry Pi) install_build_tools() { if [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then print_status "Installing build essentials..." sudo apt install -y build-essential curl wget print_success "Build tools installed" elif [[ "$OS" == "macos" ]]; then # Xcode command line tools are usually installed with Homebrew if ! command_exists gcc; then print_status "Installing Xcode command line tools..." xcode-select --install else print_success "Build tools are available" fi fi } # Function to install synchan install_synchan() { local synchan_dir="$HOME/synchan" if [ -d "$synchan_dir" ]; then print_warning "Synchan directory already exists at $synchan_dir" read -p "Do you want to remove the existing directory and reinstall? [y/N]: " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then print_status "Removing existing synchan directory..." rm -rf "$synchan_dir" else print_status "Skipping synchan installation" return 0 fi fi print_status "Installing synchan from https://github.com/lancatlin/synchan..." # Check if git is available if ! command_exists git; then print_error "Git is required to install synchan. Please install Git first." return 1 fi # Check if yarn is available, install if not if ! command_exists yarn; then print_status "Yarn not found, installing yarn..." if command_exists npm; then npm install -g yarn else print_error "npm is required to install yarn. Please install Node.js first." return 1 fi fi # Clone the repository print_status "Cloning synchan repository..." if git clone https://github.com/lancatlin/synchan.git "$synchan_dir"; then print_success "Repository cloned successfully" else print_error "Failed to clone synchan repository" return 1 fi # Navigate to the directory and install dependencies print_status "Installing dependencies with yarn..." cd "$synchan_dir" if yarn install; then print_success "Dependencies installed successfully" print_success "Synchan installed at: $synchan_dir" print_status "To use synchan, navigate to: cd $synchan_dir" else print_error "Failed to install dependencies with yarn" return 1 fi # Return to original directory cd - > /dev/null } # Function to install actionwire install_actionwire() { local actionwire_dir="$HOME/actionwire" if [ -d "$actionwire_dir" ]; then print_warning "Actionwire directory already exists at $actionwire_dir" read -p "Do you want to remove the existing directory and reinstall? [y/N]: " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then print_status "Removing existing actionwire directory..." rm -rf "$actionwire_dir" else print_status "Skipping actionwire installation" return 0 fi fi print_status "Installing actionwire from https://github.com/lancatlin/actionwire..." # Check if git is available if ! command_exists git; then print_error "Git is required to install actionwire. Please install Git first." return 1 fi # Check if poetry is available if ! command_exists poetry; then print_status "Poetry not found, installing poetry..." if [[ "$OS" == "macos" ]]; then brew install poetry elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then # Install poetry via pip python3 -m pip install --user poetry # Add poetry to PATH if not already there if ! command_exists poetry; then echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc export PATH="$HOME/.local/bin:$PATH" fi fi print_success "Poetry installed" fi # Clone the repository print_status "Cloning actionwire repository..." if git clone https://github.com/lancatlin/actionwire.git "$actionwire_dir"; then print_success "Repository cloned successfully" else print_error "Failed to clone actionwire repository" return 1 fi # Navigate to the directory and install dependencies print_status "Installing dependencies with poetry..." cd "$actionwire_dir" if poetry install; then print_success "Dependencies installed successfully" print_success "Actionwire installed at: $actionwire_dir" print_status "To use actionwire, navigate to: cd $actionwire_dir" else print_warning "Poetry install failed, trying pip install as fallback..." if [ -f "requirements.txt" ]; then if python3 -m pip install -r requirements.txt; then print_success "Dependencies installed successfully with pip" print_success "Actionwire installed at: $actionwire_dir" print_status "To use actionwire, navigate to: cd $actionwire_dir" else print_error "Failed to install dependencies with both poetry and pip" return 1 fi elif [ -f "pyproject.toml" ]; then print_warning "pyproject.toml found but poetry failed. You may need to install dependencies manually." print_status "Try running: cd $actionwire_dir && poetry install" print_success "Actionwire cloned at: $actionwire_dir" else print_error "No requirements.txt or pyproject.toml found, and poetry install failed" return 1 fi fi # Return to original directory cd - > /dev/null } # Function to install additional useful tools install_additional_tools() { print_status "Installing additional useful development tools..." if [[ "$OS" == "macos" ]]; then # Install common tools brew install curl wget jq tree # Install development tools brew install --cask visual-studio-code brew install --cask iterm2 print_success "Additional tools installed" elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then # Install common tools sudo apt install -y curl wget jq tree vim nano htop # Install VS Code for ARM if available if [[ $(uname -m) == "aarch64" ]]; then print_status "Installing VS Code for ARM64..." wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg sudo install -o root -g root -m 644 packages.microsoft.gpg /etc/apt/trusted.gpg.d/ sudo sh -c 'echo "deb [arch=arm64,armhf,amd64 signed-by=/etc/apt/trusted.gpg.d/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list' sudo apt update sudo apt install -y code else print_warning "VS Code may not be available for this ARM architecture" fi print_success "Additional tools installed" fi } # Function to verify installations verify_installations() { print_status "Verifying installations..." echo "" print_status "=== Installation Summary ===" if command_exists git; then print_success "✓ Git: $(git --version)" else print_error "✗ Git installation failed" fi if command_exists node; then print_success "✓ Node.js: $(node --version)" print_success "✓ npm: $(npm --version)" else print_error "✗ Node.js installation failed" fi if command_exists python3; then print_success "✓ Python3: $(python3 --version)" if command_exists pip3; then print_success "✓ pip3: $(pip3 --version)" fi else print_error "✗ Python3 installation failed" fi if [[ "$OS" == "macos" ]]; then if command_exists brew; then print_success "✓ Homebrew: $(brew --version | head -n1)" else print_error "✗ Homebrew installation failed" fi fi # Check synchan installation if [ -d "$HOME/synchan" ]; then print_success "✓ Synchan: Installed at $HOME/synchan" else print_warning "⚠ Synchan: Not installed" fi # Check actionwire installation if [ -d "$HOME/actionwire" ]; then print_success "✓ Actionwire: Installed at $HOME/actionwire" else print_warning "⚠ Actionwire: Not installed" fi } # Main execution main() { print_status "Starting cross-platform development environment setup..." print_status "This script will install: Git, Node.js, Python, and optionally synchan and actionwire" echo "" # Detect operating system detect_os # Update package manager update_packages # Install package manager if needed (Homebrew for Mac) install_package_manager # Install build tools install_build_tools # Install core development tools install_git install_nodejs install_python # Ask if user wants to install synchan echo "" read -p "Do you want to install synchan from GitHub? [y/N]: " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then install_synchan fi # Ask if user wants to install actionwire echo "" read -p "Do you want to install actionwire from GitHub? [y/N]: " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then install_actionwire fi # Ask if user wants additional tools echo "" read -p "Do you want to install additional development tools? [y/N]: " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then install_additional_tools fi # Verify all installations verify_installations echo "" print_success "Setup complete! Your development environment is ready." if [[ "$OS" == "macos" ]]; then print_status "You may need to restart your terminal or run 'source ~/.zprofile' to use the new tools." elif [[ "$OS" == "raspi" ]] || [[ "$OS" == "linux" ]]; then print_status "You may need to restart your terminal or run 'source ~/.bashrc' to use the new tools." print_status "If poetry was installed, you may need to restart your terminal for PATH changes to take effect." fi } # Run main function main "$@"