diff --git a/.gitignore b/.gitignore index 940053a..e008966 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,3 @@ temp **/autoload **/pypoetry -# darwin -.DS_Store - diff --git a/files/home/.aliases b/files/home/.aliases index 1427b37..a063aad 100644 --- a/files/home/.aliases +++ b/files/home/.aliases @@ -7,3 +7,9 @@ alias reload-cache='rm -rf "${XDG_CACHE_HOME:-$HOME/.cache}/dots" ~/.zcompdump* alias zen='curl -s https://api.github.com/zen && echo' alias la='ls -la' alias colby='copilot --allow-all-tools --allow-all-paths --banner' +alias gs='git s' +alias gd='git d' +alias gdc='git dc' +alias gc='git c' +alias gl='git ld' + diff --git a/files/home/.gitconfig b/files/home/.gitconfig index 7549aa4..462e6b0 100644 --- a/files/home/.gitconfig +++ b/files/home/.gitconfig @@ -19,8 +19,6 @@ [core] autocrlf = input - editor = vim - pager = less -FRX [color] ui = auto diff --git a/script/install b/script/install index 3da8594..07fd568 100755 --- a/script/install +++ b/script/install @@ -26,52 +26,24 @@ else fi # Log functions -log_info() { - echo -e "${BLUE}[INFO]${NC} $*" -} +log_info() { echo -e "${BLUE}[INFO]${NC} $*"; } +log_pass() { echo -e "${GREEN}[PASS]${NC} $*"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +log_error() { echo -e "${RED}[FAIL]${NC} $*"; } +log_debug() { echo -e "${CYAN}$*${NC}"; } -log_pass() { - echo -e "${GREEN}[PASS]${NC} $*" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $*" -} - -log_error() { - echo -e "${RED}[FAIL]${NC} $*" -} - -log_debug() { - echo -e "${CYAN}$*${NC}" -} - -# Export log functions so they're available in sourced scripts -export -f log_info -export -f log_pass -export -f log_warn -export -f log_error -export -f log_debug +# Export log functions +export -f log_info log_pass log_warn log_error log_debug printf "\n\t${CYAN} <<< ${CYAN_BOLD}dots${CYAN} >>> ${NC}\n" printf "\t${GREY}==============${NC}\n\n" # High-resolution time helpers -# now_ns prints current time in nanoseconds using GNU date if available. -# On systems where %N isn't supported (e.g., BSD date), it falls back to -# seconds precision multiplied to nanoseconds. This avoids external deps like bc. -now_ns() { - local ns - ns=$(date +%s%N 2>/dev/null || true) - if [[ "$ns" =~ ^[0-9]+$ ]]; then - echo "$ns" - else - # Fallback: seconds precision - local s - s=$(date +%s) - echo $(( s * 1000000000 )) - fi -} +if date +%s%N 2>/dev/null | grep -qE '^[0-9]+$'; then + now_ns() { date +%s%N; } +else + now_ns() { echo $(( $(date +%s) * 1000000000 )); } +fi # Prevent running as root if [[ $EUID -eq 0 && -z "$SKIP_SUDO_CHECK" ]]; then @@ -85,6 +57,27 @@ if [[ -z "$SKIP_SUDO_CHECK" ]]; then sudo -v fi +# Set up environment +export DOTS_OS="" +export DOTS_PKG="" +export DOTS_ENV="" +if [[ -n "${CODESPACES:-}" ]]; then + DOTS_ENV="codespaces" +fi +case "$OSTYPE" in + darwin*) DOTS_OS="macos"; DOTS_PKG="brew" ;; + linux*) + DOTS_OS="linux" + if command -v apt-get &>/dev/null; then + DOTS_PKG="apt" + elif command -v pacman &>/dev/null; then + DOTS_PKG="pacman" + elif command -v dnf &>/dev/null; then + DOTS_PKG="dnf" + fi + ;; +esac + # Set up directory variables if [ -L "$0" ]; then dir=$(dirname $(readlink -f "$0")) @@ -128,7 +121,8 @@ run() { echo -e "Running all install targets" fi - for script in $install_dir/*.sh; do + scripts=("$install_dir"/*.sh) + for script in "${scripts[@]}"; do if [[ -n "$targets" ]]; then script_name=$(basename "$script" .sh) script_name=${script_name#*-} diff --git a/script/install.d/00-os.sh b/script/install.d/00-os.sh index 761729e..772e07b 100644 --- a/script/install.d/00-os.sh +++ b/script/install.d/00-os.sh @@ -5,14 +5,16 @@ # Print operating system information and hint which installer path will run. # -if [[ "$OSTYPE" == "darwin"* ]]; then +log_info "Environment: DOTS_OS=$DOTS_OS, DOTS_PKG=$DOTS_PKG, DOTS_ENV=$DOTS_ENV" + +if [[ "$DOTS_OS" == "macos" ]]; then # macOS info sw_vers log_info "Detected macOS (OSTYPE=$OSTYPE)" log_info "Package manager: Homebrew (brew)" log_info "Code path: macOS-only brew scripts will run; Linux package scripts are skipped." -elif [[ "$OSTYPE" == "linux-gnu"* ]]; then +elif [[ "$DOTS_OS" == "linux" ]]; then # Linux info if [[ -r /etc/os-release ]]; then cat /etc/os-release @@ -21,17 +23,16 @@ elif [[ "$OSTYPE" == "linux-gnu"* ]]; then fi log_info "Detected Linux (OSTYPE=$OSTYPE, ID=${ID:-unknown}, ID_LIKE=${ID_LIKE:-n/a}, NAME=${NAME:-n/a}, VERSION_ID=${VERSION_ID:-n/a})" + log_info "Package manager detected: ${DOTS_PKG:-none}" - if command -v apt-get >/dev/null 2>&1; then - log_info "Package manager detected: apt-get" - export DOTS_PKG_MGR=apt - elif command -v pacman >/dev/null 2>&1; then - log_info "Package manager detected: pacman" - export DOTS_PKG_MGR=pacman - else - log_warn "No known package manager (apt-get/pacman) found on Linux." + if [[ -z "$DOTS_PKG" ]]; then + log_warn "No known package manager (apt-get/pacman/dnf) found on Linux." fi else log_error "Unknown OS: $OSTYPE" fi + +if [[ "$DOTS_ENV" == "codespaces" ]]; then + log_info "Running in GitHub Codespaces" +fi diff --git a/script/install.d/01-ssh.sh b/script/install.d/01-ssh.sh index 4c3f3e5..dfbc454 100644 --- a/script/install.d/01-ssh.sh +++ b/script/install.d/01-ssh.sh @@ -5,29 +5,24 @@ # Print SSH key. # -# skip if CODESPACES is set -if [ -n "$CODESPACES" ]; then - log_warn "Running in a GitHub Codespace" - export SKIP_SSH_CONFIG=1 +# Skip in Codespaces +[[ "$DOTS_ENV" == "codespaces" ]] && { log_pass "Skipping in Codespaces"; return 0; } + +# Skip if explicitly disabled +[[ -n "$SKIP_SSH_CONFIG" ]] && { log_warn "Skipping SSH configuration"; return 0; } + +ssh_method="ed25519" + +ssh_target="${HOME}/.ssh" +ssh_key="${ssh_target}/id_${ssh_method}" +ssh_pub="${ssh_key}.pub" +if [ ! -f "$ssh_key" ]; then + ssh-keygen \ + -t "$ssh_method" \ + -f "$ssh_key" \ + -C "$(whoami)@$(hostname)-$(date -I)" fi -# skip if SKIP_SSH_CONFIG is set -if [ -z "$SKIP_SSH_CONFIG" ]; then - ssh_method="ed25519" +cat "$ssh_pub" - ssh_target="${HOME}/.ssh" - ssh_key="${ssh_target}/id_${ssh_method}" - ssh_pub="${ssh_key}.pub" - if [ ! -f "$ssh_key" ]; then - ssh-keygen \ - -t "$ssh_method" \ - -f "$ssh_key" \ - -C "$(whoami)@$(hostname)-$(date -I)" - fi - - cat "$ssh_pub" - - unset ssh_method ssh_target ssh_key ssh_pub -else - log_warn "Skipping SSH configuration" -fi +unset ssh_method ssh_target ssh_key ssh_pub diff --git a/script/install.d/02-brew.sh b/script/install.d/02-brew.sh index ea0ee63..ae5b6ce 100644 --- a/script/install.d/02-brew.sh +++ b/script/install.d/02-brew.sh @@ -5,24 +5,23 @@ # (macOS only) Install homebrew. # -if [[ "$OSTYPE" == "darwin"* ]]; then - if [ -d "/opt/homebrew/bin" ]; then - export PATH="/opt/homebrew/bin:$PATH" - fi - export NONINTERACTIVE=1 - export HOMEBREW_NO_ANALYTICS=1 - export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 - export HOMEBREW_NO_ENV_HINTS=1 - export HOMEBREW_NO_AUTO_UPDATE=1 - export HOMEBREW_NO_INSTALL_CLEANUP=1 - if ! command -v brew &> /dev/null; then - echo "Installing Homebrew..." - bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - eval "$(/opt/homebrew/bin/brew shellenv)" - else - echo "Homebrew is already installed." - fi - brew --version -else - log_warn "Skipping: Not macOS" +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if [ -d "/opt/homebrew/bin" ]; then + export PATH="/opt/homebrew/bin:$PATH" fi +export NONINTERACTIVE=1 +export HOMEBREW_NO_ANALYTICS=1 +export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 +export HOMEBREW_NO_ENV_HINTS=1 +export HOMEBREW_NO_AUTO_UPDATE=1 +export HOMEBREW_NO_INSTALL_CLEANUP=1 +if ! command -v brew &> /dev/null; then + echo "Installing Homebrew..." + bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + eval "$(/opt/homebrew/bin/brew shellenv)" +else + echo "Homebrew is already installed." +fi +brew --version diff --git a/script/install.d/03-apt.sh b/script/install.d/03-apt.sh index 5cc75cd..51e954c 100644 --- a/script/install.d/03-apt.sh +++ b/script/install.d/03-apt.sh @@ -5,21 +5,20 @@ # (distros with apt only) Install core apt packages. # -if command -v apt-get &> /dev/null; then - apt_packages=( - ca-certificates - curl - gnupg - gnupg2 - wget - ) +# apt only +[[ "$DOTS_PKG" != "apt" ]] && { log_warn "Skipping: Not using apt"; return 0; } - sudo apt-get update -qq - sudo apt-get install -qq "${apt_packages[@]}" +apt_packages=( + ca-certificates + curl + gnupg + gnupg2 + wget +) - unset apt_packages +sudo apt-get update -qq +sudo apt-get install -qq "${apt_packages[@]}" - apt --version -else - log_warn "Skipping: apt-get not found" -fi +unset apt_packages + +apt --version diff --git a/script/install.d/03-pacman.sh b/script/install.d/03-pacman.sh index b4d5ca7..67a4f32 100644 --- a/script/install.d/03-pacman.sh +++ b/script/install.d/03-pacman.sh @@ -5,21 +5,20 @@ # (distros with pacman only) Install core pacman packages. # -if command -v pacman &> /dev/null; then - pacman_packages=( - ca-certificates - curl - gnupg - wget - base-devel - ) +# pacman only +[[ "$DOTS_PKG" != "pacman" ]] && { log_warn "Skipping: Not using pacman"; return 0; } - sudo pacman -Sy --noconfirm - sudo pacman -S --noconfirm --needed "${pacman_packages[@]}" +pacman_packages=( + ca-certificates + curl + gnupg + wget + base-devel +) - unset pacman_packages +sudo pacman -Sy --noconfirm +sudo pacman -S --noconfirm --needed "${pacman_packages[@]}" - pacman --version -else - log_warn "Skipping: pacman not found" -fi +unset pacman_packages + +pacman --version diff --git a/script/install.d/04-git.sh b/script/install.d/04-git.sh index 26e7e30..06ccf44 100644 --- a/script/install.d/04-git.sh +++ b/script/install.d/04-git.sh @@ -6,17 +6,21 @@ # if ! command -v git &> /dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) sudo apt-get install -qq git - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm git - else + ;; + brew) + brew install git + ;; + *) log_warn "Skipping git install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install git - fi + return 0 + ;; + esac fi git --version diff --git a/script/install.d/05-zsh.sh b/script/install.d/05-zsh.sh index a832347..569cd89 100644 --- a/script/install.d/05-zsh.sh +++ b/script/install.d/05-zsh.sh @@ -7,17 +7,21 @@ # install zsh if ! command -v zsh &> /dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) sudo apt-get install -qq zsh - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm zsh - else + ;; + brew) + brew install zsh + ;; + *) log_warn "Skipping zsh install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install zsh - fi + return 0 + ;; + esac fi zsh --version diff --git a/script/install.d/06-stow.sh b/script/install.d/06-stow.sh index 39ef12f..fcb852f 100644 --- a/script/install.d/06-stow.sh +++ b/script/install.d/06-stow.sh @@ -6,17 +6,21 @@ # if ! command -v stow &> /dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) sudo apt-get install -qq stow - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm stow - else + ;; + brew) + brew install stow + ;; + *) log_warn "Skipping stow install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install stow - fi + return 0 + ;; + esac fi stow --version diff --git a/script/install.d/10-pyenv.sh b/script/install.d/10-pyenv.sh index fed8717..6ca5843 100644 --- a/script/install.d/10-pyenv.sh +++ b/script/install.d/10-pyenv.sh @@ -10,8 +10,8 @@ if ! echo "$PATH" | grep -q "$PYENV_ROOT"; then export PATH="$PYENV_ROOT/bin:$PATH" fi if ! command -v pyenv &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) # https://github.com/pyenv/pyenv/wiki#suggested-build-environment sudo apt-get install -qq build-essential libssl-dev zlib1g-dev \ libbz2-dev libreadline-dev libsqlite3-dev curl \ @@ -19,7 +19,8 @@ if ! command -v pyenv &>/dev/null; then # see https://github.com/pyenv/pyenv-installer bash -c "$(curl -fsSL https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer)" - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) # Prefer native packages if available; otherwise install build deps then use installer if ! sudo pacman -Qi pyenv >/dev/null 2>&1; then sudo pacman -S --noconfirm --needed base-devel openssl zlib-ng-compat bzip2 readline sqlite xz tk libffi curl @@ -27,16 +28,18 @@ if ! command -v pyenv &>/dev/null; then else sudo pacman -S --noconfirm --needed pyenv pyenv-virtualenv fi - else + ;; + brew) + brew install pyenv + brew install pyenv-virtualenv + ;; + *) log_warn "Skipping pyenv install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install pyenv - brew install pyenv-virtualenv - fi + ;; + esac fi -if [[ "$OSTYPE" == "linux-gnu"* ]]; then +if [[ "$DOTS_OS" == "linux" ]]; then virtualenv_path="$(pyenv root)/plugins/pyenv-virtualenv" if [ ! -d "$virtualenv_path" ]; then git clone \ diff --git a/script/install.d/11-python.sh b/script/install.d/11-python.sh index a15ffdb..a8e5a63 100644 --- a/script/install.d/11-python.sh +++ b/script/install.d/11-python.sh @@ -41,17 +41,20 @@ mkdir -p ~/.local/bin unset local_bin_path if ! command -v pipx &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) sudo apt-get install -qq pipx - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm python-pipx - else - log_warn "Skipping pipx install: no apt-get or pacman found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install pipx - fi + ;; + brew) + brew install pipx + ;; + *) + log_warn "Skipping pipx install: no supported package manager found" + ;; + esac fi echo "pipx $(pipx --version)" diff --git a/script/install.d/20-docker.sh b/script/install.d/20-docker.sh index 06f2fd9..8f2008e 100644 --- a/script/install.d/20-docker.sh +++ b/script/install.d/20-docker.sh @@ -8,60 +8,49 @@ # skip if in WSL if [[ -n "$WSL_DISTRO_NAME" ]]; then - log_warn "Running in WSL" - export SKIP_DOCKER_CONFIG=1 + log_warn "Skipping: Running in WSL" + return 0 fi -# skip if in CODESPACES -if [[ -n "$CODESPACES" ]]; then - log_warn "Running in GitHub Codespaces" - export SKIP_DOCKER_CONFIG=1 +# skip if in Codespaces +[[ "$DOTS_ENV" == "codespaces" ]] && { log_pass "Skipping in Codespaces"; return 0; } + +# skip on macOS +[[ "$DOTS_OS" == "macos" ]] && { log_warn "Skipping: macOS"; return 0; } + +if ! command -v docker &> /dev/null; then + case "$DOTS_PKG" in + apt) + sudo install -m 0755 -d /etc/apt/keyrings + sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc + sudo chmod a+r /etc/apt/keyrings/docker.asc + + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + sudo apt-get update + + sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + ;; + pacman) + sudo pacman -S --noconfirm --needed docker docker-buildx docker-compose + ;; + *) + log_warn "Skipping Docker install: no supported package manager found" + ;; + esac fi -# skip on mac -if [[ "$OSTYPE" == "darwin"* ]]; then - log_warn "Running on macOS" - export SKIP_DOCKER_CONFIG=1 +readonly docker_group="docker" +if ! grep -q "$docker_group" /etc/group; then + log_info "Adding docker group" + sudo groupadd "$docker_group" fi -if [[ -z "$SKIP_DOCKER_CONFIG" ]]; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if ! command -v docker &> /dev/null; then - if command -v apt-get >/dev/null 2>&1; then - sudo install -m 0755 -d /etc/apt/keyrings - sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc - sudo chmod a+r /etc/apt/keyrings/docker.asc - - echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ - $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ - sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - sudo apt-get update - - sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - elif command -v pacman >/dev/null 2>&1; then - sudo pacman -S --noconfirm --needed docker docker-buildx docker-compose - else - log_warn "Skipping Docker install: no supported package manager found" - fi - fi - - readonly docker_group="docker" - if ! grep -q "$docker_group" /etc/group; then - log_info "Adding docker group" - sudo groupadd "$docker_group" - fi - - if ! groups "$USER" | grep -q "\b$docker_group\b"; then - log_info "Adding user to docker group" - sudo usermod -aG docker "$USER" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - if ! command -v docker &> /dev/null; then - brew install --cask docker - fi - fi - docker --version -else - log_warn "Skipping Docker configuration" +if ! groups "$USER" | grep -q "\b$docker_group\b"; then + log_info "Adding user to docker group" + sudo usermod -aG docker "$USER" fi + +docker --version diff --git a/script/install.d/21-azure.sh b/script/install.d/21-azure.sh index aa4ff70..4018580 100644 --- a/script/install.d/21-azure.sh +++ b/script/install.d/21-azure.sh @@ -6,18 +6,21 @@ # if ! command -v az &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) # https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm azure-cli &>/dev/null - else + ;; + brew) + brew install azure-cli + ;; + *) log_warn "Skipping Azure CLI install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install azure-cli - fi + ;; + esac fi az --version diff --git a/script/install.d/22-gh.sh b/script/install.d/22-gh.sh index fd7f338..e172e4c 100644 --- a/script/install.d/22-gh.sh +++ b/script/install.d/22-gh.sh @@ -6,22 +6,25 @@ # if ! command -v gh &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) # https://github.com/cli/cli/blob/trunk/docs/install_linux.md#debian-ubuntu-linux-raspberry-pi-os-apt sudo mkdir -p -m 755 /etc/apt/keyrings && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg >/dev/null && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null && sudo apt-get update -qq && sudo apt-get install -qq gh - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm github-cli - else + ;; + brew) + brew install gh + ;; + *) log_warn "Skipping GitHub CLI install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install gh - fi + ;; + esac fi gh --version diff --git a/script/install.d/25-terraform.sh b/script/install.d/25-terraform.sh index e46bb2d..41745f6 100644 --- a/script/install.d/25-terraform.sh +++ b/script/install.d/25-terraform.sh @@ -6,8 +6,8 @@ # if ! command -v terraform &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) terraform_keyring_path="/usr/share/keyrings/hashicorp-archive-keyring.gpg" if [[ ! -f "$terraform_keyring_path" ]]; then curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o "$terraform_keyring_path" @@ -17,15 +17,18 @@ if ! command -v terraform &>/dev/null; then sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt-get update -qq && sudo apt-get install -qq terraform - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm terraform - else + ;; + brew) + brew tap hashicorp/tap + brew install hashicorp/tap/terraform + ;; + *) log_warn "Skipping Terraform install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew tap hashicorp/tap - brew install hashicorp/tap/terraform - fi + ;; + esac fi terraform --version diff --git a/script/install.d/30-iterm2.sh b/script/install.d/30-iterm2.sh index 9817f96..0e3147c 100644 --- a/script/install.d/30-iterm2.sh +++ b/script/install.d/30-iterm2.sh @@ -5,11 +5,10 @@ # (macOS only) Install iTerm2. # -if [[ "$OSTYPE" == "darwin"* ]]; then - if ! brew list --cask iterm2 &>/dev/null; then - brew install --cask iterm2 - fi - log_pass "iTerm2 installed successfully!" -else - log_warn "Skipping: Not macOS" +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if ! brew list --cask iterm2 &>/dev/null; then + brew install --cask iterm2 fi +log_pass "iTerm2 installed successfully!" diff --git a/script/install.d/40-nerdfont.sh b/script/install.d/40-nerdfont.sh index 8da9127..a4c460b 100644 --- a/script/install.d/40-nerdfont.sh +++ b/script/install.d/40-nerdfont.sh @@ -5,20 +5,19 @@ # (macOS only) Install nerdfonts. # -if [[ "$OSTYPE" == "darwin"* ]]; then - fonts_list=( - font-fira-mono-nerd-font - font-fira-code-nerd-font - ) +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } - if ! brew list "${fonts_list[@]}" &> /dev/null; then - brew tap homebrew/cask-fonts - for font in "${fonts_list[@]}"; do - brew install --cask "$font" - done - fi +fonts_list=( + font-fira-mono-nerd-font + font-fira-code-nerd-font +) - unset fonts_list -else - log_warn "Skipping: Not macOS" +if ! brew list "${fonts_list[@]}" &> /dev/null; then + brew tap homebrew/cask-fonts + for font in "${fonts_list[@]}"; do + brew install --cask "$font" + done fi + +unset fonts_list diff --git a/script/install.d/50-redis.sh b/script/install.d/50-redis.sh index ab07c26..10c4f9a 100644 --- a/script/install.d/50-redis.sh +++ b/script/install.d/50-redis.sh @@ -6,8 +6,8 @@ # if ! command -v redis-cli &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) redis_keyring_path="/usr/share/keyrings/redis-archive-keyring.gpg" if [[ ! -f "$redis_keyring_path" ]]; then curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o "$redis_keyring_path" @@ -15,14 +15,17 @@ if ! command -v redis-cli &>/dev/null; then echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" \ | sudo tee /etc/apt/sources.list.d/redis.list > /dev/null sudo apt-get install -qq redis - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) sudo pacman -S --noconfirm redis - else + ;; + brew) + brew install redis + ;; + *) log_warn "Skipping Redis install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install redis - fi + ;; + esac fi redis-cli --version diff --git a/script/install.d/70-cca.sh b/script/install.d/70-cca.sh index 21afa4d..a6f79d0 100644 --- a/script/install.d/70-cca.sh +++ b/script/install.d/70-cca.sh @@ -5,12 +5,11 @@ # (macOS only) Install Colour Contrast Analyser (CCA). # -if [[ "$OSTYPE" == "darwin"* ]]; then - if ! brew list --cask colour-contrast-analyser &> /dev/null; then - brew install --cask colour-contrast-analyser - else - echo "Colour Contrast Analyser (CCA) is already installed." - fi +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if ! brew list --cask colour-contrast-analyser &> /dev/null; then + brew install --cask colour-contrast-analyser else - log_warn "Skipping: Not macOS" + echo "Colour Contrast Analyser (CCA) is already installed." fi diff --git a/script/install.d/71-rectangle.sh b/script/install.d/71-rectangle.sh index d94b986..26b4a92 100644 --- a/script/install.d/71-rectangle.sh +++ b/script/install.d/71-rectangle.sh @@ -5,12 +5,11 @@ # (macOS only) Install Rectangle. # -if [[ "$OSTYPE" == "darwin"* ]]; then - if ! brew list --cask rectangle &> /dev/null; then - brew install --cask rectangle - else - echo "Rectangle is already installed." - fi +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if ! brew list --cask rectangle &> /dev/null; then + brew install --cask rectangle else - log_warn "Skipping: Not macOS" + echo "Rectangle is already installed." fi diff --git a/script/install.d/72-meetingbar.sh b/script/install.d/72-meetingbar.sh index fa3c933..4c74f24 100644 --- a/script/install.d/72-meetingbar.sh +++ b/script/install.d/72-meetingbar.sh @@ -5,12 +5,11 @@ # (macOS only) Install MeetingBar. # -if [[ "$OSTYPE" == "darwin"* ]]; then - if ! brew list --cask meetingbar &> /dev/null; then - brew install --cask meetingbar - else - echo "MeetingBar is already installed." - fi +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if ! brew list --cask meetingbar &> /dev/null; then + brew install --cask meetingbar else - log_warn "Skipping: Not macOS" + echo "MeetingBar is already installed." fi diff --git a/script/install.d/73-betterdisplay.sh b/script/install.d/73-betterdisplay.sh index bb70e08..8b0544c 100644 --- a/script/install.d/73-betterdisplay.sh +++ b/script/install.d/73-betterdisplay.sh @@ -5,12 +5,11 @@ # (macOS only) Install BetterDisplay. # -if [[ "$OSTYPE" == "darwin"* ]]; then - if ! brew list --cask betterdisplay &> /dev/null; then - brew install --cask betterdisplay - else - echo "BetterDisplay is already installed." - fi +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if ! brew list --cask betterdisplay &> /dev/null; then + brew install --cask betterdisplay else - log_warn "Skipping: Not macOS" + echo "BetterDisplay is already installed." fi diff --git a/script/install.d/74-dockutil.sh b/script/install.d/74-dockutil.sh index 4423941..180e77b 100644 --- a/script/install.d/74-dockutil.sh +++ b/script/install.d/74-dockutil.sh @@ -5,12 +5,11 @@ # (macOS only) Install dockutil. # -if [[ "$OSTYPE" == "darwin"* ]]; then - if ! brew list dockutil &> /dev/null; then - brew install dockutil - else - echo "dockutil is already installed." - fi +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } + +if ! brew list dockutil &> /dev/null; then + brew install dockutil else - log_warn "Skipping: Not macOS" + echo "dockutil is already installed." fi diff --git a/script/install.d/80-neofetch.sh b/script/install.d/80-neofetch.sh index 1f8d997..701d341 100644 --- a/script/install.d/80-neofetch.sh +++ b/script/install.d/80-neofetch.sh @@ -6,17 +6,20 @@ # if ! command -v neofetch &>/dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then + case "$DOTS_PKG" in + apt) sudo apt-get install -qq neofetch &>/dev/null - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) yay -S --noconfirm neofetch &>/dev/null - else + ;; + brew) + brew install neofetch + ;; + *) log_warn "Skipping neofetch install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then - brew install neofetch - fi + ;; + esac fi echo "$(neofetch --version)" diff --git a/script/install.d/81-cmatrix.sh b/script/install.d/81-cmatrix.sh index 6f26ead..fd79bd1 100644 --- a/script/install.d/81-cmatrix.sh +++ b/script/install.d/81-cmatrix.sh @@ -5,27 +5,23 @@ # Install cmatrix. # -# skip if in CODESPACES -if [[ -n "$CODESPACES" ]]; then - log_warn "Running in GitHub Codespaces" - export SKIP_CMATRIX_CONFIG=1 -fi +# skip if in Codespaces +[[ "$DOTS_ENV" == "codespaces" ]] && { log_pass "Skipping in Codespaces"; return 0; } -if [[ -z "$SKIP_CMATRIX_CONFIG" ]]; then - if ! command -v cmatrix &> /dev/null; then - if [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then - sudo apt-get install -qq cmatrix &>/dev/null - elif command -v pacman >/dev/null 2>&1; then - sudo pacman -S --noconfirm cmatrix &>/dev/null - else - log_warn "Skipping cmatrix install: no supported package manager found" - fi - elif [[ "$OSTYPE" == "darwin"* ]]; then +if ! command -v cmatrix &> /dev/null; then + case "$DOTS_PKG" in + apt) + sudo apt-get install -qq cmatrix &>/dev/null + ;; + pacman) + sudo pacman -S --noconfirm cmatrix &>/dev/null + ;; + brew) brew install cmatrix - fi - fi - log_pass "cmatrix installed successfully!" -else - log_warn "Skipping cmatrix configuration" + ;; + *) + log_warn "Skipping cmatrix install: no supported package manager found" + ;; + esac fi +log_pass "cmatrix installed successfully!" diff --git a/script/install.d/97-macos.sh b/script/install.d/97-macos.sh index a0f89a6..a5226d9 100644 --- a/script/install.d/97-macos.sh +++ b/script/install.d/97-macos.sh @@ -5,185 +5,184 @@ # (macOS only) Configure defaults # -if [[ "$OSTYPE" == "darwin"* ]]; then - # Keyboard - # -------- - # off -- Keyboard: Capitalize words automatically - defaults write -globalDomain NSAutomaticCapitalizationEnabled -bool false +# macOS only +[[ "$DOTS_OS" != "macos" ]] && { log_warn "Skipping: Not macOS"; return 0; } - # off -- Keyboard: Add period with double-space - defaults write -globalDomain NSAutomaticPeriodSubstitutionEnabled -bool false +# Keyboard +# -------- +# off -- Keyboard: Capitalize words automatically +defaults write -globalDomain NSAutomaticCapitalizationEnabled -bool false - # off -- Keyboard: Quote substitution - defaults write -globalDomain NSAutomaticQuoteSubstitutionEnabled -bool false +# off -- Keyboard: Add period with double-space +defaults write -globalDomain NSAutomaticPeriodSubstitutionEnabled -bool false - # off -- Keyboard: Dash substitution - defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false +# off -- Keyboard: Quote substitution +defaults write -globalDomain NSAutomaticQuoteSubstitutionEnabled -bool false - # off -- Keyboard: Auto-correct - defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false - defaults write NSGlobalDomain WebAutomaticSpellingCorrectionEnabled -bool false +# off -- Keyboard: Dash substitution +defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false - # Appearance - # ---------- - # Graphite -- Appearance (prevent top-left window colours) - defaults write -globalDomain AppleAquaColorVariant -int 6 +# off -- Keyboard: Auto-correct +defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false +defaults write NSGlobalDomain WebAutomaticSpellingCorrectionEnabled -bool false - # on -- Appearance: Dark mode - defaults write -globalDomain AppleInterfaceStyle -string "Dark" +# Appearance +# ---------- +# Graphite -- Appearance (prevent top-left window colours) +defaults write -globalDomain AppleAquaColorVariant -int 6 - # #2CB494 -- Highlight color - defaults write -globalDomain AppleHighlightColor -string "0.172549 0.705882 0.580392" +# on -- Appearance: Dark mode +defaults write -globalDomain AppleInterfaceStyle -string "Dark" - killall SystemUIServer 2>/dev/null || true +# #2CB494 -- Highlight color +defaults write -globalDomain AppleHighlightColor -string "0.172549 0.705882 0.580392" - # Control Center - # -------------- - # off -- Control Center: Show Bluetooth icon in menu bar - defaults write \ - ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ - Bluetooth \ - -int 24 +killall SystemUIServer 2>/dev/null || true - # off -- Control Center: Show Wi-Fi icon in menu bar - defaults write \ - ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ - WiFi \ - -int 24 +# Control Center +# -------------- +# off -- Control Center: Show Bluetooth icon in menu bar +defaults write \ + ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ + Bluetooth \ + -int 24 - # off -- Control Center: Show Now Playing icon in menu bar - defaults write \ - ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ - NowPlaying \ - -int 24 +# off -- Control Center: Show Wi-Fi icon in menu bar +defaults write \ + ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ + WiFi \ + -int 24 - # off -- Control Center: Show Battery icon in menu bar - defaults write \ - ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ - Battery \ - -int 24 +# off -- Control Center: Show Now Playing icon in menu bar +defaults write \ + ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ + NowPlaying \ + -int 24 - killall ControlCenter 2>/dev/null || true +# off -- Control Center: Show Battery icon in menu bar +defaults write \ + ~/Library/Preferences/ByHost/com.apple.controlcenter.plist \ + Battery \ + -int 24 - # Finder - # ------ - # on -- Finder: Add quit option - defaults write com.apple.finder QuitMenuItem -bool true +killall ControlCenter 2>/dev/null || true - # on -- Finder: Show hidden files - defaults write com.apple.finder AppleShowAllFiles -bool true +# Finder +# ------ +# on -- Finder: Add quit option +defaults write com.apple.finder QuitMenuItem -bool true - # on -- Finder: Show all filename extensions - defaults write NSGlobalDomain AppleShowAllExtensions -bool true +# on -- Finder: Show hidden files +defaults write com.apple.finder AppleShowAllFiles -bool true - # off -- Finder: Show warning before changing an extension - defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false +# on -- Finder: Show all filename extensions +defaults write NSGlobalDomain AppleShowAllExtensions -bool true - # on -- Finder: Show path bar - defaults write com.apple.finder ShowPathbar -bool true +# off -- Finder: Show warning before changing an extension +defaults write com.apple.finder FXEnableExtensionChangeWarning -bool false - # on -- Finder: Show status bar - defaults write com.apple.finder ShowStatusBar -bool true +# on -- Finder: Show path bar +defaults write com.apple.finder ShowPathbar -bool true - # on -- Finder: Keep folders on top - defaults write com.apple.finder _FXSortFoldersFirst -bool true +# on -- Finder: Show status bar +defaults write com.apple.finder ShowStatusBar -bool true - # off -- Finder: Use macOS Crash Reporter - defaults write com.apple.CrashReporter DialogType -string "none" +# on -- Finder: Keep folders on top +defaults write com.apple.finder _FXSortFoldersFirst -bool true - # off -- Finder: Enable dashboard widgets - defaults write com.apple.dashboard mcx-disabled -bool true +# off -- Finder: Use macOS Crash Reporter +defaults write com.apple.CrashReporter DialogType -string "none" - # on -- Finder: Show hard drives on desktop - defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true +# off -- Finder: Enable dashboard widgets +defaults write com.apple.dashboard mcx-disabled -bool true - # on -- Finder: Show external hard drives on desktop - defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true +# on -- Finder: Show hard drives on desktop +defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true - # on -- Finder: Show removable media on desktop - defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool true +# on -- Finder: Show external hard drives on desktop +defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true - # on -- Finder: Show mounted servers on desktop - defaults write com.apple.finder ShowMountedServersOnDesktop -bool true +# on -- Finder: Show removable media on desktop +defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool true - # off -- Finder: Show recent tags - defaults write com.apple.finder ShowRecentTags -bool false +# on -- Finder: Show mounted servers on desktop +defaults write com.apple.finder ShowMountedServersOnDesktop -bool true - # off -- Finder: Create .DS_Store files - defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true - defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true +# off -- Finder: Show recent tags +defaults write com.apple.finder ShowRecentTags -bool false - # home -- Finder: New Finder windows show - defaults write com.apple.finder NewWindowTargetPath -string "file://${HOME}/" +# off -- Finder: Create .DS_Store files +defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true +defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true - # list -- Finder: Preferred view style - defaults write com.apple.finder FXPreferredViewStyle -string "nlsv" +# home -- Finder: New Finder windows show +defaults write com.apple.finder NewWindowTargetPath -string "file://${HOME}/" - killall Finder 2>/dev/null || true +# list -- Finder: Preferred view style +defaults write com.apple.finder FXPreferredViewStyle -string "nlsv" - # Spotlight - # --------- - # on -- Spotlight: Hide menu bar icon - defaults write com.apple.Spotlight MenuItemHidden -int 1 +killall Finder 2>/dev/null || true - killall Spotlight 2>/dev/null || true +# Spotlight +# --------- +# on -- Spotlight: Hide menu bar icon +defaults write com.apple.Spotlight MenuItemHidden -int 1 - # Dock - # ---- - # off -- Dock: Show recent applications - defaults write com.apple.dock show-recents -bool false +killall Spotlight 2>/dev/null || true - # on -- Dock: Use scroll gestures - defaults write com.apple.dock scroll-to-open -bool true +# Dock +# ---- +# off -- Dock: Show recent applications +defaults write com.apple.dock show-recents -bool false - # Remove default apps from the dock - default_apps=( - "Messages" - "Mail" - "Maps" - "Photos" - "FaceTime" - "Calendar" - "Contacts" - "Reminders" - "Freeform" - "TV" - "Music" - "News" - "Keynote" - "Numbers" - "Pages" - ) - for default_app in default_apps; do - dockutil --remove "$default_app" --no-restart 1>/dev/null 2>&1 || true - done +# on -- Dock: Use scroll gestures +defaults write com.apple.dock scroll-to-open -bool true - # Set up apps in the dock - dock_order=( - "/System/Library/CoreServices/Finder.app" # Cannot be moved - "/System/Applications/App Store.app" - "/System/Applications/Apps.app" - "/System/Applications/System Settings.app" - "/System/Applications/Utilities/Activity Monitor.app" - "/Applications/iTerm.app" - ) - dock_state=$(defaults read com.apple.dock persistent-apps) - for i in "${!dock_order[@]}"; do - if [[ $i -ne 0 ]]; then - path="${dock_order[$i]}" - name=$(basename "$path" | sed 's/\.app$//') - if [[ $dock_state == *"$name"* ]]; then - dockutil --move "${path}" --position "$i" --no-restart - else - dockutil --add "${path}" --position "$i" --no-restart - fi +# Remove default apps from the dock +default_apps=( + "Messages" + "Mail" + "Maps" + "Photos" + "FaceTime" + "Calendar" + "Contacts" + "Reminders" + "Freeform" + "TV" + "Music" + "News" + "Keynote" + "Numbers" + "Pages" +) +for default_app in default_apps; do + dockutil --remove "$default_app" --no-restart 1>/dev/null 2>&1 || true +done + +# Set up apps in the dock +dock_order=( + "/System/Library/CoreServices/Finder.app" # Cannot be moved + "/System/Applications/App Store.app" + "/System/Applications/Apps.app" + "/System/Applications/System Settings.app" + "/System/Applications/Utilities/Activity Monitor.app" + "/Applications/iTerm.app" +) +dock_state=$(defaults read com.apple.dock persistent-apps) +for i in "${!dock_order[@]}"; do + if [[ $i -ne 0 ]]; then + path="${dock_order[$i]}" + name=$(basename "$path" | sed 's/\.app$//') + if [[ $dock_state == *"$name"* ]]; then + dockutil --move "${path}" --position "$i" --no-restart + else + dockutil --add "${path}" --position "$i" --no-restart fi - done - if [[ ! $dock_state == *"spacer"* ]]; then - dockutil --add '' --type spacer --section apps --position "${#dock_order[@]}" --no-restart fi - - killall Dock 2>/dev/null || true -else - log_warn "Skipping: Not macOS" +done +if [[ ! $dock_state == *"spacer"* ]]; then + dockutil --add '' --type spacer --section apps --position "${#dock_order[@]}" --no-restart fi + +killall Dock 2>/dev/null || true diff --git a/script/install.d/98-clean.sh b/script/install.d/98-clean.sh index 789f182..2383ba6 100644 --- a/script/install.d/98-clean.sh +++ b/script/install.d/98-clean.sh @@ -5,22 +5,26 @@ # Clean up after installation. # -if [[ "$OSTYPE" == "darwin"* ]]; then - brew cleanup -elif [[ "$OSTYPE" == "linux-gnu"* ]]; then - if command -v apt-get >/dev/null 2>&1; then +case "$DOTS_PKG" in + brew) + brew cleanup + ;; + apt) sudo apt-get autoremove -qq sudo apt-get clean -qq - elif command -v pacman >/dev/null 2>&1; then + ;; + pacman) # Remove orphans if any (ignore error if none) if pacman -Qtdq >/dev/null 2>&1; then sudo pacman -Rns --noconfirm $(pacman -Qtdq) || true fi # Clear package cache without interactive prompt yes | sudo pacman -Scc >/dev/null 2>&1 || true - else + ;; + *) log_warn "Skipping cleanup: no supported package manager found" - fi -fi + return 0 + ;; +esac log_pass "Cleanup completed successfully!"