From d376d6e3e2f44bc96467ed74a741ff67308f2072 Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Fri, 19 Jun 2026 21:36:24 +0530 Subject: [PATCH] decoupled bootstrapper added uninstaller --- b.sh | 43 ++++++++++++++++++ bootstrap.sh | 123 +++++++++++++++++++++++++++++++++------------------ readme.md | 3 +- routes.sh | 64 +++++++++++++++++++-------- 4 files changed, 170 insertions(+), 63 deletions(-) create mode 100755 b.sh diff --git a/b.sh b/b.sh new file mode 100755 index 0000000..e979e77 --- /dev/null +++ b/b.sh @@ -0,0 +1,43 @@ +# >>> bootstrap-cli b function >>> +# Shortcut for downloading and running bootstrap/install scripts +b() { + if [ -z "$1" ]; then + echo "Usage: b [args...]" >&2 + return 1 + fi + + local routes_dir="$HOME/.config/bootstrap" + local b_file="$routes_dir/b.sh" + local routes_file="$routes_dir/routes.sh" + local last_update_file="$routes_dir/.last_b_update" + + # 1. Check for b.sh updates (once every 24 hours) + local current_time + current_time=$(date +%s 2>/dev/null || date +%s) + local last_update=0 + [ -f "$last_update_file" ] && last_update=$(cat "$last_update_file" 2>/dev/null || echo 0) + + if [ $((current_time - last_update)) -gt 86400 ]; then + local b_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/b.sh" + if curl -fsSL "$b_url" -o "$b_file" 2>/dev/null; then + echo "$current_time" > "$last_update_file" + . "$b_file" # Load the updated function in current shell context + fi + fi + + # 2. Update routes.sh on every run + local routes_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/routes.sh" + mkdir -p "$routes_dir" + if curl -fsSL "$routes_url" -o "$routes_file" 2>/dev/null || wget -qO "$routes_file" "$routes_url" 2>/dev/null; then + : + fi + + if [ ! -f "$routes_file" ]; then + echo "Error: Routes file not found at $routes_file and could not be downloaded." >&2 + return 1 + fi + + # 3. Execute the routes file + bash "$routes_file" "$@" +} +# <<< bootstrap-cli b function <<< diff --git a/bootstrap.sh b/bootstrap.sh index 34a877f..8a0ff21 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -8,64 +8,99 @@ if [ -z "${BASH_VERSION:-}" ]; then exit 1 fi -# Add a shortcut function 'b' to user's shell configurations if not already present -add_b_alias() { +# Detect if the script is sourced +is_sourced=false +if [ -n "${ZSH_VERSION:-}" ]; then + case $ZSH_EVAL_CONTEXT in + *file*) is_sourced=true ;; + esac +elif [ -n "${BASH_VERSION:-}" ]; then + if [ "${BASH_SOURCE[0]}" != "$0" ]; then + is_sourced=true + fi +fi + +# Install/update the bootstrap loader and download b.sh & routes.sh +install_bootstrap() { local target_files=() [ -f "$HOME/.bashrc" ] && target_files+=("$HOME/.bashrc") [ -f "$HOME/.zshrc" ] && target_files+=("$HOME/.zshrc") - for config_file in "${target_files[@]}"; do - # 1. Clean up old unmarkered function if it exists - if grep -q "Shortcut for downloading bootstrap/install scripts" "$config_file" 2>/dev/null; then - sed -i '/# Shortcut for downloading bootstrap\/install scripts/,/^}/d' "$config_file" - fi + local routes_dir="$HOME/.config/bootstrap" + mkdir -p "$routes_dir" - # 2. Clean up old markered function if it exists + # Download b.sh and routes.sh from the repository, with fallback to local files if running inside the repo + echo "Downloading bootstrap scripts..." + local b_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/b.sh" + local routes_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/routes.sh" + + local script_dir + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + + if [ -f "$script_dir/b.sh" ] && [ -f "$script_dir/routes.sh" ]; then + echo "Using local files from repository..." + cp "$script_dir/b.sh" "$routes_dir/b.sh" + cp "$script_dir/routes.sh" "$routes_dir/routes.sh" + else + if command -v curl >/dev/null 2>&1; then + curl -fsSL "$b_url" -o "$routes_dir/b.sh" + curl -fsSL "$routes_url" -o "$routes_dir/routes.sh" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$routes_dir/b.sh" "$b_url" + wget -qO "$routes_dir/routes.sh" "$routes_url" + else + echo "Error: Neither curl nor wget is installed." >&2 + exit 1 + fi + fi + + # Set up shell configuration files + for config_file in "${target_files[@]}"; do + # 1. Clean up old embedded function block if it exists (from previous setup) if grep -q "# >>> bootstrap-cli b function >>>" "$config_file" 2>/dev/null; then sed -i '/# >>> bootstrap-cli b function >>>/,/# <<< bootstrap-cli b function <<>> bootstrap-cli setup >>>" "$config_file" 2>/dev/null; then + sed -i '/# >>> bootstrap-cli setup >>>/,/# <<< bootstrap-cli setup <<> "$config_file" -# >>> bootstrap-cli b function >>> -# Shortcut for downloading and running bootstrap/install scripts -b() { - if [ -z "$1" ]; then - echo "Usage: b [args...]" >&2 - return 1 - fi - - local routes_dir="$HOME/.config/bootstrap" - local routes_file="$routes_dir/routes.sh" - local routes_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/routes.sh" - - mkdir -p "$routes_dir" - - # Attempt to update the routes.sh file - if command -v curl >/dev/null 2>&1; then - curl -fsSL "$routes_url" -o "$routes_file" 2>/dev/null - elif command -v wget >/dev/null 2>&1; then - wget -qO "$routes_file" "$routes_url" 2>/dev/null - fi - - if [ ! -f "$routes_file" ]; then - echo "Error: Routes file not found at $routes_file and could not be downloaded." >&2 - return 1 - fi - - bash "$routes_file" "$@" -} -# <<< bootstrap-cli b function <<< +# >>> bootstrap-cli setup >>> +export BOOTSTRAP_DIR="$HOME/.config/bootstrap" +[ -f "$BOOTSTRAP_DIR/b.sh" ] && . "$BOOTSTRAP_DIR/b.sh" +# <<< bootstrap-cli setup <<< EOF done } -add_b_alias +install_bootstrap -# Source ~/.bashrc to make changes immediately available -if [ -f "$HOME/.bashrc" ]; then - echo "Sourcing ~/.bashrc..." - . "$HOME/.bashrc" +# Load the b function immediately in the current subshell +if [ -f "$HOME/.config/bootstrap/b.sh" ]; then + . "$HOME/.config/bootstrap/b.sh" +fi + +# Handle sourcing the shell configuration file +if [ "$is_sourced" = true ]; then + if [ -n "${ZSH_VERSION:-}" ] && [ -f "$HOME/.zshrc" ]; then + echo "Sourcing ~/.zshrc..." + . "$HOME/.zshrc" + elif [ -n "${BASH_VERSION:-}" ] && [ -f "$HOME/.bashrc" ]; then + echo "Sourcing ~/.bashrc..." + . "$HOME/.bashrc" + fi +else + echo + echo "Bootstrap CLI installed successfully!" + echo "To start using the 'b' command in this terminal session, run:" + if [ -n "${ZSH_VERSION:-}" ] || [ -f "$HOME/.zshrc" ]; then + echo " source ~/.zshrc" + else + echo " source ~/.bashrc" + fi fi diff --git a/readme.md b/readme.md index 283068c..7a45f8f 100644 --- a/readme.md +++ b/readme.md @@ -21,11 +21,12 @@ To bootstrap a new machine and set up the `b` command tool, run the following: curl -fsSL https://adityagupta.dev/b | bash ``` -Once bootstrapped, you can run any installer script using the `b` command followed by its shortcut name: +Once bootstrapped, you can run any installer script using the `b` command followed by its shortcut name. You can also chain multiple installations by separating their names with a comma: ```bash b nvim b yazi +b nvim,yazi ``` ## What the Neovim Installer Does diff --git a/routes.sh b/routes.sh index 9884ec7..dcd6e26 100755 --- a/routes.sh +++ b/routes.sh @@ -8,25 +8,53 @@ if [ -z "${BASH_VERSION:-}" ]; then exit 1 fi -SCRIPT_NAME="${1:-}" -if [ -z "$SCRIPT_NAME" ]; then - echo "Usage: b [args...]" >&2 +SCRIPT_NAMES="${1:-}" +if [ -z "$SCRIPT_NAMES" ]; then + echo "Usage: b [args...]" >&2 exit 1 fi shift -case "$SCRIPT_NAME" in - nvim) - echo "Launching Neovim installer..." - curl -fsSL "https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/installers/install_nvim.sh" | bash -s -- "$@" - ;; - yazi) - echo "Launching Yazi installer..." - curl -fsSL "https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/installers/install_yazi.sh" | bash -s -- "$@" - ;; - *) - echo "Error: Unknown script '$SCRIPT_NAME'." >&2 - echo "Available scripts: nvim, yazi" >&2 - exit 1 - ;; -esac +# Split comma-separated script names +IFS=',' read -ra SCRIPTS <<< "$SCRIPT_NAMES" + +for script in "${SCRIPTS[@]}"; do + case "$script" in + nvim) + echo "Launching Neovim installer..." + curl -fsSL "https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/installers/install_nvim.sh" | bash -s -- "$@" + ;; + yazi) + echo "Launching Yazi installer..." + curl -fsSL "https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/installers/install_yazi.sh" | bash -s -- "$@" + ;; + bye) + echo "Removing bootstrap CLI completely..." + + target_files=() + [ -f "$HOME/.bashrc" ] && target_files+=("$HOME/.bashrc") + [ -f "$HOME/.zshrc" ] && target_files+=("$HOME/.zshrc") + + for config_file in "${target_files[@]}"; do + # Remove loader setup + if grep -q "# >>> bootstrap-cli setup >>>" "$config_file" 2>/dev/null; then + sed -i '/# >>> bootstrap-cli setup >>>/,/# <<< bootstrap-cli setup <<>> bootstrap-cli b function >>>" "$config_file" 2>/dev/null; then + sed -i '/# >>> bootstrap-cli b function >>>/,/# <<< bootstrap-cli b function <<&2 + echo "Available scripts: nvim, yazi, bye" >&2 + exit 1 + ;; + esac +done