#!/bin/bash set -e LOCALBIN=$HOME/.local/bin # --- Helpers --- info() { printf "\033[1;34m%s\033[0m\n" "󰋼 $*"; } warn() { printf "\033[1;33m%s\033[0m\n" "󰅚 $*"; } error() { printf "\033[1;31m%s\033[0m\n" "󰅙 $*"; } success() { printf "\033[1;32m%s\033[0m\n" "󰄬 $*"; } arch() { case "$(uname -m)" in x86_64) echo "x86_64" ;; aarch64) echo "aarch64" ;; armv7l) echo "armhf" ;; *) echo "unknown" ;; esac } # --- Check --- check_all() { local missing=() for cmd in zsh git curl jq fzf starship eza bat delta fastfetch dotstate lazygit lazydocker; do command -v "$cmd" &>/dev/null || missing+=("$cmd") done echo "${missing[@]}" } # --- Update --- update() { $LOCALBIN/dotstate activate &>/dev/null || true sed -i.bak 's/^repo_mode\s*=\s*".*"/repo_mode = "Local"/' ~/.config/dotstate/config.toml &>/dev/null || echo 'repo_mode = "Local"' >> ~/.config/dotstate/config.toml &>/dev/null $LOCALBIN/dotstate doctor --fix &>/dev/null || true $LOCALBIN/dotstate activate &>/dev/null || true } # --- Install --- install_pkgs() { if command -v pacman &>/dev/null; then sudo pacman -S --noconfirm "$@" elif command -v dnf &>/dev/null; then sudo dnf install -y "$@" elif command -v apt &>/dev/null; then sudo apt update -qq && sudo apt install -y "$@" elif command -v zypper &>/dev/null; then sudo zypper install -y "$@" elif command -v apk &>/dev/null; then sudo apk add "$@" else return 1 fi } install_binary() { local name="$1" local arch arch=$(arch) mkdir -p $HOME/.config/zsh case "$name" in starship) info "installing starship" curl -sS https://starship.rs/install.sh | sh -s -- -y ;; eza) info "installing eza" local url="https://github.com/eza-community/eza/releases/latest/download/eza-${arch}-unknown-linux-musl.tar.gz" curl -sSfL "$url" | sudo tar xz -C /usr/local/bin ;; bat) info "installing bat" local url="https://github.com/sharkdp/bat/releases/latest/download/bat-${arch}-unknown-linux-musl.tar.gz" curl -sSfL "$url" | sudo tar xz --strip-components=1 -C /usr/local/bin "bat-${arch}-unknown-linux-musl/bat" ;; delta) info "installing delta" local url="https://github.com/dandavison/delta/releases/latest/download/delta-${arch}-unknown-linux-musl.tar.gz" curl -sSfL "$url" | sudo tar xz --strip-components=1 -C /usr/local/bin "delta-${arch}-unknown-linux-musl/delta" ;; fastfetch) info "installing fastfetch" local url="https://github.com/fastfetch-cli/fastfetch/releases/latest/download/fastfetch-linux-${arch}.tar.gz" curl -sSfL "$url" | sudo tar xz --strip-components=2 -C /usr/local/bin ;; jq) info "installing jq" local url="https://github.com/jqlang/jq/releases/latest/download/jq-linux-${arch}" curl -sSfL "$url" -o /usr/local/bin/jq sudo chmod +x /usr/local/bin/jq ;; lazygit) info "installing lazygit" local lazygit_arch case "$arch" in x86_64) lazygit_arch="x86_64" ;; aarch64) lazygit_arch="arm64" ;; armhf) lazygit_arch="armv6" ;; esac curl -sSfL "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_Linux_${lazygit_arch}.tar.gz" | sudo tar xz -C /usr/local/bin ;; lazydocker) info "installing lazydocker" local lazydocker_arch case "$arch" in x86_64) lazydocker_arch="x86_64" ;; aarch64) lazydocker_arch="arm64" ;; armhf) lazydocker_arch="armv6" ;; esac curl -sSfL "https://github.com/jesseduffield/lazydocker/releases/latest/download/lazydocker_Linux_${lazydocker_arch}.tar.gz" | sudo tar xz -C /usr/local/bin ;; dotstate) info "installing dotstate" curl -fsSL https://dotstate.serkan.dev/install.sh | bash ;; esac } install_missing() { local missing=("$@") [[ ${#missing[@]} -eq 0 ]] && return 0 declare -A PKG_NAMES=( [git]="git" [curl]="curl" [jq]="jq" [fzf]="fzf" [eza]="eza" [bat]="bat" [delta]="git-delta" [fastfetch]="fastfetch" [zsh]="zsh" [lazygit]="lazygit" [lazydocker]="lazydocker" ) local sys_pkgs=() local bin_pkgs=() for tool in "${missing[@]}"; do if [[ "$tool" == "starship" || "$tool" == "dotstate" ]]; then bin_pkgs+=("$tool") continue fi sys_pkgs+=("${PKG_NAMES[$tool]:-$tool}") done if [[ ${#sys_pkgs[@]} -gt 0 ]]; then info "installing from system repos: ${sys_pkgs[*]}" install_pkgs "${sys_pkgs[@]}" &>/dev/null || { warn "system install failed, falling back to binaries" bin_pkgs+=("${sys_pkgs[@]}") } fi for tool in "${bin_pkgs[@]}"; do install_binary "$tool" done } # --- Repo --- update_repo() { local REPO_URL="https://git.jeremymcclure.com/jeremy/dotstate-storage.git" local TARGET_DIR="$HOME/.config/dotstate/storage" if [[ -d "$TARGET_DIR/.git" ]]; then cd "$TARGET_DIR" || return 0 local remote_sha local_sha remote_sha=$(timeout 5 git ls-remote "$REPO_URL" HEAD | awk '{print $1}') [[ -z "$remote_sha" ]] && return 0 local_sha=$(git rev-parse HEAD) if [[ "$remote_sha" == "$local_sha" ]]; then success "Repository up to date" return 0 fi warn "Repository out of date. Pulling updates..." local old_sha old_sha=$(git rev-parse HEAD) git fetch origin &>/dev/null && git reset --hard origin/master &>/dev/null && git clean -fd &>/dev/null git log --format='%C(yellow)%h%C(reset) %C(cyan)%ar%C(reset) %s' "$old_sha"..HEAD else info "Repository not found. Cloning..." git clone --depth=1 "$REPO_URL" "$TARGET_DIR" &>/dev/null fi update } # --- Main --- MISSING=($(check_all)) if [[ ${#MISSING[@]} -eq 0 ]]; then success "All Packages Installed" update else install_missing "${MISSING[@]}" fi update_repo success "Done Bootstrapping, run \"exec zsh\" or restart your shell"