From f9a25ff37e7a15a84a95e5b3cac0438c8e594088 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Sun, 28 Jun 2026 08:17:30 +0530 Subject: [PATCH] refactor(Installers): Update all installers to use library helpers and Update add_installer skill --- .agents/skills/add_installer/SKILL.md | 75 +++++++++++++-------------- installers/install_docker.sh | 3 +- installers/install_node.sh | 1 + installers/install_nvim.sh | 11 ++++ installers/install_yay.sh | 1 + installers/install_yazi.sh | 1 + installers/install_zoxide.sh | 1 + 7 files changed, 54 insertions(+), 39 deletions(-) diff --git a/.agents/skills/add_installer/SKILL.md b/.agents/skills/add_installer/SKILL.md index 3a65d7f..98eb5ee 100644 --- a/.agents/skills/add_installer/SKILL.md +++ b/.agents/skills/add_installer/SKILL.md @@ -44,25 +44,27 @@ If the user provides an official install or curl script in the prompt: - Remove redundant parts like macOS and Windows compatibility. - Strip unnecessary shell boilerplate, self-update logic, and other bloat. - Implement only the essential Linux installation logic inside the `install_` function. +- Do NOT add checks for `curl` or attempt to install it. Assume `curl` is installed and available. ### Step 2: Add metadata comments to the top of your installer script -At the top of your new installer script, right below `#!/usr/bin/env bash`, add the following three metadata headers: +At the top of your new installer script, right below `#!/usr/bin/env bash`, add the following metadata headers: ```bash # Tool: # DisplayName: # Description: +# Strategy: (binary | managed | system) ``` The central router `lib/routes.sh` and autocomplete function in `b.sh` will dynamically parse this metadata from all `install_*.sh` scripts to register the installer and keys automatically! No manual edits to `lib/routes.sh` or `b.sh` are required. ### Step 3: Implement Rollback Tracking (Crucial) -To ensure the user can seamlessly use `b rb `, all manual modifications must be tracked: -- When extracting binaries to `~/.local/bin/`, use `track_file "${BOOTSTRAP_BIN:-$HOME/.local/share/bootstrap/bin}/binary"`. -- When creating directories like `~/.config/tool/`, use `track_dir "$HOME/.config/tool"`. -- When running manual apt/dnf/npm commands, log their inverses: `add_rollback_cmd "sudo npm uninstall -g package"`. -Note: `pkg_install`, `write_env_snippet`, and `write_alias_snippet` will automatically track themselves. +To ensure the user can seamlessly use `b rb ` to uninstall or rollback a tool: +- When extracting binaries, copy them to `$BOOTSTRAP_BIN` and use `track_file "$BOOTSTRAP_BIN/binary"`. Never use `sudo` or write to system folders like `/usr/local/bin`. +- When creating directories (e.g., in `$BOOTSTRAP_OPT` or `$BOOTSTRAP_RUNTIMES`), use `track_dir` to register them. +- When running manual commands (like compiling or registry changes), log their inverses: `add_rollback_cmd "rm -rf ..."` or equivalent cleanup. +Note: `write_env_snippet` and `write_alias_snippet` will automatically track themselves. ### Step 4: Verify (optional) @@ -75,22 +77,15 @@ Verify that the installer works and appears in the help output: ## Installer Script Template -Every installer follows this exact boilerplate structure. Copy this and fill in the tool-specific logic: +Every installer follows this exact structure. Copy this and fill in the tool-specific logic (notice there are no standalone execution guards or curl checks): ```bash #!/usr/bin/env bash # Tool: # DisplayName: # Description: Short description of what it installs +# Strategy: (binary | managed | system) # -# Installer Script -# - -# Prevent standalone execution -if [ -z "${_LIB_COMMON_SOURCED:-}" ]; then - echo "Error: This script must be run through the 'b' CLI." >&2 - exit 1 -fi set -euo pipefail @@ -110,14 +105,14 @@ install_() { fi # --- Tool-specific installation logic goes here --- - # Use pkg_install for distro packages (it automatically handles rollback hooks!): + # Use pkg_install for distro packages: # pkg_install "arch:|debian:|fedora:" # Or manual downloads (always use download_file for resumability!): # local url="https://..." # download_file "$url" "$TMP_DIR/binary" - # cp "$TMP_DIR/binary" "${BOOTSTRAP_BIN:-$HOME/.local/share/bootstrap/bin}/binary" - # track_file "${BOOTSTRAP_BIN:-$HOME/.local/share/bootstrap/bin}/binary" # Important for rollback! + # cp "$TMP_DIR/binary" "$BOOTSTRAP_BIN/binary" + # track_file "$BOOTSTRAP_BIN/binary" # Important for rollback! } # ─── Shell Configuration (if needed) ───────────────────────────────── @@ -159,7 +154,7 @@ These are pre-loaded by `bootstrap.sh` — no need to source them manually in in | `confirm "prompt"` | Interactive yes/no prompt, returns 0 for yes | | `has_command ` | Check if a command exists (returns 0/1) | | `make_temp_dir` | Create and echo a temp directory path | -| `download_file ` | Resumable and cached download of `` to ``. Uses `~/.local/state/bootstrap/cache/`. | +| `download_file ` | Resumable and cached download of `` to ``. Uses `$BOOTSTRAP_CACHE_DIR/downloads/`. | ### From `lib/platform.sh` @@ -167,7 +162,7 @@ These are pre-loaded by `bootstrap.sh` — no need to source them manually in in |---|---| | `detect_distro` | Echoes `arch`, `debian`, `fedora`, or `unknown` | | `detect_arch` | Echoes `x86_64` or `arm64` | -| `pkg_install ...` | Install packages. Supports distro mapping: `"arch:pkg_a\|debian:pkg_d\|fedora:pkg_f"`. Automatically integrates with rollback context and handles package reference counting. | +| `pkg_install ...` | Install packages. Supports distro mapping: `"arch:pkg_a\|debian:pkg_d\|fedora:pkg_f"`. | | `pkg_check ...` | Returns 0 if packages are installed. Supports identical mapping syntax. | ### From `lib/rollback.sh` @@ -176,7 +171,7 @@ These are pre-loaded by `bootstrap.sh` — no need to source them manually in in |---|---| | `track_file ` | Registers a file for deletion during `b rb` rollback. | | `track_dir ` | Registers a directory for recursive deletion during rollback. | -| `add_rollback_cmd ` | Adds a raw bash command to the uninstall manifest (e.g., `add_rollback_cmd "sudo npm uninstall -g "`). | +| `add_rollback_cmd ` | Adds a raw bash command to the uninstall manifest (e.g., `add_rollback_cmd "rm -rf "`). | ### From `lib/shell_config.sh` @@ -185,6 +180,14 @@ These are pre-loaded by `bootstrap.sh` — no need to source them manually in in | `write_env_snippet ` | Creates an isolated `env.d/` shell drop-in snippet and registers it for rollback. | | `write_alias_snippet ` | Creates an isolated `aliases.d/` shell drop-in snippet and registers it for rollback. | +### From `lib/github.sh` + +| Function | Description | +|---|---| +| `github_get_latest_release ` | Fetches the latest release tag (e.g., `v1.0.0`) from the GitHub API. | +| `github_get_download_url ` | Finds an asset matching a regex in the specified release and prints its URL. | +| `github_download_asset ` | Resolves the URL for the matching asset and downloads it directly to ``. | + --- ## Common Patterns @@ -207,10 +210,7 @@ pkg_install "arch:neovim|debian:nvim|fedora:neovim" "git" ```bash local latest_tag="" - latest_tag=$(curl -sL https://api.github.com/repos///releases/latest \ - | grep '"tag_name":' | head -n1 \ - | sed -E 's/.*"tag_name": "([^"]+)".*/\1/' || true) -fi +latest_tag=$(github_get_latest_release "owner/repo") if [ -z "$latest_tag" ]; then latest_tag="v1.0.0" # fallback @@ -218,19 +218,18 @@ if [ -z "$latest_tag" ]; then fi ``` -### Resumable Download and Extraction +### GitHub Download and Extraction ```bash -local url="https://github.com/owner/repo/releases/download/${version}/archive.tar.gz" -local dest="$TMP_DIR/archive.tar.gz" +local archive="$TMP_DIR/archive.tar.gz" -# Resumable, cached download -download_file "$url" "$dest" +# Download the asset matching a regex pattern for the specific release tag +github_download_asset "owner/repo" "$latest_tag" "app-.*-linux-x86_64\.tar\.gz" "$archive" # Extract and install -tar -xzf "$dest" -C "$TMP_DIR" -sudo cp "$TMP_DIR/binary" /usr/local/bin/binary -track_file "/usr/local/bin/binary" +tar -xzf "$archive" -C "$TMP_DIR" +cp "$TMP_DIR/binary" "$BOOTSTRAP_BIN/binary" +track_file "$BOOTSTRAP_BIN/binary" ``` --- @@ -239,10 +238,10 @@ track_file "/usr/local/bin/binary" 1. **File naming**: Always `install_.sh` in the `installers/` directory. 2. **Confirmation prompts**: Always ask before installing. Check if already installed first. -3. **Rollback Tracking**: NEVER omit rollback hooks. If you move a file to `~/.local/bin/`, you MUST call `track_file`. If you run `makepkg`, you MUST call `add_rollback_cmd` for `pacman -R`. +3. **Rollback Tracking**: NEVER omit rollback hooks. If you move a file to `$BOOTSTRAP_BIN`, you MUST call `track_file`. 4. **Shell Drop-ins**: Always use `write_env_snippet` or `write_alias_snippet` instead of manually injecting code directly into `~/.bashrc`. -5. **No hardcoded paths**: Use `$HOME`, library functions, and `detect_*` helpers. -6. **Error handling**: Use `set -euo pipefail` after the guard block. -7. **CLI Enforcement Guard**: Always copy the standalone execution guard block verbatim to the top of your installer script to prevent direct execution. -8. **Clean Official Scripts**: When implementing official curl/install scripts provided in the prompt, strip them of bloat, macOS/Windows support, and redundant shell setups before writing the script. +5. **No hardcoded paths**: Use `$HOME`, `$BOOTSTRAP_BIN`, `$BOOTSTRAP_OPT`, `$BOOTSTRAP_RUNTIMES`, library functions, and `detect_*` helpers. +6. **Error handling**: Use `set -euo pipefail`. +7. **No Standalone Execution Guards**: Do NOT add guards to prevent running the installer directly; simplify code paths to focus on clean runs. +8. **Clean Official Scripts**: When implementing official curl/install scripts, strip them of bloat, macOS/Windows support, and redundant shell setups. Do not check or install `curl`. 9. **No manual shell re-sourcing**: Do NOT manually run `source ~/.bashrc` or print instructions asking the user to run it. Sourcing of the shell configuration is handled automatically by the central router and CLI at the end of the installation. diff --git a/installers/install_docker.sh b/installers/install_docker.sh index 2b0e382..b20a5fb 100644 --- a/installers/install_docker.sh +++ b/installers/install_docker.sh @@ -24,8 +24,9 @@ install_docker() { fi fi - # Use pkg_install for distro packages (it automatically handles rollback hooks for the packages!) + # Use pkg_install for distro packages and explicitly register them for reference-counted rollback pkg_install "arch:docker|debian:docker.io|fedora:docker" + registry_add_sys_deps "docker" "arch:docker|debian:docker.io|fedora:docker" # Ensure docker group exists (some distros might not create it immediately) if ! getent group docker >/dev/null 2>&1; then diff --git a/installers/install_node.sh b/installers/install_node.sh index 203b815..3aafe2a 100644 --- a/installers/install_node.sh +++ b/installers/install_node.sh @@ -24,6 +24,7 @@ install_nvm() { if ! has_command tar; then log_info "tar not found. Installing tar..." pkg_install tar + registry_add_sys_deps "node" "tar" fi # Try to fetch the latest version of NVM from GitHub API diff --git a/installers/install_nvim.sh b/installers/install_nvim.sh index 8b2c66e..d2fbe9a 100644 --- a/installers/install_nvim.sh +++ b/installers/install_nvim.sh @@ -40,6 +40,17 @@ install_packages() { "debian:python3-venv" \ "fedora:gcc-c++" + registry_add_sys_deps "nvim" \ + git tar unzip ripgrep fzf nodejs npm xclip wl-clipboard \ + "arch:fd|debian:fd-find|fedora:fd-find" \ + "arch:cmake|debian:cmake|fedora:cmake" \ + "arch:make|debian:build-essential|fedora:make" \ + "arch:gcc|debian:build-essential|fedora:gcc" \ + "arch:python|debian:python3|fedora:python3" \ + "debian:python3-pip|fedora:python3-pip" \ + "debian:python3-venv" \ + "fedora:gcc-c++" + create_fd_symlink log_info "Installing tree-sitter-cli globally..." diff --git a/installers/install_yay.sh b/installers/install_yay.sh index 105f0b9..072dbf0 100755 --- a/installers/install_yay.sh +++ b/installers/install_yay.sh @@ -38,6 +38,7 @@ install_yay() { else log_info "Dependencies (git and base-devel) are already present. Skipping package installation." fi + registry_add_sys_deps "yay" "git" "base-devel" log_info "Cloning yay-bin repository..." local clone_dir diff --git a/installers/install_yazi.sh b/installers/install_yazi.sh index e2bf1f8..dd1d3cb 100755 --- a/installers/install_yazi.sh +++ b/installers/install_yazi.sh @@ -45,6 +45,7 @@ install_yazi() { if ! has_command unzip; then log_info "unzip not found. Installing unzip..." pkg_install unzip + registry_add_sys_deps "yazi" "unzip" fi local arch diff --git a/installers/install_zoxide.sh b/installers/install_zoxide.sh index 560687c..e8065aa 100755 --- a/installers/install_zoxide.sh +++ b/installers/install_zoxide.sh @@ -19,6 +19,7 @@ install_fzf() { log_info "fzf not found. Installing fzf..." pkg_install fzf + registry_add_sys_deps "zoxide" "fzf" } install_zoxide() {