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