feat: Added support for lazy loading plugins
This commit is contained in:
@@ -41,7 +41,7 @@ else
|
||||
BOOTSTRAP_SOURCE_DIR="$BOOTSTRAP_TMP_DIR"
|
||||
|
||||
_BASE_URL="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master"
|
||||
_LIBS=("lib/common.sh" "lib/rollback.sh" "lib/platform.sh" "lib/shell_config.sh")
|
||||
_LIBS=("lib/common.sh" "lib/rollback.sh" "lib/platform.sh" "lib/shell_config.sh" "lib/json.sh" "lib/plugins.sh")
|
||||
|
||||
_curl_args=()
|
||||
for _lib in "${_LIBS[@]}"; do
|
||||
@@ -82,6 +82,8 @@ install_bootstrap() {
|
||||
"lib/rollback.sh"
|
||||
"lib/platform.sh"
|
||||
"lib/shell_config.sh"
|
||||
"lib/json.sh"
|
||||
"lib/plugins.sh"
|
||||
"commands/help.sh"
|
||||
"commands/con.sh"
|
||||
"commands/uninstall.sh"
|
||||
|
||||
@@ -48,6 +48,13 @@ if version_lt "$local_ver" "$remote_ver" || [ "$force_update" = true ]; then
|
||||
if bash "$tmp_bootstrap"; then
|
||||
# Update the last update timestamp
|
||||
date +%s > "${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/.last_b_update" 2>/dev/null || true
|
||||
|
||||
# Update plugin cache
|
||||
if [ -f "${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/lib/plugins.sh" ]; then
|
||||
. "${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/lib/plugins.sh"
|
||||
update_plugin_cache
|
||||
fi
|
||||
|
||||
log_success "Bootstrap CLI successfully updated to version $remote_ver!"
|
||||
else
|
||||
log_error "Failed to execute bootstrap installer."
|
||||
|
||||
156
lib/plugins.sh
Normal file
156
lib/plugins.sh
Normal file
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -f "$BOOTSTRAP_DIR/lib/json.sh" ]; then
|
||||
. "$BOOTSTRAP_DIR/lib/json.sh"
|
||||
fi
|
||||
|
||||
# Parses a plugin manifest using the generic json parser and outputs bash array assignments
|
||||
parse_plugin_manifest() {
|
||||
# The generic parser outputs lines like:
|
||||
# plugins.myplugin.version="1.0"
|
||||
# plugins.myplugin.url="https://..."
|
||||
# We want to extract myplugin and the keys to build:
|
||||
# PLUGIN_VERSIONS["myplugin"]="1.0"
|
||||
# PLUGIN_URLS["myplugin"]="https://..."
|
||||
|
||||
parse_json | awk -F'=' '
|
||||
{
|
||||
path = $1
|
||||
val = $2
|
||||
|
||||
# Remove quotes around value for bash array assignment
|
||||
gsub(/^"|"$/, "", val)
|
||||
|
||||
# Match paths starting with "plugins."
|
||||
if (match(path, /^plugins\./)) {
|
||||
rest = substr(path, RLENGTH + 1)
|
||||
# Find the last dot to separate plugin name from the property key
|
||||
last_dot = 0
|
||||
for (i=length(rest); i>0; i--) {
|
||||
if (substr(rest, i, 1) == ".") {
|
||||
last_dot = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if (last_dot > 0) {
|
||||
plugin_name = substr(rest, 1, last_dot - 1)
|
||||
prop = substr(rest, last_dot + 1)
|
||||
if (prop == "version") {
|
||||
print "PLUGIN_VERSIONS[\"" plugin_name "\"]=\"" val "\""
|
||||
} else if (prop == "url") {
|
||||
print "PLUGIN_URLS[\"" plugin_name "\"]=\"" val "\""
|
||||
}
|
||||
}
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
||||
# Fetches manifests from sources and generates the cache
|
||||
update_plugin_cache() {
|
||||
local cache_file="$BOOTSTRAP_DIR/lib/plugin_cache.sh"
|
||||
local sources_file="$BOOTSTRAP_DIR/plugin_sources.txt"
|
||||
|
||||
mkdir -p "$BOOTSTRAP_DIR/lib"
|
||||
|
||||
# Initialize cache file
|
||||
cat << 'EOF' > "$cache_file"
|
||||
# Auto-generated plugin cache. Do not edit manually.
|
||||
declare -g -A PLUGIN_URLS
|
||||
declare -g -A PLUGIN_VERSIONS
|
||||
EOF
|
||||
|
||||
if [ -f "$sources_file" ]; then
|
||||
while IFS= read -r url || [ -n "$url" ]; do
|
||||
# Skip empty lines and comments
|
||||
[[ -z "$url" || "$url" == \#* ]] && continue
|
||||
|
||||
log_info "Fetching plugin manifest from $url..."
|
||||
local manifest_json
|
||||
if manifest_json=$(curl -fsSL "$url" 2>/dev/null); then
|
||||
echo "$manifest_json" | parse_plugin_manifest >> "$cache_file"
|
||||
else
|
||||
log_warn "Failed to fetch manifest from $url"
|
||||
fi
|
||||
done < "$sources_file"
|
||||
fi
|
||||
|
||||
# Clear downloaded scripts to force lazy re-download of the updated versions
|
||||
rm -rf "$BOOTSTRAP_DIR/plugins" 2>/dev/null || true
|
||||
|
||||
log_success "Plugin cache updated successfully."
|
||||
}
|
||||
|
||||
manage_plugin_sources() {
|
||||
local sources_file="$BOOTSTRAP_DIR/plugin_sources.txt"
|
||||
if [ ! -f "$sources_file" ]; then
|
||||
touch "$sources_file"
|
||||
echo "# Add raw URLs to JSON plugin manifests here, one per line." > "$sources_file"
|
||||
fi
|
||||
|
||||
local editor="${EDITOR:-}"
|
||||
if [ -z "$editor" ]; then
|
||||
if has_command nvim; then editor="nvim"
|
||||
elif has_command vim; then editor="vim"
|
||||
elif has_command nano; then editor="nano"
|
||||
else editor="vi"
|
||||
fi
|
||||
fi
|
||||
|
||||
$editor "$sources_file"
|
||||
|
||||
# Update cache after editing
|
||||
update_plugin_cache
|
||||
}
|
||||
|
||||
handle_plugin() {
|
||||
local subcmd="${1:-}"
|
||||
case "$subcmd" in
|
||||
sources)
|
||||
manage_plugin_sources
|
||||
;;
|
||||
update)
|
||||
update_plugin_cache
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown plugin command: $subcmd"
|
||||
log_info "Available commands: b plugin sources, b plugin update"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
run_plugin() {
|
||||
local plugin_name="$1"
|
||||
shift
|
||||
|
||||
local url="${PLUGIN_URLS[$plugin_name]:-}"
|
||||
if [ -z "$url" ]; then
|
||||
log_error "Plugin '$plugin_name' not found in cache."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local plugin_dir="$BOOTSTRAP_DIR/plugins"
|
||||
local local_plugin="$plugin_dir/${plugin_name}.sh"
|
||||
|
||||
if [ ! -f "$local_plugin" ]; then
|
||||
log_info "Downloading plugin '$plugin_name'..."
|
||||
mkdir -p "$plugin_dir"
|
||||
if ! curl -fsSL "$url" -o "$local_plugin"; then
|
||||
log_error "Failed to download plugin '$plugin_name' from $url"
|
||||
rm -f "$local_plugin"
|
||||
return 1
|
||||
fi
|
||||
chmod +x "$local_plugin"
|
||||
fi
|
||||
|
||||
log_info "Running plugin '$plugin_name'..."
|
||||
# Execute the plugin in a subshell, passing any additional arguments
|
||||
(
|
||||
# Plugins have access to common.sh already because it's sourced in the parent shell
|
||||
# Export BOOTSTRAP_DIR so plugins can use it
|
||||
export BOOTSTRAP_DIR
|
||||
bash "$local_plugin" "$@"
|
||||
)
|
||||
return $?
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ else
|
||||
INSTALLER_KEYS=()
|
||||
fi
|
||||
|
||||
# Source plugin system
|
||||
if [ -f "$BOOTSTRAP_DIR/lib/plugins.sh" ]; then
|
||||
. "$BOOTSTRAP_DIR/lib/plugins.sh"
|
||||
if [ -f "$BOOTSTRAP_DIR/lib/plugin_cache.sh" ]; then
|
||||
. "$BOOTSTRAP_DIR/lib/plugin_cache.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Helper function to run/edit installer scripts
|
||||
run_ware() {
|
||||
local tool="$1"
|
||||
@@ -191,6 +199,12 @@ for script in "${SCRIPTS[@]}"; do
|
||||
else
|
||||
# Handle non-installer commands
|
||||
case "$script" in
|
||||
plugin)
|
||||
shift # consume 'plugin' arg
|
||||
handle_plugin "$@"
|
||||
# Once handle_plugin completes, we should exit so it doesn't process more SCRIPTS
|
||||
exit $?
|
||||
;;
|
||||
all)
|
||||
if [ -f "$BOOTSTRAP_DIR/commands/help.sh" ]; then
|
||||
. "$BOOTSTRAP_DIR/commands/help.sh"
|
||||
@@ -263,9 +277,13 @@ for script in "${SCRIPTS[@]}"; do
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_error "Unknown command '$script'."
|
||||
log_info "Run 'b all' to list all available commands."
|
||||
exit 1
|
||||
if [[ -n "${PLUGIN_URLS[$script]:-}" ]]; then
|
||||
run_plugin "$script" "$@"
|
||||
else
|
||||
log_error "Unknown command '$script'."
|
||||
log_info "Run 'b all' to list all available commands."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user