#!/bin/bash set -e # 🎯 Detect OS & package manager detect_platform() { if [[ "$OSTYPE" == "darwin"* ]]; then OS="macos"; PKG_MGR="brew" if ! command -v brew &>/dev/null; then echo "🍺 Installing Homebrew..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile eval "$(/opt/homebrew/bin/brew shellenv)" fi elif command -v apt &>/dev/null; then OS="debian"; PKG_MGR="apt" elif command -v dnf &>/dev/null; then OS="rhel"; PKG_MGR="dnf" elif command -v yum &>/dev/null; then OS="rhel"; PKG_MGR="yum" elif command -v pacman &>/dev/null; then OS="arch"; PKG_MGR="pacman" else echo "❌ Unsupported platform"; exit 1 fi echo "βœ“ Detected $OS ($PKG_MGR)" } # πŸ” Install gpg if needed (Debian/Ubuntu) install_gpg_if_needed() { if [[ "$OS" == "debian" ]] && ! command -v gpg &>/dev/null; then echo "πŸ”‘ Installing gpg..." sudo apt update && sudo apt install -y gnupg fi } # πŸ“¦ Add Fish repo (Debian/Ubuntu) add_fish_repo_debian() { echo "β€’ Adding Fish repo..." echo 'deb http://download.opensuse.org/repositories/shells:/fish:/release:/4/Debian_12/ /' | \ sudo tee /etc/apt/sources.list.d/fish.list >/dev/null curl -fsSL https://download.opensuse.org/repositories/shells:fish:release:4/Debian_12/Release.key | \ gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/fish.gpg > /dev/null sudo apt update } # 🐟 Install Fish shell install_fish() { echo "β€’ Installing Fish..." case "$OS" in debian) add_fish_repo_debian; sudo apt install -y fish ;; rhel) sudo $PKG_MGR install -y fish ;; arch) sudo pacman -Sy --noconfirm fish ;; macos) brew install fish ;; esac } # πŸ”Ž Detect if an update seems available (without doing a refresh) fish_update_available() { case "$PKG_MGR" in apt) # Compare Installed vs Candidate using current cache (no apt update) local installed candidate installed="$(dpkg-query -W -f='${Version}\n' fish 2>/dev/null || true)" candidate="$(apt-cache policy fish 2>/dev/null | awk '/Candidate:/ {print $2}')" [[ -n "$installed" && -n "$candidate" && "$candidate" != "(none)" && "$candidate" != "$installed" ]] ;; dnf|yum) # Fast check; may contact repos briefly but doesn't install $PKG_MGR -q check-update fish >/dev/null 2>&1 [[ $? -eq 100 ]] # 100 = updates available ;; pacman) # No refresh; just check queued upgrades pacman -Qu 2>/dev/null | grep -q '^fish ' ;; brew) # No brew update; check current outdated list brew outdated --quiet 2>/dev/null | grep -q '^fish$' ;; esac } # ♻️ Update flow (only prompt if an update looks available) maybe_update_fish() { echo "β€’ Checking Fish updates…" if fish_update_available; then read -rp "A newer Fish appears available. Refresh repos and update now? (y/N): " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then case "$PKG_MGR" in apt) sudo apt update sudo apt install -y fish && echo "βœ“ Fish updated" ;; dnf|yum) sudo $PKG_MGR check-update || true sudo $PKG_MGR update -y fish && echo "βœ“ Fish updated" ;; pacman) sudo pacman -Sy --noconfirm sudo pacman -S --noconfirm fish && echo "βœ“ Fish updated" ;; brew) brew update brew upgrade fish && echo "βœ“ Fish updated" ;; esac else echo "βœ“ Skipped update" fi else echo "βœ“ No update detected (based on current cache)" fi } # 🎣 Install Fisher install_fisher() { if fish -c "functions -q fisher" &>/dev/null; then echo "βœ“ Fisher already present" else echo "β€’ Installing Fisher..." # isolate stdin so curl|bash doesnt leak into fish fish -c 'curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher' /dev/null fi chsh -s "$fish_path" echo "βœ“ Fish set as default shell (applies to new sessions)" else echo "βœ“ Keeping current default shell" fi } # πŸš€ Main flow detect_platform install_gpg_if_needed if command -v fish &>/dev/null; then echo "βœ“ Fish already installed" maybe_update_fish else install_fish fi install_fisher install_plugins set_fish_default echo "βœ“ Fish + Fisher + plugins ready on $OS"