#!/usr/bin/env bash set -euo pipefail # loadout bootstrap: # - downloads repo tarball # - runs per-OS installer # - installs a `loadout` helper command for future runs # # Usage (stdin + args): # curl -fsSL https://loadout.timlind.net | bash -s -- --dev --gaming # wget -qO- https://loadout.timlind.net | bash -s -- --dev --gaming log() { printf "[loadout-bootstrap] %s\n" "$*"; } die() { printf "[loadout-bootstrap] ERROR: %s\n" "$*" >&2; exit 1; } have_cmd() { command -v "$1" >/dev/null 2>&1; } sudo_run() { if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then "$@" else have_cmd sudo || die "sudo is required for: $*" sudo "$@" fi } choose_fetcher() { local pref="${LOADOUT_FETCHER:-}" if [[ -n "$pref" ]]; then if have_cmd "$pref"; then printf "%s" "$pref" return 0 fi die "Requested fetcher not found: $pref (set via LOADOUT_FETCHER)" fi if have_cmd curl; then printf "curl" return 0 fi if have_cmd wget; then printf "wget" return 0 fi die "Need curl or wget to bootstrap." } fetch_url() { local fetcher="$1" local url="$2" case "$fetcher" in curl) curl -fsSL "$url" ;; wget) wget -qO- "$url" ;; *) die "Unknown fetcher: $fetcher" ;; esac } install_loadout_helper() { local url="$1" local fetcher="$2" local target_user="${SUDO_USER:-${USER:-}}" local target_home="${HOME:-}" if [[ -n "$target_user" ]]; then target_home="$(getent passwd "$target_user" | cut -d: -f6 || true)" fi [[ -n "$target_home" ]] || die "Cannot resolve target home directory." # Config is per-user even if the helper is installed system-wide. local cfg_dir="$target_home/.config/loadout" mkdir -p "$cfg_dir" local cfg_file="$cfg_dir/bootstrap.env" cat >"$cfg_file" </dev/null || true fi # Install helper where it's immediately discoverable on PATH. local existing_helper="" local helper_dir="" existing_helper="$(type -p loadout 2>/dev/null || true)" if [[ -n "$existing_helper" && -x "$existing_helper" ]]; then case "$(dirname "$existing_helper")" in "$target_home/.local/bin"|/usr/local/bin) helper_dir="$(dirname "$existing_helper")" ;; esac fi if [[ -z "$helper_dir" ]]; then if [[ -w /usr/local/bin ]]; then helper_dir="/usr/local/bin" else # Try /usr/local/bin via sudo, fall back to ~/.local/bin. if have_cmd sudo; then helper_dir="/usr/local/bin" else helper_dir="$target_home/.local/bin" fi fi fi if [[ "$helper_dir" == "/usr/local/bin" && ! -w /usr/local/bin ]] && ! have_cmd sudo; then helper_dir="$target_home/.local/bin" fi if [[ "$helper_dir" == "$target_home/.local/bin" ]]; then mkdir -p "$helper_dir" fi local tmp_helper tmp_helper="$(mktemp)" cat >"$tmp_helper" <<'EOF' #!/usr/bin/env bash set -euo pipefail die() { printf "[loadout] ERROR: %s\n" "$*" >&2; exit 1; } have_cmd() { command -v "$1" >/dev/null 2>&1; } cfg="${XDG_CONFIG_HOME:-$HOME/.config}/loadout/bootstrap.env" if [[ -f "$cfg" ]]; then # shellcheck disable=SC1090 source "$cfg" fi url="${LOADOUT_URL:-https://loadout.timlind.net}" fetcher="${LOADOUT_FETCHER:-${LOADOUT_FETCHER_DEFAULT:-}}" if [[ -n "$fetcher" ]] && ! have_cmd "$fetcher"; then fetcher="" fi if [[ -z "$fetcher" ]]; then if have_cmd curl; then fetcher="curl" elif have_cmd wget; then fetcher="wget" else die "Need curl or wget." fi fi case "$fetcher" in curl) curl -fsSL "$url" | bash -s -- "$@" ;; wget) wget -qO- "$url" | bash -s -- "$@" ;; *) die "Unknown fetcher: $fetcher" ;; esac EOF chmod +x "$tmp_helper" local helper="$helper_dir/loadout" if [[ "$helper_dir" == "/usr/local/bin" && ! -w /usr/local/bin ]]; then # Needs sudo to place in /usr/local/bin. sudo_run install -m 0755 "$tmp_helper" "$helper" else install -m 0755 "$tmp_helper" "$helper" fi rm -f "$tmp_helper" log "Installed helper: $helper" if [[ -n "$existing_helper" && "$existing_helper" != "$helper" ]]; then log "NOTE: Another loadout helper exists at $existing_helper" log " Remove it or run: hash -r to refresh your shell." fi if [[ ":${PATH:-}:" != *":$helper_dir:"* ]]; then log "NOTE: '$helper_dir' is not on PATH in this shell." log " Start a new shell, or run: export PATH=\"$helper_dir:\$PATH\"" fi log "Run: loadout --help" } REPO_OWNER="${LOADOUT_GH_OWNER:-timlindnet}" REPO_NAME="${LOADOUT_GH_REPO:-loadout}" REF="${LOADOUT_GH_REF:-main}" LOADOUT_URL="${LOADOUT_URL:-https://loadout.timlind.net}" TARBALL_URL="https://github.com/${REPO_OWNER}/${REPO_NAME}/archive/refs/heads/${REF}.tar.gz" tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT fetcher="$(choose_fetcher)" log "Downloading ${REPO_OWNER}/${REPO_NAME}@${REF}..." fetch_url "$fetcher" "$TARBALL_URL" >"$tmp/repo.tgz" log "Extracting..." tar -xzf "$tmp/repo.tgz" -C "$tmp" repo_dir="" for d in "$tmp"/*; do if [[ -d "$d" ]]; then repo_dir="$d" break fi done [[ -n "$repo_dir" && -d "$repo_dir" ]] || die "Could not locate extracted repo directory." log "Running install..." bash "$repo_dir/install.sh" "$@" install_loadout_helper "$LOADOUT_URL" "$fetcher"