refactor(Installers): Update all installers to use library helpers and Update add_installer skill

This commit is contained in:
2026-06-28 08:17:30 +05:30
parent 03e9c20e54
commit f9a25ff37e
7 changed files with 54 additions and 39 deletions

View File

@@ -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_<name>` 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: <name>
# DisplayName: <displayName>
# Description: <description>
# Strategy: <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 <name>`, 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 <name>` 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: <name>
# DisplayName: <ToolName>
# Description: Short description of what it installs
# Strategy: <strategy> (binary | managed | system)
#
# <ToolName> 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_<name>() {
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:<pkg_a>|debian:<pkg_d>|fedora:<pkg_f>"
# 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 <cmd>` | Check if a command exists (returns 0/1) |
| `make_temp_dir` | Create and echo a temp directory path |
| `download_file <url> <dest>` | Resumable and cached download of `<url>` to `<dest>`. Uses `~/.local/state/bootstrap/cache/`. |
| `download_file <url> <dest>` | Resumable and cached download of `<url>` to `<dest>`. 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 <pkg>...` | 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 <pkg>...` | Install packages. Supports distro mapping: `"arch:pkg_a\|debian:pkg_d\|fedora:pkg_f"`. |
| `pkg_check <pkg>...` | 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 <path>` | Registers a file for deletion during `b rb` rollback. |
| `track_dir <path>` | Registers a directory for recursive deletion during rollback. |
| `add_rollback_cmd <cmd>` | Adds a raw bash command to the uninstall manifest (e.g., `add_rollback_cmd "sudo npm uninstall -g <pkg>"`). |
| `add_rollback_cmd <cmd>` | Adds a raw bash command to the uninstall manifest (e.g., `add_rollback_cmd "rm -rf <path>"`). |
### 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 <name> <content>` | Creates an isolated `env.d/` shell drop-in snippet and registers it for rollback. |
| `write_alias_snippet <name> <content>` | Creates an isolated `aliases.d/` shell drop-in snippet and registers it for rollback. |
### From `lib/github.sh`
| Function | Description |
|---|---|
| `github_get_latest_release <repo>` | Fetches the latest release tag (e.g., `v1.0.0`) from the GitHub API. |
| `github_get_download_url <repo> <tag> <regex>` | Finds an asset matching a regex in the specified release and prints its URL. |
| `github_download_asset <repo> <tag> <regex> <dest>` | Resolves the URL for the matching asset and downloads it directly to `<dest>`. |
---
## 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/<owner>/<repo>/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_<name>.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.

View File

@@ -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

View File

@@ -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

View File

@@ -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..."

View File

@@ -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

View File

@@ -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

View File

@@ -19,6 +19,7 @@ install_fzf() {
log_info "fzf not found. Installing fzf..."
pkg_install fzf
registry_add_sys_deps "zoxide" "fzf"
}
install_zoxide() {