#!/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 -- ubuntu --dev --gaming # wget -qO- https://loadout.timlind.net | bash -s -- ubuntu --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 default_os="$3" 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 helper_dir="" 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" mkdir -p "$helper_dir" fi 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}" default_os="${LOADOUT_DEFAULT_OS:-ubuntu}" os="$default_os" if [[ "${1:-}" != "" && "${1:-}" != "-"* ]]; then # Allow overriding the OS explicitly: `loadout ubuntu --dev`. os="$1" shift fi 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 -- "$os" "$@" ;; wget) wget -qO- "$url" | bash -s -- "$os" "$@" ;; *) 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 [[ ":${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" } os="${1:-}" if [[ -z "$os" || "$os" == "-"* ]]; then die "Missing OS argument. Example: bash -s -- ubuntu --dev --gaming" fi shift 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 for OS '$os'..." bash "$repo_dir/$os/install.sh" "$@" install_loadout_helper "$LOADOUT_URL" "$fetcher" "$os"