From c41e884270261e1f06c5cc2d3f42a0f99e9d8a87 Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:08:40 +0200 Subject: [PATCH 01/12] feat: completely rewrote installer implemented shellcheck formatting fix terminal spam added better cleanup logic --- install.sh | 159 +++++++++++++++++++++++------------------------------ 1 file changed, 69 insertions(+), 90 deletions(-) diff --git a/install.sh b/install.sh index ebdb15c..bb5ee0b 100644 --- a/install.sh +++ b/install.sh @@ -5,8 +5,8 @@ # ╚══███╔╝ ██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ # ███╔╝ █████╗███████╗███████║██║█████╗ ██║ # ███╔╝ ╚════╝╚════██║██╔══██║██║██╔══╝ ██║ -# ███████╗ ███████╗██║ ██║██║██║ ██║ -# ╚══════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ +# ███████╗ ███████╗██║ ██║██║██║ ██║ +# ╚══════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ # ============================================================================= # Z-SHIFT: High-Performance Zsh + Starship + Zinit installation script # ============================================================================= @@ -14,6 +14,17 @@ # Exit immediately if a command exits with a non-zero status set -e +# --- GLOBAL VARIABLES & CLEANUP TRAP --- +TEMP_DIR="" + +cleanup() { + # This runs automatically on script exit, interruption, or termination + if [ -n "$TEMP_DIR" ] && [ -d "$TEMP_DIR" ]; then + rm -rf "$TEMP_DIR" + fi +} +trap cleanup EXIT INT TERM + # --- CONFIGURATION --- ZSHRC_URL="${ZSHIFT_CUSTOM_URL:-https://raw.githubusercontent.com/0xdilshan/Z-SHIFT/main/.zshrc}" @@ -40,33 +51,33 @@ elif [ -f /etc/os-release ]; then OS_TYPE="linux" # shellcheck disable=SC1091 . /etc/os-release - DISTRO=$ID + DISTRO="$ID" fi echo -e "${BLUE}Detected OS: ${OS_TYPE} (${DISTRO})${NC}" -# Helper function to install packages based on distro +# Helper function to install packages silently based on distro install_pkg() { local pkgs=("$@") echo -e "${YELLOW}Installing: ${pkgs[*]}...${NC}" case $DISTRO in ubuntu|debian|pop|kali|linuxmint) - sudo apt update -y - sudo apt install -y "${pkgs[@]}" + export DEBIAN_FRONTEND=noninteractive + sudo apt-get update -qq -y > /dev/null + sudo apt-get install -qq -y "${pkgs[@]}" > /dev/null ;; arch|manjaro|endeavouros) - # Use --needed to skip up-to-date packages - sudo pacman -Sy --noconfirm --needed "${pkgs[@]}" + sudo pacman -Sy --quiet --noconfirm --needed "${pkgs[@]}" > /dev/null ;; fedora|rhel|centos) - sudo dnf install -y "${pkgs[@]}" + sudo dnf install -q -y "${pkgs[@]}" > /dev/null ;; opensuse*|suse) - sudo zypper install -y "${pkgs[@]}" + sudo zypper install -q -y "${pkgs[@]}" > /dev/null ;; macos) - brew install "${pkgs[@]}" + brew install -q "${pkgs[@]}" > /dev/null ;; *) echo -e "${RED}Unsupported distribution: $DISTRO${NC}" @@ -80,8 +91,9 @@ install_pkg() { # ============================================================================= if [[ "$OS_TYPE" == "macos" ]]; then if ! command -v brew &> /dev/null; then - echo -e "${YELLOW}Homebrew not found. Installing Homebrew...${NC}" - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + echo -e "${YELLOW}Homebrew not found. Installing Homebrew (this may take a while)...${NC}" + # Silencing homebrew installation logs but keeping stderr + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" > /dev/null if [ -f "/opt/homebrew/bin/brew" ]; then eval "$(/opt/homebrew/bin/brew shellenv)" @@ -95,29 +107,17 @@ fi # 2. SYSTEM DEPENDENCIES # ============================================================================= echo -e "${YELLOW}Installing base dependencies...${NC}" -COMMON_DEPS="git curl unzip zsh" -if [[ "$OS_TYPE" == "macos" ]]; then - install_pkg git curl wget unzip zsh -else - # Linux specific checks: using 'gnupg' for cross-distro compatibility - install_pkg wget gnupg $COMMON_DEPS -fi - -# ============================================================================= -# 2. SYSTEM DEPENDENCIES -# ============================================================================= -echo -e "${YELLOW}Installing base dependencies...${NC}" -COMMON_DEPS="git curl unzip zsh" +# Define dependencies as an array to prevent word-splitting issues +COMMON_DEPS=(git curl unzip zsh) if [[ "$OS_TYPE" == "macos" ]]; then install_pkg git curl wget unzip zsh else - # Linux-specific checks: using 'gnupg' for cross-distro compatibility - install_pkg wget gnupg $COMMON_DEPS + # Linux specific checks: using 'gnupg' for cross-distro compatibility + install_pkg wget gnupg "${COMMON_DEPS[@]}" fi - # ============================================================================= # 3. INSTALL STANDALONE TOOLS (Eza) # ============================================================================= @@ -128,23 +128,23 @@ if command -v eza &> /dev/null; then else case "$DISTRO" in ubuntu|debian|pop|kali|linuxmint) + export DEBIAN_FRONTEND=noninteractive sudo mkdir -p /etc/apt/keyrings wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc \ - | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg + | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg > /dev/null 2>&1 || true echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" \ - | sudo tee /etc/apt/sources.list.d/gierens.list + | sudo tee /etc/apt/sources.list.d/gierens.list > /dev/null sudo chmod 644 /etc/apt/keyrings/gierens.gpg \ /etc/apt/sources.list.d/gierens.list - sudo apt update && sudo apt install -y eza + sudo apt-get update -qq -y > /dev/null && sudo apt-get install -qq -y eza > /dev/null ;; fedora) FEDORA_VERSION=$(rpm -E %fedora) - # Fedora 42+ logic (assuming eza isn't in repos yet) if [ "$FEDORA_VERSION" -ge 42 ]; then echo -e "${YELLOW}:: Fedora $FEDORA_VERSION detected. Downloading binary...${NC}" @@ -162,12 +162,9 @@ else FILENAME="eza_${BINARY_ARCH}.tar.gz" URL="https://github.com/eza-community/eza/releases/latest/download/${FILENAME}" - echo -e "${BLUE}Downloading $FILENAME...${NC}" - - # Download and extract in one pipeline to avoid messy temp files - curl -L "$URL" | tar -xz -C /tmp + # Download silently (-sS) and extract + curl -sSL "$URL" | tar -xz -C /tmp - # Move and set permissions if [ -f "/tmp/eza" ]; then sudo mv /tmp/eza /usr/local/bin/eza sudo chmod +x /usr/local/bin/eza @@ -177,9 +174,7 @@ else exit 1 fi else - # Standard repo install for older versions - echo -e "${BLUE}:: Installing eza via DNF...${NC}" - sudo dnf install -y eza + sudo dnf install -q -y eza > /dev/null fi ;; @@ -196,7 +191,8 @@ echo -e "${YELLOW}Setting up Configuration...${NC}" # --- Prepare Directories --- rm -rf ~/.config/eza-themes -git clone --quiet https://github.com/eza-community/eza-themes.git ~/.config/eza-themes +# Clone silently +git clone --quiet https://github.com/eza-community/eza-themes.git ~/.config/eza-themes > /dev/null 2>&1 mkdir -p ~/.config/eza mkdir -p ~/.config @@ -205,52 +201,36 @@ if ! command -v starship &> /dev/null; then if [[ "$OS_TYPE" == "macos" ]]; then install_pkg starship else - curl -sS https://starship.rs/install.sh | sh -s -- -y + # Install starship silently + curl -sS https://starship.rs/install.sh | sh -s -- -y > /dev/null fi fi # --- Theme Arrays --- STARSHIP_THEMES=( - "gruvbox-rainbow" - "nerd-font-symbols" - "no-nerd-font" - "bracketed-segments" - "plain-text-symbols" - "no-runtime-versions" - "no-empty-icons" - "pure-preset" - "pastel-powerline" - "tokyo-night" - "jetpack" - "catppuccin-powerline" + "gruvbox-rainbow" "nerd-font-symbols" "no-nerd-font" + "bracketed-segments" "plain-text-symbols" "no-runtime-versions" + "no-empty-icons" "pure-preset" "pastel-powerline" + "tokyo-night" "jetpack" "catppuccin-powerline" ) EZA_THEMES=( - "gruvbox-dark.yml" - "black.yml" - "catppuccin-frappe.yml" - "catppuccin-latte.yml" - "catppuccin-macchiato.yml" - "catppuccin-mocha.yml" - "default.yml" - "dracula.yml" - "frosty.yml" - "gruvbox-light.yml" - "one_dark.yml" - "rose-pine-dawn.yml" - "rose-pine-moon.yml" - "rose-pine.yml" - "solarized-dark.yml" - "tokyonight.yml" - "white.yml" + "gruvbox-dark.yml" "black.yml" "catppuccin-frappe.yml" + "catppuccin-latte.yml" "catppuccin-macchiato.yml" "catppuccin-mocha.yml" + "default.yml" "dracula.yml" "frosty.yml" "gruvbox-light.yml" + "one_dark.yml" "rose-pine-dawn.yml" "rose-pine-moon.yml" + "rose-pine.yml" "solarized-dark.yml" "tokyonight.yml" "white.yml" ) # --- Interactive Menu Logic --- -# Defaults SELECTED_STARSHIP="gruvbox-rainbow" SELECTED_EZA="gruvbox-dark.yml" if [ "$CI_ENV" != "true" ]; then + if [ ! -t 0 ]; then + exec < /dev/tty + fi + echo -e "\n${CYAN}::: THEME SELECTION :::${NC}" echo "1) Default (Starship: Gruvbox-Rainbow | Eza: Gruvbox-Dark)" echo "2) Custom Selection" @@ -258,7 +238,6 @@ if [ "$CI_ENV" != "true" ]; then read -r THEME_OPT if [[ "$THEME_OPT" == "2" ]]; then - # 1. Select Starship Theme echo -e "\n${BLUE}:: Select Starship Prompt Theme ::${NC}" PS3="Enter number (1-${#STARSHIP_THEMES[@]}): " select s_theme in "${STARSHIP_THEMES[@]}"; do @@ -270,7 +249,6 @@ if [ "$CI_ENV" != "true" ]; then fi done - # 2. Select Eza Theme echo -e "\n${BLUE}:: Select Eza (ls) Theme ::${NC}" PS3="Enter number (1-${#EZA_THEMES[@]}): " select e_theme in "${EZA_THEMES[@]}"; do @@ -288,7 +266,7 @@ fi # --- Apply Configuration --- echo -e "${YELLOW}Applying Starship Preset: ${SELECTED_STARSHIP}...${NC}" -starship preset "$SELECTED_STARSHIP" -o ~/.config/starship.toml || \ +starship preset "$SELECTED_STARSHIP" -o ~/.config/starship.toml > /dev/null 2>&1 || \ echo -e "${RED}Warning: Failed to load preset '$SELECTED_STARSHIP'. Check starship version.${NC}" echo -e "${YELLOW}Applying Eza Theme: ${SELECTED_EZA}...${NC}" @@ -300,17 +278,19 @@ ln -sf "$HOME/.config/eza-themes/themes/${SELECTED_EZA}" "$HOME/.config/eza/them if [ "$CI_ENV" = "true" ]; then echo -e "${YELLOW}>> CI Environment detected. Skipping Font Installation.${NC}" else + if [ ! -t 0 ]; then + exec < /dev/tty + fi + echo -e "\n${CYAN}::: FONT INSTALLATION :::${NC}" echo -ne "${YELLOW}Install FiraCode Nerd Font? [Y/n] (default: Y): ${NC}" read -r FONT_OPT - # Check for 'n' or 'N'. All other inputs (including empty Enter) trigger installation. if [[ "$FONT_OPT" =~ ^[Nn]$ ]]; then echo -e "${BLUE}>> Skipping Font Installation.${NC}" else echo -e "${YELLOW}Installing FiraCode Nerd Font...${NC}" - # Determine Font Directory if [[ "$OS_TYPE" == "macos" ]]; then FONT_DIR="$HOME/Library/Fonts" else @@ -320,17 +300,16 @@ else mkdir -p "$FONT_DIR" TEMP_DIR=$(mktemp -d) - echo -e "${BLUE}Downloading FiraCode.zip...${NC}" - - wget -q --show-progress -O "$TEMP_DIR/FiraCode.zip" "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/FiraCode.zip" + # Removed --show-progress to prevent progress bar spam, replacing it with quiet download + wget -q -O "$TEMP_DIR/FiraCode.zip" "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/FiraCode.zip" unzip -q "$TEMP_DIR/FiraCode.zip" -d "$TEMP_DIR" find "$TEMP_DIR" -name "*.ttf" -exec mv -f {} "$FONT_DIR/" \; 2>/dev/null || true - rm -rf "$TEMP_DIR" - # Refresh Cache (Linux only) + # Immediate cleanup via explicit call (Trap will also handle this if it fails before this line) + [ -n "$TEMP_DIR" ] && rm -rf "$TEMP_DIR" && TEMP_DIR="" + if [[ "$OS_TYPE" == "linux" ]] && command -v fc-cache &> /dev/null; then - echo -e "${BLUE}Updating font cache...${NC}" - fc-cache -f "$FONT_DIR" + fc-cache -f -q "$FONT_DIR" > /dev/null 2>&1 fi echo -e "${GREEN}✔ Font installation complete.${NC}" fi @@ -353,7 +332,7 @@ fi # ============================================================================= # 7. FINALIZE # ============================================================================= -ZSH_PATH=$(which zsh) +ZSH_PATH=$(command -v zsh) if [ "$CI_ENV" = "true" ]; then echo -e "\n${GREEN}✔ CI Environment detected. Installation Verified!${NC}" @@ -361,15 +340,15 @@ if [ "$CI_ENV" = "true" ]; then fi if ! grep -q "$ZSH_PATH" /etc/shells; then - echo "$ZSH_PATH" | sudo tee -a /etc/shells + echo "$ZSH_PATH" | sudo tee -a /etc/shells > /dev/null fi if [ "$SHELL" != "$ZSH_PATH" ]; then if [[ "$OS_TYPE" == "macos" ]]; then - chsh -s "$ZSH_PATH" + chsh -s "$ZSH_PATH" > /dev/null 2>&1 else - sudo usermod --shell "$ZSH_PATH" "$USER" || chsh -s "$ZSH_PATH" + sudo usermod --shell "$ZSH_PATH" "$USER" > /dev/null 2>&1 || chsh -s "$ZSH_PATH" > /dev/null 2>&1 fi fi -echo -e "\n${GREEN}✔ Z-Shift Installation Complete!${NC}" \ No newline at end of file +echo -e "\n${GREEN}✔ Z-Shift Installation Complete! Please restart your terminal.${NC}" \ No newline at end of file From 49c0b6a79c92e9783f5ab545f89ea0164c76d63d Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Tue, 24 Feb 2026 23:30:22 +0200 Subject: [PATCH 02/12] fix: alisases fix and new update alias --- .zshrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.zshrc b/.zshrc index 7006fbe..95c1531 100644 --- a/.zshrc +++ b/.zshrc @@ -145,6 +145,7 @@ alias du='du -h -d 1' # Disk usage depth 1 # --- Zinit & Maintenance --- alias zini='zinit' +unalias zi zpl zplg 2>/dev/null alias zup='zinit self-update && zinit update --parallel && zinit cclear && tldr --update' alias zclean='zinit cclear && zinit delete --clean' @@ -200,7 +201,7 @@ zshift-update() { DATE_STAMP=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="$HOME/.zshrc.zshift_${DATE_STAMP}.bak" TEMP_ZSHRC="$(mktemp)" - + UPDATE_URL="${ZSHIFT_CUSTOM_URL:-https://raw.githubusercontent.com/0xdilshan/Z-SHIFT/main/.zshrc}" echo -e "${BLUE}:: Initiating Z-Shift Update...${NC}" @@ -241,6 +242,8 @@ zshift-update() { exec zsh } +alias zsu='zshift-update' + # ============================================================================= # 7. BYTE-COMPILATION & LOCAL CUSTOMIZATIONS # ============================================================================= From dc1cff31b1637c0ea08c50df4cbe88b56e65d8be Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:30:03 +0200 Subject: [PATCH 03/12] perf: skip_global_compinit --- install.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/install.sh b/install.sh index bb5ee0b..2a47a31 100644 --- a/install.sh +++ b/install.sh @@ -272,6 +272,12 @@ starship preset "$SELECTED_STARSHIP" -o ~/.config/starship.toml > /dev/null 2>&1 echo -e "${YELLOW}Applying Eza Theme: ${SELECTED_EZA}...${NC}" ln -sf "$HOME/.config/eza-themes/themes/${SELECTED_EZA}" "$HOME/.config/eza/theme.yml" +# --- Zsh Environment Optimization --- +echo -e "${YELLOW}Optimizing Zsh startup...${NC}" +if ! grep -q "skip_global_compinit=1" ~/.zshenv 2>/dev/null; then + echo 'skip_global_compinit=1' >> ~/.zshenv +fi + # ============================================================================= # 5. FONTS (FiraCode Nerd Font) # ============================================================================= From f83c5f3327e150df84558e2753e8d1c625b56d01 Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:49:57 +0200 Subject: [PATCH 04/12] fix: shellcheck formattings --- install.sh | 62 +++++++++++++++--------- uninstall.sh | 134 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 131 insertions(+), 65 deletions(-) diff --git a/install.sh b/install.sh index 2a47a31..7dc8381 100644 --- a/install.sh +++ b/install.sh @@ -14,6 +14,22 @@ # Exit immediately if a command exits with a non-zero status set -e +# --- COLORS --- +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# --- ROOT CHECK --- +# Prevent running the script as root (unless in CI) to protect user's $HOME permissions +if [ "$EUID" -eq 0 ] && [ "$CI_ENV" != "true" ]; then + echo -e "${RED}Please do not run this script as root or with sudo.${NC}" + echo -e "${YELLOW}The script will prompt for your sudo password when needed.${NC}" + exit 1 +fi + # --- GLOBAL VARIABLES & CLEANUP TRAP --- TEMP_DIR="" @@ -28,14 +44,6 @@ trap cleanup EXIT INT TERM # --- CONFIGURATION --- ZSHRC_URL="${ZSHIFT_CUSTOM_URL:-https://raw.githubusercontent.com/0xdilshan/Z-SHIFT/main/.zshrc}" -# Colors for output -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -RED='\033[0;31m' -NC='\033[0m' # No Color - echo -e "${CYAN}>>> Initiating Z-Shift Environment Deployment...${NC}" # ============================================================================= @@ -162,17 +170,20 @@ else FILENAME="eza_${BINARY_ARCH}.tar.gz" URL="https://github.com/eza-community/eza/releases/latest/download/${FILENAME}" - # Download silently (-sS) and extract - curl -sSL "$URL" | tar -xz -C /tmp + # Download silently (-sS) and extract securely using a temp dir + EZA_TMP=$(mktemp -d) + curl -sSL "$URL" | tar -xz -C "$EZA_TMP" - if [ -f "/tmp/eza" ]; then - sudo mv /tmp/eza /usr/local/bin/eza + if [ -f "$EZA_TMP/eza" ]; then + sudo mv "$EZA_TMP/eza" /usr/local/bin/eza sudo chmod +x /usr/local/bin/eza echo -e "${GREEN}:: eza installed successfully to /usr/local/bin/eza${NC}" else echo -e "${RED}Error: Binary 'eza' not found in archive.${NC}" + rm -rf "$EZA_TMP" exit 1 fi + rm -rf "$EZA_TMP" else sudo dnf install -q -y eza > /dev/null fi @@ -190,11 +201,11 @@ fi echo -e "${YELLOW}Setting up Configuration...${NC}" # --- Prepare Directories --- -rm -rf ~/.config/eza-themes +rm -rf "$HOME/.config/eza-themes" # Clone silently -git clone --quiet https://github.com/eza-community/eza-themes.git ~/.config/eza-themes > /dev/null 2>&1 -mkdir -p ~/.config/eza -mkdir -p ~/.config +git clone --quiet https://github.com/eza-community/eza-themes.git "$HOME/.config/eza-themes" > /dev/null 2>&1 +mkdir -p "$HOME/.config/eza" +mkdir -p "$HOME/.config" # --- Install Starship Binary if missing --- if ! command -v starship &> /dev/null; then @@ -266,7 +277,7 @@ fi # --- Apply Configuration --- echo -e "${YELLOW}Applying Starship Preset: ${SELECTED_STARSHIP}...${NC}" -starship preset "$SELECTED_STARSHIP" -o ~/.config/starship.toml > /dev/null 2>&1 || \ +starship preset "$SELECTED_STARSHIP" -o "$HOME/.config/starship.toml" > /dev/null 2>&1 || \ echo -e "${RED}Warning: Failed to load preset '$SELECTED_STARSHIP'. Check starship version.${NC}" echo -e "${YELLOW}Applying Eza Theme: ${SELECTED_EZA}...${NC}" @@ -274,8 +285,8 @@ ln -sf "$HOME/.config/eza-themes/themes/${SELECTED_EZA}" "$HOME/.config/eza/them # --- Zsh Environment Optimization --- echo -e "${YELLOW}Optimizing Zsh startup...${NC}" -if ! grep -q "skip_global_compinit=1" ~/.zshenv 2>/dev/null; then - echo 'skip_global_compinit=1' >> ~/.zshenv +if ! grep -q "skip_global_compinit=1" "$HOME/.zshenv" 2>/dev/null; then + echo 'skip_global_compinit=1' >> "$HOME/.zshenv" fi # ============================================================================= @@ -325,20 +336,25 @@ fi # 6. DOWNLOAD .ZSHRC # ============================================================================= echo -e "${YELLOW}Downloading .zshrc from GitHub...${NC}" -[ -f ~/.zshrc ] && mv ~/.zshrc ~/.zshrc.bak +[ -f "$HOME/.zshrc" ] && mv "$HOME/.zshrc" "$HOME/.zshrc.bak" -if curl -fsSL -o ~/.zshrc "$ZSHRC_URL"; then +if curl -fsSL -o "$HOME/.zshrc" "$ZSHRC_URL"; then echo -e "${GREEN}Downloaded .zshrc successfully.${NC}" else echo -e "${RED}Failed to download .zshrc!${NC}" - [ -f ~/.zshrc.bak ] && mv ~/.zshrc.bak ~/.zshrc + [ -f "$HOME/.zshrc.bak" ] && mv "$HOME/.zshrc.bak" "$HOME/.zshrc" exit 1 fi # ============================================================================= # 7. FINALIZE # ============================================================================= -ZSH_PATH=$(command -v zsh) +ZSH_PATH=$(command -v zsh || true) + +if [ -z "$ZSH_PATH" ]; then + echo -e "${RED}Error: Zsh binary not found. Please verify the installation.${NC}" + exit 1 +fi if [ "$CI_ENV" = "true" ]; then echo -e "\n${GREEN}✔ CI Environment detected. Installation Verified!${NC}" diff --git a/uninstall.sh b/uninstall.sh index 926ddbe..0e53442 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,17 +1,36 @@ #!/bin/bash # ============================================================================= -# Z-SHIFT: Cleanup & Restoration Script (Final Hardened Version) +# Z-SHIFT: Cleanup & Restoration Script # ============================================================================= # Colors for output -RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' +CYAN='\033[0;36m' +RED='\033[0;31m' +NC='\033[0m' # No Color -echo -e "${BLUE}>>> Starting Z-Shift Removal...${NC}" +echo -e "${CYAN}>>> Initiating Z-Shift Environment Removal...${NC}" + +# ============================================================================= +# 0. OS & PACKAGE MANAGER DETECTION +# ============================================================================= +OS_TYPE="unknown" +DISTRO="unknown" + +if [[ "$OSTYPE" == "darwin"* ]]; then + OS_TYPE="macos" + DISTRO="macos" +elif [ -f /etc/os-release ]; then + OS_TYPE="linux" + # shellcheck disable=SC1091 + . /etc/os-release + DISTRO="$ID" +fi + +echo -e "${BLUE}Detected OS: ${OS_TYPE} (${DISTRO})${NC}" # ----------------------------------------------------------------------------- # Helper: Detect current shell safely @@ -27,7 +46,7 @@ get_current_shell() { # ----------------------------------------------------------------------------- # 1. RESTORE PREVIOUS SHELL # ----------------------------------------------------------------------------- -if [[ "$OSTYPE" != "darwin"* ]]; then +if [[ "$OS_TYPE" != "macos" ]]; then CURRENT_SHELL=$(get_current_shell) if [[ "$CURRENT_SHELL" == *"zsh"* ]]; then @@ -35,13 +54,16 @@ if [[ "$OSTYPE" != "darwin"* ]]; then if [ -n "$BASH_PATH" ]; then echo -e "${YELLOW}:: Reverting default shell to Bash...${NC}" - # Try usermod first, fallback to chsh - sudo usermod --shell "$BASH_PATH" "$USER" 2>/dev/null || chsh -s "$BASH_PATH" - echo -e "${GREEN}✔ Default shell reverted to $BASH_PATH.${NC}" + if sudo usermod --shell "$BASH_PATH" "$USER" 2>/dev/null || chsh -s "$BASH_PATH"; then + echo -e "${GREEN}✔ Default shell reverted to $BASH_PATH.${NC}" + else + echo -e "${RED}✘ Failed to revert default shell. You may need to do this manually.${NC}" + fi + else + echo -e "${RED}✘ Bash not found in PATH. Cannot automatically revert shell.${NC}" fi fi else - # On Mac, Zsh is the system default. We leave it as is. echo -e "${GREEN}:: macOS detected. Keeping Zsh as system default.${NC}" fi @@ -50,7 +72,7 @@ fi # ----------------------------------------------------------------------------- echo -e "${YELLOW}:: Cleaning up configuration files...${NC}" -# Restore .zshrc backup if available, otherwise just delete the Z-Shift one +# Restore .zshrc backup if [ -f "$HOME/.zshrc.bak" ]; then mv "$HOME/.zshrc.bak" "$HOME/.zshrc" echo -e "${GREEN}✔ Restored previous .zshrc from backup.${NC}" @@ -59,41 +81,66 @@ else echo -e "${YELLOW}:: No backup found. Removed Z-Shift .zshrc.${NC}" fi -# Remove Z-Shift specific config files +# Remove Z-Shift added line in .zshenv +if [ -f "$HOME/.zshenv" ]; then + if grep -q "skip_global_compinit=1" "$HOME/.zshenv"; then + grep -v "skip_global_compinit=1" "$HOME/.zshenv" > "$HOME/.zshenv.tmp" && mv "$HOME/.zshenv.tmp" "$HOME/.zshenv" + echo -e "${GREEN}✔ Cleaned up ~/.zshenv.${NC}" + fi + [ ! -s "$HOME/.zshenv" ] && rm -f "$HOME/.zshenv" +fi + +# Remove Z-Shift directories rm -f "$HOME/.config/starship.toml" rm -rf "$HOME/.config/eza" rm -rf "$HOME/.config/eza-themes" -# Remove Zinit plugins and data +# Remove Zinit data ZINIT_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/zinit" -rm -rf "$ZINIT_DIR" -echo -e "${GREEN}✔ Configuration and plugin data removed.${NC}" +if [ -d "$ZINIT_DIR" ]; then + rm -rf "$ZINIT_DIR" + echo -e "${GREEN}✔ Plugin data removed.${NC}" +fi # ----------------------------------------------------------------------------- # 3. OPTIONAL: REMOVE BINARIES # ----------------------------------------------------------------------------- if [ "$CI_ENV" != "true" ]; then - echo -ne "${CYAN}Do you want to uninstall the CLI tools (eza, bat, fd, etc.)? [y/N]: ${NC}" - read -r REPLY - if [[ "$REPLY" =~ ^[Yy]$ ]]; then - echo -e "${YELLOW}:: Removing binaries...${NC}" + if [ ! -t 0 ]; then exec < /dev/tty; fi - if [[ "$OSTYPE" == "darwin"* ]]; then - brew uninstall eza bat fd fzf ripgrep tealdeer zoxide starship 2>/dev/null || true - elif [ -f /etc/debian_version ]; then - sudo apt remove -y eza bat fd-find fzf ripgrep starship 2>/dev/null || true - elif [ -f /etc/fedora-release ]; then - sudo dnf remove -y eza bat fd fzf ripgrep starship 2>/dev/null || true - elif [ -f /etc/arch-release ]; then - sudo pacman -Rs --noconfirm eza bat fd fzf ripgrep starship 2>/dev/null || true - fi + echo -ne "${CYAN}Do you want to uninstall the CLI tools (eza, starship)? [y/N]: ${NC}" + read -r REPLY_BINS + if [[ "$REPLY_BINS" =~ ^[Yy]$ ]]; then + echo -e "${YELLOW}:: Removing binaries...${NC}" - # IMPORTANT: Remove manual script-installed binaries - # These are often missed by package managers - [ -f /usr/local/bin/eza ] && sudo rm -f /usr/local/bin/eza - [ -f /usr/local/bin/starship ] && sudo rm -f /usr/local/bin/starship + case $DISTRO in + ubuntu|debian|pop|kali|linuxmint) + export DEBIAN_FRONTEND=noninteractive + sudo apt-get remove -qq -y eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via APT.${NC}" + + sudo rm -f /etc/apt/sources.list.d/gierens.list + sudo rm -f /etc/apt/keyrings/gierens.gpg + sudo apt-get update -qq -y > /dev/null 2>&1 || true + ;; + arch|manjaro|endeavouros) + sudo pacman -Rs --noconfirm eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via Pacman.${NC}" + ;; + fedora|rhel|centos) + sudo dnf remove -q -y eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via DNF.${NC}" + ;; + macos) + brew uninstall -q eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via Brew.${NC}" + ;; + esac + + # Manual binary removal for custom paths + for bin in /usr/local/bin/eza /usr/local/bin/starship; do + if [ -f "$bin" ]; then + sudo rm -f "$bin" || echo -e "${RED}✘ Failed to remove $bin${NC}" + fi + done - echo -e "${GREEN}✔ Binary cleanup complete.${NC}" + echo -e "${GREEN}✔ Binary cleanup attempt complete.${NC}" fi fi @@ -102,19 +149,22 @@ fi # ----------------------------------------------------------------------------- if [ "$CI_ENV" != "true" ]; then echo -ne "${CYAN}Do you want to remove FiraCode Nerd Fonts? [y/N]: ${NC}" - read -r REPLY - if [[ "$REPLY" =~ ^[Yy]$ ]]; then + read -r REPLY_FONTS + if [[ "$REPLY_FONTS" =~ ^[Yy]$ ]]; then echo -e "${YELLOW}:: Removing fonts...${NC}" + FONT_DIR="$HOME/.local/share/fonts" - [[ "$OSTYPE" == "darwin"* ]] && FONT_DIR="$HOME/Library/Fonts" - - rm -f "$FONT_DIR"/FiraCode* 2>/dev/null - - # Refresh font cache if the tool exists - if command -v fc-cache >/dev/null 2>&1; then - fc-cache -f "$FONT_DIR" || true + [[ "$OS_TYPE" == "macos" ]] && FONT_DIR="$HOME/Library/Fonts" + + if ls "$FONT_DIR"/FiraCode* >/dev/null 2>&1; then + rm -f "$FONT_DIR"/FiraCode* + if [[ "$OS_TYPE" == "linux" ]] && command -v fc-cache >/dev/null 2>&1; then + fc-cache -f -q "$FONT_DIR" > /dev/null 2>&1 || true + fi + echo -e "${GREEN}✔ Fonts removed.${NC}" + else + echo -e "${YELLOW}:: No FiraCode fonts found in $FONT_DIR.${NC}" fi - echo -e "${GREEN}✔ Fonts removed.${NC}" fi fi From 98de4fbb6773d34a15b3270d16f6c2c03af2f477 Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:14:19 +0200 Subject: [PATCH 05/12] fix: install.sh improvements --- install.sh | 138 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 61 deletions(-) diff --git a/install.sh b/install.sh index 7dc8381..9fca057 100644 --- a/install.sh +++ b/install.sh @@ -11,8 +11,9 @@ # Z-SHIFT: High-Performance Zsh + Starship + Zinit installation script # ============================================================================= -# Exit immediately if a command exits with a non-zero status -set -e +# Removed bare 'set -e' in favour of explicit checks on critical commands — +# 'set -e' interacts poorly with subshells and conditional logic. +set -uo pipefail # --- COLORS --- GREEN='\033[0;32m' @@ -20,24 +21,22 @@ YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' RED='\033[0;31m' -NC='\033[0m' # No Color +NC='\033[0m' # --- ROOT CHECK --- -# Prevent running the script as root (unless in CI) to protect user's $HOME permissions -if [ "$EUID" -eq 0 ] && [ "$CI_ENV" != "true" ]; then +if [ "$EUID" -eq 0 ] && [ "${CI_ENV:-}" != "true" ]; then echo -e "${RED}Please do not run this script as root or with sudo.${NC}" echo -e "${YELLOW}The script will prompt for your sudo password when needed.${NC}" exit 1 fi # --- GLOBAL VARIABLES & CLEANUP TRAP --- -TEMP_DIR="" +TEMP_DIRS=() cleanup() { - # This runs automatically on script exit, interruption, or termination - if [ -n "$TEMP_DIR" ] && [ -d "$TEMP_DIR" ]; then - rm -rf "$TEMP_DIR" - fi + for d in "${TEMP_DIRS[@]}"; do + [ -n "$d" ] && [ -d "$d" ] && rm -rf "$d" + done } trap cleanup EXIT INT TERM @@ -64,7 +63,6 @@ fi echo -e "${BLUE}Detected OS: ${OS_TYPE} (${DISTRO})${NC}" -# Helper function to install packages silently based on distro install_pkg() { local pkgs=("$@") echo -e "${YELLOW}Installing: ${pkgs[*]}...${NC}" @@ -100,9 +98,9 @@ install_pkg() { if [[ "$OS_TYPE" == "macos" ]]; then if ! command -v brew &> /dev/null; then echo -e "${YELLOW}Homebrew not found. Installing Homebrew (this may take a while)...${NC}" - # Silencing homebrew installation logs but keeping stderr - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" > /dev/null - + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" > /dev/null || { + echo -e "${RED}Homebrew installation failed.${NC}"; exit 1 + } if [ -f "/opt/homebrew/bin/brew" ]; then eval "$(/opt/homebrew/bin/brew shellenv)" elif [ -f "/usr/local/bin/brew" ]; then @@ -116,13 +114,11 @@ fi # ============================================================================= echo -e "${YELLOW}Installing base dependencies...${NC}" -# Define dependencies as an array to prevent word-splitting issues COMMON_DEPS=(git curl unzip zsh) if [[ "$OS_TYPE" == "macos" ]]; then install_pkg git curl wget unzip zsh else - # Linux specific checks: using 'gnupg' for cross-distro compatibility install_pkg wget gnupg "${COMMON_DEPS[@]}" fi @@ -170,9 +166,12 @@ else FILENAME="eza_${BINARY_ARCH}.tar.gz" URL="https://github.com/eza-community/eza/releases/latest/download/${FILENAME}" - # Download silently (-sS) and extract securely using a temp dir EZA_TMP=$(mktemp -d) - curl -sSL "$URL" | tar -xz -C "$EZA_TMP" + TEMP_DIRS+=("$EZA_TMP") + + curl -sSL "$URL" | tar -xz -C "$EZA_TMP" || { + echo -e "${RED}Error: Failed to download/extract eza binary.${NC}"; exit 1 + } if [ -f "$EZA_TMP/eza" ]; then sudo mv "$EZA_TMP/eza" /usr/local/bin/eza @@ -180,10 +179,8 @@ else echo -e "${GREEN}:: eza installed successfully to /usr/local/bin/eza${NC}" else echo -e "${RED}Error: Binary 'eza' not found in archive.${NC}" - rm -rf "$EZA_TMP" exit 1 fi - rm -rf "$EZA_TMP" else sudo dnf install -q -y eza > /dev/null fi @@ -200,24 +197,23 @@ fi # ============================================================================= echo -e "${YELLOW}Setting up Configuration...${NC}" -# --- Prepare Directories --- rm -rf "$HOME/.config/eza-themes" -# Clone silently git clone --quiet https://github.com/eza-community/eza-themes.git "$HOME/.config/eza-themes" > /dev/null 2>&1 mkdir -p "$HOME/.config/eza" mkdir -p "$HOME/.config" -# --- Install Starship Binary if missing --- -if ! command -v starship &> /dev/null; then +if command -v starship &> /dev/null; then + echo -e "${GREEN}:: Starship is already installed. Skipping.${NC}" +else if [[ "$OS_TYPE" == "macos" ]]; then install_pkg starship else - # Install starship silently - curl -sS https://starship.rs/install.sh | sh -s -- -y > /dev/null + curl -sS https://starship.rs/install.sh | sh -s -- -y > /dev/null || { + echo -e "${RED}Starship installation failed.${NC}"; exit 1 + } fi fi -# --- Theme Arrays --- STARSHIP_THEMES=( "gruvbox-rainbow" "nerd-font-symbols" "no-nerd-font" "bracketed-segments" "plain-text-symbols" "no-runtime-versions" @@ -233,11 +229,10 @@ EZA_THEMES=( "rose-pine.yml" "solarized-dark.yml" "tokyonight.yml" "white.yml" ) -# --- Interactive Menu Logic --- SELECTED_STARSHIP="gruvbox-rainbow" SELECTED_EZA="gruvbox-dark.yml" -if [ "$CI_ENV" != "true" ]; then +if [ "${CI_ENV:-}" != "true" ]; then if [ ! -t 0 ]; then exec < /dev/tty fi @@ -275,7 +270,6 @@ if [ "$CI_ENV" != "true" ]; then fi fi -# --- Apply Configuration --- echo -e "${YELLOW}Applying Starship Preset: ${SELECTED_STARSHIP}...${NC}" starship preset "$SELECTED_STARSHIP" -o "$HOME/.config/starship.toml" > /dev/null 2>&1 || \ echo -e "${RED}Warning: Failed to load preset '$SELECTED_STARSHIP'. Check starship version.${NC}" @@ -283,7 +277,6 @@ starship preset "$SELECTED_STARSHIP" -o "$HOME/.config/starship.toml" > /dev/nul echo -e "${YELLOW}Applying Eza Theme: ${SELECTED_EZA}...${NC}" ln -sf "$HOME/.config/eza-themes/themes/${SELECTED_EZA}" "$HOME/.config/eza/theme.yml" -# --- Zsh Environment Optimization --- echo -e "${YELLOW}Optimizing Zsh startup...${NC}" if ! grep -q "skip_global_compinit=1" "$HOME/.zshenv" 2>/dev/null; then echo 'skip_global_compinit=1' >> "$HOME/.zshenv" @@ -292,43 +285,58 @@ fi # ============================================================================= # 5. FONTS (FiraCode Nerd Font) # ============================================================================= -if [ "$CI_ENV" = "true" ]; then +if [ "${CI_ENV:-}" = "true" ]; then echo -e "${YELLOW}>> CI Environment detected. Skipping Font Installation.${NC}" else if [ ! -t 0 ]; then exec < /dev/tty fi - echo -e "\n${CYAN}::: FONT INSTALLATION :::${NC}" - echo -ne "${YELLOW}Install FiraCode Nerd Font? [Y/n] (default: Y): ${NC}" - read -r FONT_OPT + if [[ "$OS_TYPE" == "macos" ]]; then + FONT_DIR="$HOME/Library/Fonts" + else + FONT_DIR="$HOME/.local/share/fonts" + fi - if [[ "$FONT_OPT" =~ ^[Nn]$ ]]; then - echo -e "${BLUE}>> Skipping Font Installation.${NC}" + if ls "$FONT_DIR"/FiraCode* >/dev/null 2>&1; then + echo -e "${GREEN}:: FiraCode Nerd Font already installed. Skipping.${NC}" else - echo -e "${YELLOW}Installing FiraCode Nerd Font...${NC}" - - if [[ "$OS_TYPE" == "macos" ]]; then - FONT_DIR="$HOME/Library/Fonts" + echo -e "\n${CYAN}::: FONT INSTALLATION :::${NC}" + echo -ne "${YELLOW}Install FiraCode Nerd Font? [Y/n] (default: Y): ${NC}" + read -r FONT_OPT + + if [[ "$FONT_OPT" =~ ^[Nn]$ ]]; then + echo -e "${BLUE}>> Skipping Font Installation.${NC}" else - FONT_DIR="$HOME/.local/share/fonts" - fi - - mkdir -p "$FONT_DIR" - TEMP_DIR=$(mktemp -d) - - # Removed --show-progress to prevent progress bar spam, replacing it with quiet download - wget -q -O "$TEMP_DIR/FiraCode.zip" "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/FiraCode.zip" - unzip -q "$TEMP_DIR/FiraCode.zip" -d "$TEMP_DIR" - find "$TEMP_DIR" -name "*.ttf" -exec mv -f {} "$FONT_DIR/" \; 2>/dev/null || true - - # Immediate cleanup via explicit call (Trap will also handle this if it fails before this line) - [ -n "$TEMP_DIR" ] && rm -rf "$TEMP_DIR" && TEMP_DIR="" - - if [[ "$OS_TYPE" == "linux" ]] && command -v fc-cache &> /dev/null; then - fc-cache -f -q "$FONT_DIR" > /dev/null 2>&1 + echo -e "${YELLOW}Installing FiraCode Nerd Font...${NC}" + + mkdir -p "$FONT_DIR" + + FONT_VER=$(curl -fsSL "https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest" \ + | grep '"tag_name"' | cut -d'"' -f4) + if [ -z "$FONT_VER" ]; then + echo -e "${YELLOW}Warning: Could not determine latest font version. Falling back to v3.4.0.${NC}" + FONT_VER="v3.4.0" + fi + + FONT_TMP=$(mktemp -d) + TEMP_DIRS+=("$FONT_TMP") + + wget -q -O "$FONT_TMP/FiraCode.zip" \ + "https://github.com/ryanoasis/nerd-fonts/releases/download/${FONT_VER}/FiraCode.zip" || { + echo -e "${RED}Font download failed. Skipping.${NC}" + } + + if [ -f "$FONT_TMP/FiraCode.zip" ]; then + unzip -q "$FONT_TMP/FiraCode.zip" -d "$FONT_TMP" + find "$FONT_TMP" -name "*.ttf" -exec mv -f {} "$FONT_DIR/" \; 2>/dev/null || true + + if [[ "$OS_TYPE" == "linux" ]] && command -v fc-cache &> /dev/null; then + fc-cache -f -q "$FONT_DIR" > /dev/null 2>&1 + fi + echo -e "${GREEN}✔ Font installation complete (${FONT_VER}).${NC}" + fi fi - echo -e "${GREEN}✔ Font installation complete.${NC}" fi fi @@ -356,7 +364,7 @@ if [ -z "$ZSH_PATH" ]; then exit 1 fi -if [ "$CI_ENV" = "true" ]; then +if [ "${CI_ENV:-}" = "true" ]; then echo -e "\n${GREEN}✔ CI Environment detected. Installation Verified!${NC}" exit 0 fi @@ -367,9 +375,17 @@ fi if [ "$SHELL" != "$ZSH_PATH" ]; then if [[ "$OS_TYPE" == "macos" ]]; then - chsh -s "$ZSH_PATH" > /dev/null 2>&1 + if ! chsh -s "$ZSH_PATH" 2>&1; then + echo -e "${YELLOW}Warning: Could not set Zsh as default shell automatically.${NC}" + echo -e "${YELLOW}Run manually: chsh -s ${ZSH_PATH}${NC}" + fi else - sudo usermod --shell "$ZSH_PATH" "$USER" > /dev/null 2>&1 || chsh -s "$ZSH_PATH" > /dev/null 2>&1 + if ! sudo usermod --shell "$ZSH_PATH" "$USER" > /dev/null 2>&1; then + if ! chsh -s "$ZSH_PATH"; then + echo -e "${YELLOW}Warning: Could not set Zsh as default shell automatically.${NC}" + echo -e "${YELLOW}Run manually: chsh -s ${ZSH_PATH}${NC}" + fi + fi fi fi From 8ec7453256882f8d580e820bb22ca3501cebe69d Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:16:51 +0200 Subject: [PATCH 06/12] add: new shellcheck config --- .shellcheckrc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .shellcheckrc diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 0000000..04e1e47 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1,12 @@ +# .shellcheckrc: Shared Shellcheck configuration for Z-Shift +# FIX #12: Centralises ignore rules so CI (ci.yml) and local tests +# (tests/local_test.sh) use identical linting settings without duplication. + +# SC2086: Double-quoting variables — suppressed for flexibility in install_pkg +disable=SC2086 + +# SC2034: Variable appears unused — suppressed for sourced env vars +disable=SC2034 + +# SC1091: Not following sourced files — suppressed for /etc/os-release +disable=SC1091 From cf5bd4a03ba5634e64b3a1a950bac9a85d2ac59a Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:24:17 +0200 Subject: [PATCH 07/12] add: more safety checks for .zshrc backup file --- .zshrc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.zshrc b/.zshrc index 95c1531..073515c 100644 --- a/.zshrc +++ b/.zshrc @@ -145,10 +145,15 @@ alias du='du -h -d 1' # Disk usage depth 1 # --- Zinit & Maintenance --- alias zini='zinit' -unalias zi zpl zplg 2>/dev/null alias zup='zinit self-update && zinit update --parallel && zinit cclear && tldr --update' alias zclean='zinit cclear && zinit delete --clean' +# This avoids a noisy warning if the aliases were never set. + +(( ${+aliases[zi]} )) && unalias zi +(( ${+aliases[zpl]} )) && unalias zpl +(( ${+aliases[zplg]})) && unalias zplg + # --- Eza (The ls replacement) --- if [[ -n "${commands[eza]}" ]]; then alias ls='eza --icons --group-directories-first --git' @@ -224,6 +229,19 @@ zshift-update() { cp "$HOME/.zshrc" "$BACKUP_FILE" fi + # Warn the user if their current .zshrc differs from the backup, + if [ -f "$BACKUP_FILE" ] && ! diff -q "$HOME/.zshrc" "$BACKUP_FILE" > /dev/null 2>&1; then + echo -e "${YELLOW}!! Warning: Your .zshrc has local modifications.${NC}" + echo -e "${YELLOW} These will be replaced. Move personal config to ~/.zshrc.local to preserve it.${NC}" + echo -ne "${YELLOW} Continue anyway? [y/N]: ${NC}" + read -r REPLY + if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then + echo -e "${BLUE}:: Update cancelled.${NC}" + rm -f "$TEMP_ZSHRC" + return 0 + fi + fi + mv "$TEMP_ZSHRC" "$HOME/.zshrc" echo -e "${GREEN}:: Configuration file updated.${NC}" From c135a44f39658fc74bac834211a218212be1026d Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:28:21 +0200 Subject: [PATCH 08/12] fix: uninstall.sh fedora fixes --- uninstall.sh | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/uninstall.sh b/uninstall.sh index 0e53442..807e214 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -4,13 +4,12 @@ # Z-SHIFT: Cleanup & Restoration Script # ============================================================================= -# Colors for output GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' RED='\033[0;31m' -NC='\033[0m' # No Color +NC='\033[0m' echo -e "${CYAN}>>> Initiating Z-Shift Environment Removal...${NC}" @@ -32,9 +31,6 @@ fi echo -e "${BLUE}Detected OS: ${OS_TYPE} (${DISTRO})${NC}" -# ----------------------------------------------------------------------------- -# Helper: Detect current shell safely -# ----------------------------------------------------------------------------- get_current_shell() { if command -v getent >/dev/null 2>&1; then getent passwd "$USER" | cut -d: -f7 @@ -72,7 +68,6 @@ fi # ----------------------------------------------------------------------------- echo -e "${YELLOW}:: Cleaning up configuration files...${NC}" -# Restore .zshrc backup if [ -f "$HOME/.zshrc.bak" ]; then mv "$HOME/.zshrc.bak" "$HOME/.zshrc" echo -e "${GREEN}✔ Restored previous .zshrc from backup.${NC}" @@ -81,7 +76,6 @@ else echo -e "${YELLOW}:: No backup found. Removed Z-Shift .zshrc.${NC}" fi -# Remove Z-Shift added line in .zshenv if [ -f "$HOME/.zshenv" ]; then if grep -q "skip_global_compinit=1" "$HOME/.zshenv"; then grep -v "skip_global_compinit=1" "$HOME/.zshenv" > "$HOME/.zshenv.tmp" && mv "$HOME/.zshenv.tmp" "$HOME/.zshenv" @@ -90,25 +84,23 @@ if [ -f "$HOME/.zshenv" ]; then [ ! -s "$HOME/.zshenv" ] && rm -f "$HOME/.zshenv" fi -# Remove Z-Shift directories rm -f "$HOME/.config/starship.toml" rm -rf "$HOME/.config/eza" rm -rf "$HOME/.config/eza-themes" -# Remove Zinit data ZINIT_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/zinit" if [ -d "$ZINIT_DIR" ]; then rm -rf "$ZINIT_DIR" - echo -e "${GREEN}✔ Plugin data removed.${NC}" + echo -e "${GREEN}✔ Plugin data removed (includes Zinit-managed tool binaries: bat, fd, fzf, rg, zoxide, eza).${NC}" fi # ----------------------------------------------------------------------------- # 3. OPTIONAL: REMOVE BINARIES # ----------------------------------------------------------------------------- -if [ "$CI_ENV" != "true" ]; then +if [ "${CI_ENV:-}" != "true" ]; then if [ ! -t 0 ]; then exec < /dev/tty; fi - echo -ne "${CYAN}Do you want to uninstall the CLI tools (eza, starship)? [y/N]: ${NC}" + echo -ne "${CYAN}Do you want to uninstall the system CLI tools (eza, starship)? [y/N]: ${NC}" read -r REPLY_BINS if [[ "$REPLY_BINS" =~ ^[Yy]$ ]]; then echo -e "${YELLOW}:: Removing binaries...${NC}" @@ -117,7 +109,6 @@ if [ "$CI_ENV" != "true" ]; then ubuntu|debian|pop|kali|linuxmint) export DEBIAN_FRONTEND=noninteractive sudo apt-get remove -qq -y eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via APT.${NC}" - sudo rm -f /etc/apt/sources.list.d/gierens.list sudo rm -f /etc/apt/keyrings/gierens.gpg sudo apt-get update -qq -y > /dev/null 2>&1 || true @@ -126,33 +117,49 @@ if [ "$CI_ENV" != "true" ]; then sudo pacman -Rs --noconfirm eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via Pacman.${NC}" ;; fedora|rhel|centos) - sudo dnf remove -q -y eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via DNF.${NC}" + # Remove the manual binary first; only attempt dnf for older Fedora releases + # where dnf was actually used — this avoids a confusing "not installed" error. + FEDORA_VERSION=$(rpm -E %fedora 2>/dev/null || echo "0") + if [ "$FEDORA_VERSION" -ge 42 ]; then + if [ -f /usr/local/bin/eza ]; then + sudo rm -f /usr/local/bin/eza + echo -e "${GREEN}✔ Removed manually-installed eza binary.${NC}" + fi + # Starship may still be in /usr/local/bin from its install script + if [ -f /usr/local/bin/starship ]; then + sudo rm -f /usr/local/bin/starship + echo -e "${GREEN}✔ Removed starship binary.${NC}" + fi + else + sudo dnf remove -q -y eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via DNF.${NC}" + fi ;; macos) brew uninstall -q eza starship > /dev/null 2>&1 || echo -e "${RED}! Some packages could not be removed via Brew.${NC}" ;; esac - # Manual binary removal for custom paths + # Catch-all for any remaining manual installs in /usr/local/bin + # (e.g. starship installed via its curl script on non-Fedora distros) for bin in /usr/local/bin/eza /usr/local/bin/starship; do if [ -f "$bin" ]; then - sudo rm -f "$bin" || echo -e "${RED}✘ Failed to remove $bin${NC}" + sudo rm -f "$bin" && echo -e "${GREEN}✔ Removed $bin${NC}" || echo -e "${RED}✘ Failed to remove $bin${NC}" fi done - - echo -e "${GREEN}✔ Binary cleanup attempt complete.${NC}" + + echo -e "${GREEN}✔ Binary cleanup complete.${NC}" fi fi # ----------------------------------------------------------------------------- # 4. OPTIONAL: REMOVE FONTS # ----------------------------------------------------------------------------- -if [ "$CI_ENV" != "true" ]; then +if [ "${CI_ENV:-}" != "true" ]; then echo -ne "${CYAN}Do you want to remove FiraCode Nerd Fonts? [y/N]: ${NC}" read -r REPLY_FONTS if [[ "$REPLY_FONTS" =~ ^[Yy]$ ]]; then echo -e "${YELLOW}:: Removing fonts...${NC}" - + FONT_DIR="$HOME/.local/share/fonts" [[ "$OS_TYPE" == "macos" ]] && FONT_DIR="$HOME/Library/Fonts" From 98821b64aa2133b6243333759a83cc50a507f38f Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:30:00 +0200 Subject: [PATCH 09/12] fix: hadle local_test path issues --- tests/local_test.sh | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/tests/local_test.sh b/tests/local_test.sh index cece7ef..e3d9dc3 100644 --- a/tests/local_test.sh +++ b/tests/local_test.sh @@ -1,17 +1,19 @@ #!/bin/bash # tests/local_test.sh -# Colors +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' -echo "Running Z-Shift Local Tests..." +echo "Running Z-Shift Local Tests (repo root: $REPO_ROOT)..." -# Check if files exist -REQUIRED_FILES=("install.sh" ".zshrc" "README.md") +# Check required files exist +REQUIRED_FILES=("install.sh" ".zshrc" "README.md" "theme.sh" "uninstall.sh") for file in "${REQUIRED_FILES[@]}"; do - if [ -f "../$file" ] || [ -f "$file" ]; then + if [ -f "$REPO_ROOT/$file" ]; then echo -e "[${GREEN}PASS${NC}] File $file exists" else echo -e "[${RED}FAIL${NC}] File $file missing" @@ -19,14 +21,9 @@ for file in "${REQUIRED_FILES[@]}"; do fi done -# Syntax Check (Zsh) +# Zsh syntax check if command -v zsh >/dev/null; then - # We look for .zshrc in parent dir or current dir - ZSHRC_PATH="" - [ -f ".zshrc" ] && ZSHRC_PATH=".zshrc" - [ -f "../.zshrc" ] && ZSHRC_PATH="../.zshrc" - - if zsh -n "$ZSHRC_PATH"; then + if zsh -n "$REPO_ROOT/.zshrc"; then echo -e "[${GREEN}PASS${NC}] .zshrc syntax is valid" else echo -e "[${RED}FAIL${NC}] .zshrc contains syntax errors" @@ -37,18 +34,18 @@ else fi # Shellcheck (Bash) +# from the repo root automatically, keeping rules in sync with CI. if command -v shellcheck >/dev/null; then - INSTALL_PATH="" - [ -f "install.sh" ] && INSTALL_PATH="install.sh" - [ -f "../install.sh" ] && INSTALL_PATH="../install.sh" - - # We exclude warning SC2181 (checking $? directly) as it's common in install scripts - if shellcheck -e SC2181 "$INSTALL_PATH"; then - echo -e "[${GREEN}PASS${NC}] install.sh passed shellcheck" - else - echo -e "[${RED}FAIL${NC}] install.sh failed shellcheck" - exit 1 - fi + FAILED=0 + for script in install.sh theme.sh uninstall.sh; do + if shellcheck "$REPO_ROOT/$script"; then + echo -e "[${GREEN}PASS${NC}] $script passed shellcheck" + else + echo -e "[${RED}FAIL${NC}] $script failed shellcheck" + FAILED=1 + fi + done + [ "$FAILED" -eq 1 ] && exit 1 else echo -e "[${RED}WARN${NC}] shellcheck not installed, skipping linting" fi From ecef5b3346b78d8c0d59d1f48308dfbe269b7552 Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:34:39 +0200 Subject: [PATCH 10/12] fix: updated ci workflow --- .github/workflows/ci.yml | 118 ++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e41e5aa..2391421 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ on: jobs: # ----------------------------------------------------------------------------- # JOB 1: STATIC ANALYSIS (LINTING) + # CI and local test use identical rules without duplicating the ignore list. # ----------------------------------------------------------------------------- lint: runs-on: ubuntu-latest @@ -19,19 +20,20 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install Shellcheck - run: sudo apt-get install -y shellcheck + - name: Install Shellcheck & Zsh + run: sudo apt-get install -y shellcheck zsh - name: Lint Installer (Bash) - # SC2086: Double quote variables (ignored for flexibility) - # SC2034: Unused variables (ignored) - # SC1091: Not following sourced files (ignored for /etc/os-release) - run: shellcheck -e SC2086,SC2034,SC1091 install.sh + run: shellcheck install.sh - - name: Verify Zsh Syntax - run: | - sudo apt-get install -y zsh - zsh -n .zshrc + - name: Lint Theme Switcher (Bash) + run: shellcheck theme.sh + + - name: Lint Uninstaller (Bash) + run: shellcheck uninstall.sh + + - name: Verify Zsh Syntax (.zshrc) + run: zsh -n .zshrc # ----------------------------------------------------------------------------- # JOB 2: INTEGRATION TEST (UBUNTU & MACOS) @@ -44,7 +46,7 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} - + steps: - uses: actions/checkout@v4 @@ -52,11 +54,9 @@ jobs: run: chmod +x install.sh - name: Run Installer (Non-Interactive) - # Pipes 'yes' for prompts. Uses CI_ENV to skip fonts/chsh. - run: | - yes | ./install.sh + run: yes | ./install.sh env: - CI_ENV: true + CI_ENV: true - name: Verify Zshrc Created run: | @@ -65,17 +65,34 @@ jobs: exit 1 fi - # FIX FOR MAC/UBUNTU: - # We must run zsh once to trigger the Zinit git clone inside .zshrc + # Run zsh once to trigger the Zinit git clone inside .zshrc. - name: Bootstrap Zinit (Initialize Zsh) - run: zsh -ic "exit" || true + run: | + zsh -ic "exit" 2>&1 || echo "Note: zsh bootstrap exited non-zero (likely async plugin load — see output above)" - - name: Verify Plugins Installed + - name: Verify Zinit Installed run: | - # Check standard XDG path or legacy path if [ ! -d "${HOME}/.local/share/zinit" ] && [ ! -d "${HOME}/.zinit" ]; then - echo "Error: Zinit directory not found! Plugin installation failed." - exit 1 + echo "Error: Zinit directory not found! Plugin installation failed." + exit 1 + fi + + + - name: Verify Core Tools Installed + run: | + MISSING=() + for tool in eza bat fzf zoxide starship; do + if zsh -ic "command -v $tool" > /dev/null 2>&1; then + echo "PASS: $tool found" + else + echo "WARN: $tool not found (may still be loading via Zinit turbo)" + MISSING+=("$tool") + fi + done + # Fail if more than half the tools are missing — something went wrong. + if [ "${#MISSING[@]}" -ge 3 ]; then + echo "Error: Too many tools missing: ${MISSING[*]}" + exit 1 fi # ----------------------------------------------------------------------------- @@ -88,25 +105,22 @@ jobs: strategy: matrix: distro: [archlinux:latest, fedora:latest] - + steps: - uses: actions/checkout@v4 - + - name: Test in Docker run: | docker run --rm -v ${{ github.workspace }}:/workspace -w /workspace ${{ matrix.distro }} /bin/bash -c " - # Set colors for better logging GREEN='\033[0;32m' NC='\033[0m' - + echo -e \"\${GREEN}>>> 1. SETUP: Installing dependencies for ${{ matrix.distro }}...\${NC}\" - + # --- ARCH LINUX --- if [ -f /etc/arch-release ]; then pacman -Sy --noconfirm archlinux-keyring - # Ensure wget is installed to handle the file:// download pacman -Syu --noconfirm git curl wget unzip sudo which base-devel ca-certificates - useradd -m -s /bin/bash tester echo 'tester ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers fi @@ -115,50 +129,54 @@ jobs: if [ -f /etc/fedora-release ]; then dnf upgrade -y --refresh dnf install -y git curl wget unzip sudo util-linux-user which findutils dnf-plugins-core ca-certificates - - # Pre-install Eza dnf install -y eza || (dnf copr enable -y piegames/eza && dnf install -y eza) - useradd -m -s /bin/bash tester echo 'tester ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers fi echo -e \"\${GREEN}>>> 2. PREPARE: Injecting local file path...\${NC}\" - - # 1. Copy the repository files to a temp location so we can modify them freely + cp /workspace/install.sh /tmp/install.sh cp /workspace/.zshrc /tmp/.zshrc - - # 2. USE SED TO REPLACE THE URL - # This changes the URL from 'https://...' to 'file:///tmp/.zshrc' - # Now wget will 'download' the local file instead of going to the internet. sed -i 's|^ZSHRC_URL=.*|ZSHRC_URL=\"file:///tmp/.zshrc\"|' /tmp/install.sh - - # 3. Permissions chmod +x /tmp/install.sh chmod 644 /tmp/.zshrc chown -R tester:tester /tmp echo -e \"\${GREEN}>>> 3. TEST: Running installer as user tester...\${NC}\" - - # Run the modified script in /tmp + su tester -c 'export CI_ENV=true && yes | /tmp/install.sh' - + echo -e \"\${GREEN}>>> 4. VERIFY: Checking results...\${NC}\" - + if [ -f /home/tester/.zshrc ]; then echo 'SUCCESS: .zshrc created' else echo 'FAILURE: .zshrc missing' exit 1 fi - - # Verify Zinit bootstrap - su tester -c 'zsh -ic exit' || true + + su tester -c 'zsh -ic exit' 2>&1 || echo 'Note: zsh bootstrap exited non-zero' + if [ -d /home/tester/.local/share/zinit ]; then - echo 'SUCCESS: Zinit installed' + echo 'SUCCESS: Zinit installed' else - echo 'FAILURE: Zinit missing' - exit 1 + echo 'FAILURE: Zinit missing' + exit 1 + fi + + echo -e \"\${GREEN}>>> 5. VERIFY: Checking tool availability...\${NC}\" + MISSING=0 + for tool in eza starship; do + if su tester -c \"zsh -ic 'command -v $tool'\" > /dev/null 2>&1; then + echo \"SUCCESS: \$tool found\" + else + echo \"WARN: \$tool not found\" + MISSING=\$((MISSING + 1)) + fi + done + if [ \"\$MISSING\" -ge 2 ]; then + echo 'FAILURE: Too many tools missing' + exit 1 fi " \ No newline at end of file From 07909e0efa9a5e90034d219a2c2bcb31225b398b Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:45:13 +0200 Subject: [PATCH 11/12] fix: arch and fedora ci failures --- .github/workflows/ci.yml | 53 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2391421..6380798 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,6 @@ on: jobs: # ----------------------------------------------------------------------------- # JOB 1: STATIC ANALYSIS (LINTING) - # CI and local test use identical rules without duplicating the ignore list. # ----------------------------------------------------------------------------- lint: runs-on: ubuntu-latest @@ -65,10 +64,9 @@ jobs: exit 1 fi - # Run zsh once to trigger the Zinit git clone inside .zshrc. - name: Bootstrap Zinit (Initialize Zsh) run: | - zsh -ic "exit" 2>&1 || echo "Note: zsh bootstrap exited non-zero (likely async plugin load — see output above)" + TERM=xterm-256color zsh -ic "exit" 2>&1 || echo "Note: zsh bootstrap exited non-zero (likely async plugin load — see output above)" - name: Verify Zinit Installed run: | @@ -77,21 +75,28 @@ jobs: exit 1 fi - - - name: Verify Core Tools Installed + - name: Verify Core Tools Installed (Zinit store) run: | + ZINIT_PLUGINS="${HOME}/.local/share/zinit/plugins" MISSING=() - for tool in eza bat fzf zoxide starship; do - if zsh -ic "command -v $tool" > /dev/null 2>&1; then - echo "PASS: $tool found" + declare -A TOOL_DIRS=( + [eza]="eza-community---eza" + [bat]="sharkdp---bat" + [fzf]="junegunn---fzf" + [zoxide]="ajeetdsouza---zoxide" + [starship]="starship---starship" + ) + for tool in "${!TOOL_DIRS[@]}"; do + dir="$ZINIT_PLUGINS/${TOOL_DIRS[$tool]}" + if find "$dir" -maxdepth 1 -name "$tool" -type f 2>/dev/null | grep -q .; then + echo "PASS: $tool found in Zinit store" else - echo "WARN: $tool not found (may still be loading via Zinit turbo)" + echo "WARN: $tool not found in Zinit store (${dir})" MISSING+=("$tool") fi done - # Fail if more than half the tools are missing — something went wrong. if [ "${#MISSING[@]}" -ge 3 ]; then - echo "Error: Too many tools missing: ${MISSING[*]}" + echo "Error: Too many tools missing from Zinit store: ${MISSING[*]}" exit 1 fi @@ -120,7 +125,8 @@ jobs: # --- ARCH LINUX --- if [ -f /etc/arch-release ]; then pacman -Sy --noconfirm archlinux-keyring - pacman -Syu --noconfirm git curl wget unzip sudo which base-devel ca-certificates + # 'file' required by Zinit ziextract for archive type detection + pacman -Syu --noconfirm git curl wget unzip sudo which base-devel ca-certificates file useradd -m -s /bin/bash tester echo 'tester ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers fi @@ -128,7 +134,9 @@ jobs: # --- FEDORA --- if [ -f /etc/fedora-release ]; then dnf upgrade -y --refresh - dnf install -y git curl wget unzip sudo util-linux-user which findutils dnf-plugins-core ca-certificates + # 'file' required by Zinit ziextract — without it every gh-r download + # (bat, fzf, fd, rg, zoxide) fails mid-extract with 'command not found: file' + dnf install -y git curl wget unzip sudo util-linux-user which findutils dnf-plugins-core ca-certificates file dnf install -y eza || (dnf copr enable -y piegames/eza && dnf install -y eza) useradd -m -s /bin/bash tester echo 'tester ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers @@ -156,7 +164,7 @@ jobs: exit 1 fi - su tester -c 'zsh -ic exit' 2>&1 || echo 'Note: zsh bootstrap exited non-zero' + su tester -c 'TERM=xterm-256color zsh -ic exit' 2>&1 || echo 'Note: zsh bootstrap exited non-zero' if [ -d /home/tester/.local/share/zinit ]; then echo 'SUCCESS: Zinit installed' @@ -165,18 +173,21 @@ jobs: exit 1 fi - echo -e \"\${GREEN}>>> 5. VERIFY: Checking tool availability...\${NC}\" + echo -e \"\${GREEN}>>> 5. VERIFY: Checking Zinit plugin store...\${NC}\" + ZINIT_PLUGINS=\"/home/tester/.local/share/zinit/plugins\" MISSING=0 - for tool in eza starship; do - if su tester -c \"zsh -ic 'command -v $tool'\" > /dev/null 2>&1; then - echo \"SUCCESS: \$tool found\" + for spec in \"eza-community---eza:eza\" \"starship---starship:starship\" \"sharkdp---bat:bat\" \"junegunn---fzf:fzf\"; do + dir=\"\${spec%%:*}\" + bin=\"\${spec##*:}\" + if find \"\$ZINIT_PLUGINS/\$dir\" -maxdepth 1 -name \"\$bin\" -type f 2>/dev/null | grep -q .; then + echo \"SUCCESS: \$bin found in Zinit store\" else - echo \"WARN: \$tool not found\" + echo \"WARN: \$bin not found (\$ZINIT_PLUGINS/\$dir)\" MISSING=\$((MISSING + 1)) fi done - if [ \"\$MISSING\" -ge 2 ]; then - echo 'FAILURE: Too many tools missing' + if [ \"\$MISSING\" -ge 3 ]; then + echo 'FAILURE: Too many tools missing from Zinit store' exit 1 fi " \ No newline at end of file From bef8bceb5d7070b84b11635e9884f044c99acfaa Mon Sep 17 00:00:00 2001 From: 0xdilshan <257371012+0xdilshan@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:53:56 +0200 Subject: [PATCH 12/12] ci: macos ci fixes --- .github/workflows/ci.yml | 34 ++++++++++++++++------------------ install.sh | 2 +- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6380798..df49390 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,28 +75,26 @@ jobs: exit 1 fi - - name: Verify Core Tools Installed (Zinit store) - run: | ZINIT_PLUGINS="${HOME}/.local/share/zinit/plugins" - MISSING=() - declare -A TOOL_DIRS=( - [eza]="eza-community---eza" - [bat]="sharkdp---bat" - [fzf]="junegunn---fzf" - [zoxide]="ajeetdsouza---zoxide" - [starship]="starship---starship" - ) - for tool in "${!TOOL_DIRS[@]}"; do - dir="$ZINIT_PLUGINS/${TOOL_DIRS[$tool]}" - if find "$dir" -maxdepth 1 -name "$tool" -type f 2>/dev/null | grep -q .; then - echo "PASS: $tool found in Zinit store" + MISSING=0 + # "dir:binary" pairs — no associative arrays, compatible with bash 3 (macOS) + for spec in \ + "eza-community---eza:eza" \ + "sharkdp---bat:bat" \ + "junegunn---fzf:fzf" \ + "ajeetdsouza---zoxide:zoxide" \ + "starship---starship:starship"; do + dir="${spec%%:*}" + bin="${spec##*:}" + if find "$ZINIT_PLUGINS/$dir" -maxdepth 1 -name "$bin" -type f 2>/dev/null | grep -q .; then + echo "PASS: $bin found in Zinit store" else - echo "WARN: $tool not found in Zinit store (${dir})" - MISSING+=("$tool") + echo "WARN: $bin not found ($ZINIT_PLUGINS/$dir)" + MISSING=$((MISSING + 1)) fi done - if [ "${#MISSING[@]}" -ge 3 ]; then - echo "Error: Too many tools missing from Zinit store: ${MISSING[*]}" + if [ "$MISSING" -ge 3 ]; then + echo "Error: Too many tools missing from Zinit store" exit 1 fi diff --git a/install.sh b/install.sh index 9fca057..75cb363 100644 --- a/install.sh +++ b/install.sh @@ -11,7 +11,7 @@ # Z-SHIFT: High-Performance Zsh + Starship + Zinit installation script # ============================================================================= -# Removed bare 'set -e' in favour of explicit checks on critical commands — +# Removed bare 'set -e' in favour of explicit checks on critical commands # 'set -e' interacts poorly with subshells and conditional logic. set -uo pipefail