From 51ceb194803ca8bc011327512015a8c98bdebd29 Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Fri, 21 Aug 2026 18:47:17 -0400 Subject: [PATCH] One command from fresh Fedora to the front door `boot` is the script the README now leads with: curl it, and it installs git if the machine lacks it, clones the repository to PANAMA_PATH, and hands off to ./install -- reattaching the terminal first, because a piped stdin would strand the interview. Deliberately dumb: a curled copy leaves the repository the moment it runs, so nothing that can drift lives in it. Re-running is the recovery path: an existing clone is fast-forwarded, never re-cloned, and a refused fast-forward installs from what is there rather than stopping mid-repair. All of it pinned by the boot contract, against stub git and a throwaway clone. --- README.md | 14 ++++- boot | 59 +++++++++++++++++++++ tests/setup/boot-contract | 104 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 1 deletion(-) create mode 100755 boot create mode 100755 tests/setup/boot-contract diff --git a/README.md b/README.md index 9304491..6b25ab7 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,23 @@ Formerly Sunhat. A personal config for Fedora, with the intention of helping a user set up their Fedora system with one command. +```sh +bash <(curl -fsSL https://git.gbrown.org/gib/Panama/raw/branch/main/boot) +``` + +`boot` installs git if the machine lacks it, clones this repository to +`~/.local/share/Panama` (or `$PANAMA_PATH`), and hands off to `install`. It is +deliberately small enough to read first, and the same two steps by hand work +identically: + ```sh git clone https://git.gbrown.org/gib/Panama.git ~/.local/share/Panama ~/.local/share/Panama/install ``` +Both are safe to run again: an existing clone is fast-forwarded rather than +replaced, and `install` is the upgrade path. + `install` asks its questions first and then runs the stages in `setup/scripts/` in order, without stopping again: @@ -101,7 +113,7 @@ docs/ Settings reference, and the design specs behind the work ## Tests -131 of them, under `tests/`. Run the lot, or a subset by pattern: +132 of them, under `tests/`. Run the lot, or a subset by pattern: ```sh panama test # everything diff --git a/boot b/boot new file mode 100755 index 0000000..4520bbc --- /dev/null +++ b/boot @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +# Panama's front door: the one command a fresh Fedora machine needs. +# +# bash <(curl -fsSL https://git.gbrown.org/gib/Panama/raw/branch/main/boot) +# +# Deliberately dumb, because a copy of this script leaves the repository the +# moment somebody curls it -- nothing here can be fixed by re-running +# ./install, so there is as little here as possible: get git, get the clone, +# hand off. Everything with judgment in it lives in `install`, which is also +# where re-runs and upgrades already work. + +set -euo pipefail + +REPO_URL="https://git.gbrown.org/gib/Panama.git" +PANAMA_PATH="${PANAMA_PATH:-$HOME/.local/share/Panama}" +export PANAMA_PATH + +# Root would put the clone and every dotfile in root's home and run the +# desktop setup for the wrong user. sudo is used inside where it is needed. +if [[ "$(id -u)" -eq 0 ]]; then + echo "Run this as your own user, not root: the install configures YOUR desktop." >&2 + exit 1 +fi + +# Panama assumes Fedora's repositories, package names, and GNOME base install. +if ! grep -qi '^ID=fedora' /etc/os-release 2>/dev/null; then + echo "This looks like something other than Fedora; Panama only supports Fedora Workstation." >&2 + exit 1 +fi + +# git is the one dependency the clone itself needs. Everything else -- gum +# included -- is bootstrapped by `install`. +if ! command -v git >/dev/null 2>&1; then + echo "Installing git, which the clone needs" + sudo dnf install -y git +fi + +if [[ -d "$PANAMA_PATH/.git" ]]; then + # An existing clone makes this the recovery command too. Only a fast-forward: + # local work is never rewritten, and a diverged clone still installs from + # what it has rather than stopping someone mid-repair. + echo "Panama is already cloned at $PANAMA_PATH; updating" + git -C "$PANAMA_PATH" pull --ff-only \ + || echo "Could not fast-forward; installing from the clone as it is" >&2 +else + git clone "$REPO_URL" "$PANAMA_PATH" +fi + +# `curl | bash` and `bash <(curl ...)` can leave stdin as the pipe, and the +# first thing install runs is the interview, which has to be able to ask. +# Reattach the terminal when there is one; without one the interview will say +# so itself. +# The probe actually opens /dev/tty rather than testing -r: a process with no +# controlling terminal passes -r and then fails the redirect. +if [[ ! -t 0 ]] && (exec /dev/null; then + exec "$PANAMA_PATH/install" &2; exit 1; } + +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT + +calls="$work/calls" +stub_dir="$work/bin" +clone_dir="$work/Panama" +mkdir -p "$stub_dir" + +# The stub install records that it ran and what PANAMA_PATH it saw. The stub +# git records its arguments, and materializes a clone the way the real one +# would -- boot execs the clone's install, so the clone has to contain one. +cat >"$work/fake-install" <>"$calls" +STUB +chmod +x "$work/fake-install" + +cat >"$stub_dir/git" <>"$calls" +if [[ "\$1" == "clone" ]]; then + mkdir -p "\$3/.git" + cp "$work/fake-install" "\$3/install" +fi +STUB +chmod +x "$stub_dir/git" + +run_boot() { + : >"$calls" + PATH="$stub_dir:$PATH" PANAMA_PATH="$clone_dir" bash "$boot" /dev/null 2>&1 +} + +# ── A machine without the clone ────────────────────────────────────────────── + +run_boot || note 'boot failed on a machine without the clone' + +grep -q "git clone https://git.gbrown.org/gib/Panama.git $clone_dir" "$calls" \ + || note 'boot does not clone the documented repository to PANAMA_PATH' +grep -q "install PANAMA_PATH=$clone_dir" "$calls" \ + || note 'boot does not hand off to the clone'\''s install with PANAMA_PATH exported' + +# ── A machine that already has it ──────────────────────────────────────────── + +run_boot || note 'boot failed on a machine that already has the clone' + +grep -q 'git clone' "$calls" \ + && note 'boot re-clones over an existing checkout' +grep -q 'git -C .* pull --ff-only' "$calls" \ + || note 'boot does not fast-forward an existing clone' +grep -q "install PANAMA_PATH=$clone_dir" "$calls" \ + || note 'boot does not run the install from an existing clone' + +# ── A diverged clone still installs ────────────────────────────────────────── +# +# pull --ff-only refusing is normal life -- local commits, a rebase upstream. +# The command doubles as the repair path, so a refusal must be stepped over. + +cat >"$stub_dir/git" <<'STUB' +#!/usr/bin/env bash +[[ "$*" == *pull* ]] && exit 1 +exit 0 +STUB +chmod +x "$stub_dir/git" + +: >"$calls" +if ! PATH="$stub_dir:$PATH" PANAMA_PATH="$clone_dir" bash "$boot" /dev/null 2>&1; then + note 'a clone that cannot fast-forward stops the install instead of proceeding' +fi +grep -q "install PANAMA_PATH=$clone_dir" "$calls" \ + || note 'the install does not run when the fast-forward is refused' + +if (( ${#findings[@]} > 0 )); then + printf 'boot contract: %d finding(s)\n' "${#findings[@]}" >&2 + printf ' - %s\n' "${findings[@]}" >&2 + exit 1 +fi + +printf 'boot contract: PASS\n'