feat: Auto updator

This commit is contained in:
2026-06-20 13:24:52 +05:30
parent e29dfd27b5
commit bf1529b354
8 changed files with 200 additions and 13 deletions

View File

@@ -1 +1 @@
1.0.0
1.0.1

50
b.sh
View File

@@ -15,19 +15,45 @@ b() {
local last_update=0
[ -f "$last_update_file" ] && last_update=$(cat "$last_update_file" 2>/dev/null || echo 0)
# Update everything once every 24 hours, or if routes.sh is missing
if [ $((current_time - last_update)) -gt 86400 ] || [ ! -f "$routes_file" ]; then
local bootstrap_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master/bootstrap.sh"
local tmp_bootstrap
tmp_bootstrap="$(mktemp)"
# Download and run the bootstrap installer to update all CLI files
if curl -fsSL "$bootstrap_url" -o "$tmp_bootstrap" 2>/dev/null || wget -qO "$tmp_bootstrap" "$bootstrap_url" 2>/dev/null; then
if bash "$tmp_bootstrap"; then
echo "$current_time" > "$last_update_file"
# Version comparison helper (returns 0 if $1 < $2, 1 otherwise)
_version_lt() {
[ "$1" = "$2" ] && return 1
local IFS=.
local i ver1=($1) ver2=($2)
for ((i=${#ver1[@]}; i<3; i++)); do ver1[i]=0; done
for ((i=${#ver2[@]}; i<3; i++)); do ver2[i]=0; done
for ((i=0; i<3; i++)); do
if ((10#${ver1[i]} < 10#${ver2[i]})); then
return 0
elif ((10#${ver1[i]} > 10#${ver2[i]})); then
return 1
fi
done
return 1
}
# Auto-update check: once every 24 hours, or if routes.sh or VERSION is missing
if [ $((current_time - last_update)) -gt 86400 ] || [ ! -f "$routes_file" ] || [ ! -f "$routes_dir/VERSION" ]; then
# Update the timestamp immediately to prevent spamming on connection errors
echo "$current_time" > "$last_update_file"
local base_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master"
local local_ver="0.0.0"
[ -f "$routes_dir/VERSION" ] && local_ver=$(cat "$routes_dir/VERSION" 2>/dev/null | tr -d '[:space:]')
local remote_ver
if remote_ver=$(curl -fsSL "$base_url/VERSION" 2>/dev/null || wget -qO- "$base_url/VERSION" 2>/dev/null); then
remote_ver=$(echo "$remote_ver" | tr -d '[:space:]')
if [ -n "$remote_ver" ] && _version_lt "$local_ver" "$remote_ver"; then
echo "New version $remote_ver available (local: $local_ver). Auto-updating..." >&2
local tmp_bootstrap
tmp_bootstrap="$(mktemp)"
if curl -fsSL "$base_url/bootstrap.sh" -o "$tmp_bootstrap" 2>/dev/null || wget -qO "$tmp_bootstrap" "$base_url/bootstrap.sh" 2>/dev/null; then
bash "$tmp_bootstrap" >/dev/null 2>&1
fi
rm -f "$tmp_bootstrap"
fi
fi
rm -f "$tmp_bootstrap"
fi
if [ ! -f "$routes_file" ]; then
@@ -48,7 +74,7 @@ _b_completion() {
# If completing the first argument after 'b'
if [ "$COMP_CWORD" -eq 1 ]; then
opts="all con bye"
opts="all con bye up"
local routes_file="$HOME/.config/bootstrap/routes.sh"
if [ -f "$routes_file" ]; then

View File

@@ -88,6 +88,7 @@ install_bootstrap() {
# List of all files to download/copy
local files=(
"VERSION"
"b.sh"
"routes.sh"
"lib/common.sh"
@@ -96,6 +97,7 @@ install_bootstrap() {
"commands/help.sh"
"commands/con.sh"
"commands/uninstall.sh"
"commands/up.sh"
)
if [ -f "$_SCRIPT_DIR/b.sh" ] && [ -f "$_SCRIPT_DIR/routes.sh" ]; then
@@ -180,6 +182,17 @@ EOF
# Initialize the last update timestamp to prevent immediate update on first execution (Fix 2)
local last_update_file="$routes_dir/.last_b_update"
date +%s 2>/dev/null > "$last_update_file" || date +%s > "$last_update_file"
# Set up pre-commit hook if in a git repository locally
if [ -d "$_SCRIPT_DIR/.git" ]; then
log_info "Setting up git pre-commit hook..."
mkdir -p "$_SCRIPT_DIR/.git/hooks"
if [ -f "$_SCRIPT_DIR/scripts/pre-commit" ]; then
cp "$_SCRIPT_DIR/scripts/pre-commit" "$_SCRIPT_DIR/.git/hooks/pre-commit"
chmod +x "$_SCRIPT_DIR/.git/hooks/pre-commit"
log_success "Pre-commit hook installed to .git/hooks/pre-commit"
fi
fi
}
# Only execute installation if not sourced (Fix 3)

View File

@@ -5,6 +5,7 @@ echo "Available bootstrap commands:"
# Non-installers first (aligned to 6 chars width)
printf " %-6s - %s\n" "all" "List all available commands"
printf " %-6s - %s\n" "con" "Edit config (e.g. b con nvim)"
printf " %-6s - %s\n" "up" "Check for updates and update Bootstrap CLI"
printf " %-6s - %s\n" "bye" "Uninstall Bootstrap CLI helper"
# Installers second

82
commands/up.sh Normal file
View File

@@ -0,0 +1,82 @@
# Command: up
# Manually checks for updates and runs the updater if a newer version is found.
# Source libraries if needed
if [ -z "${_LIB_COMMON_SOURCED:-}" ]; then
_LIB_DIR="${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/lib"
. "$_LIB_DIR/common.sh"
fi
require_bash
log_info "Checking for updates..."
local_ver="0.0.0"
version_file="${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/VERSION"
if [ -f "$version_file" ]; then
local_ver=$(cat "$version_file" | tr -d '[:space:]')
fi
base_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master"
remote_ver=$(curl -fsSL "$base_url/VERSION" 2>/dev/null || wget -qO- "$base_url/VERSION" 2>/dev/null)
remote_ver=$(echo "$remote_ver" | tr -d '[:space:]')
if [ -z "$remote_ver" ]; then
log_error "Failed to fetch remote version. Please check your internet connection."
exit 1
fi
# Version comparison helper
version_lt() {
[ "$1" = "$2" ] && return 1
local IFS=.
local i ver1=($1) ver2=($2)
for ((i=${#ver1[@]}; i<3; i++)); do ver1[i]=0; done
for ((i=${#ver2[@]}; i<3; i++)); do ver2[i]=0; done
for ((i=0; i<3; i++)); do
if ((10#${ver1[i]} < 10#${ver2[i]})); then
return 0
elif ((10#${ver1[i]} > 10#${ver2[i]})); then
return 1
fi
done
return 1
}
log_info "Local version: $local_ver"
log_info "Remote version: $remote_ver"
force_update=false
if [ "${1:-}" = "--force" ] || [ "${1:-}" = "-f" ]; then
force_update=true
fi
if version_lt "$local_ver" "$remote_ver" || [ "$force_update" = true ]; then
if [ "$force_update" = true ]; then
log_info "Force updating..."
else
log_info "New version available! Updating..."
fi
tmp_bootstrap="$(mktemp)"
if curl -fsSL "$base_url/bootstrap.sh" -o "$tmp_bootstrap" || wget -qO "$tmp_bootstrap" "$base_url/bootstrap.sh"; then
# Run bootstrap.sh in foreground
if bash "$tmp_bootstrap"; then
# Update the last update timestamp
date +%s > "${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/.last_b_update" 2>/dev/null || true
log_success "Bootstrap CLI successfully updated to version $remote_ver!"
else
log_error "Failed to execute bootstrap installer."
rm -f "$tmp_bootstrap"
exit 1
fi
else
log_error "Failed to download update installer."
rm -f "$tmp_bootstrap"
exit 1
fi
rm -f "$tmp_bootstrap"
else
log_success "You are already on the latest version ($local_ver)."
log_info "To force reinstall, run: b up --force"
fi

View File

@@ -44,6 +44,13 @@ b con i3
It automatically fuzzy-finds the folder in case there is no exact match.
To check for updates and update the tool manually:
```bash
b up
# Or to force a reinstall of the CLI files:
b up --force
```
## Uninstallation
@@ -55,6 +62,13 @@ b bye
Then reload your shell configuration or run `unset -f b` to clear the function definition from your current terminal session.
## Development
If you are developing this tool locally:
1. Clone the repository.
2. Run `./bootstrap.sh` to install the CLI from your local copy. This will also automatically install a Git pre-commit hook (`scripts/pre-commit`) that auto-increments the patch version in the `VERSION` file on each commit.
## Philosophy
These scripts are designed for my own systems first.

View File

@@ -83,6 +83,14 @@ for script in "${SCRIPTS[@]}"; do
exit 1
fi
;;
up)
if [ -f "$BOOTSTRAP_DIR/commands/up.sh" ]; then
. "$BOOTSTRAP_DIR/commands/up.sh" "$@"
else
log_error "Update command script not found."
exit 1
fi
;;
bye)
if [ -f "$BOOTSTRAP_DIR/commands/uninstall.sh" ]; then
. "$BOOTSTRAP_DIR/commands/uninstall.sh"

43
scripts/pre-commit Normal file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Git pre-commit hook to automatically bump the patch version in VERSION file.
# It only increments the version if files other than VERSION are staged for commit.
set -euo pipefail
VERSION_FILE="VERSION"
if [ ! -f "$VERSION_FILE" ]; then
echo "1.0.0" > "$VERSION_FILE"
git add "$VERSION_FILE"
exit 0
fi
# Check if there are staged changes other than the VERSION file
if ! git diff --cached --name-only | grep -qv "^$VERSION_FILE$"; then
# No other files staged, skip version bump
exit 0
fi
# Read current version
current_version=$(cat "$VERSION_FILE" | tr -d '[:space:]')
# Basic regex validation for semantic versioning (X.Y.Z)
if [[ ! "$current_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Current version '$current_version' in $VERSION_FILE is not in X.Y.Z format." >&2
exit 1
fi
# Parse version components
IFS='.' read -r major minor patch <<< "$current_version"
# Increment patch version
patch=$((patch + 1))
new_version="$major.$minor.$patch"
# Write to VERSION file
echo "$new_version" > "$VERSION_FILE"
# Add VERSION file to the commit
git add "$VERSION_FILE"
echo "[pre-commit] Automatically bumped version from $current_version to $new_version"