diff --git a/.mise/tasks/configure-forge-remotes b/.mise/tasks/configure-forge-remotes new file mode 100755 index 0000000..f2ec88f --- /dev/null +++ b/.mise/tasks/configure-forge-remotes @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +#MISE description="Mirror pushes to tangled, gitlab and github" +set -euo pipefail + +REPO_DIR="$HOME/.dotfiles" + +# Auth-free URL for pulls. Keeping origin on HTTPS (rather than SSH) keeps +# `mise bootstrap --from ` origin checks passing on every run. +PULL_URL="https://tangled.org/spencergilbert.dev/dotfiles" + +# Every forge that `git push` should fan out to. +PUSH_URLS=( + "git@tangled.org:did:plc:an5o2a52tfyhntuwsopwqnof" + "git@gitlab.com:spencergilbert/dotfiles.git" + "git@github.com:spencergilbert/dotfiles.git" +) + +# Idempotent: re-running it resets the URLs instead of duplicating them. +[ -d "$REPO_DIR/.git" ] || exit 0 +git -C "$REPO_DIR" remote set-url origin "$PULL_URL" +git -C "$REPO_DIR" config --unset-all remote.origin.pushurl || true +for url in "${PUSH_URLS[@]}"; do + git -C "$REPO_DIR" config --add remote.origin.pushurl "$url" +done +git -C "$REPO_DIR" config remote.pushdefault origin diff --git a/install.sh b/install.sh index 70f81e7..64ec04f 100755 --- a/install.sh +++ b/install.sh @@ -4,49 +4,20 @@ set -euo pipefail MISE_BIN="$HOME/.local/bin/mise" REPO_DIR="$HOME/.dotfiles" -# Public, auth-free URL used only for the very first clone. -CLONE_URL="https://tangled.org/spencergilbert.dev/dotfiles" +# Public, auth-free URL for the first clone and subsequent pulls. +# Pushes fan out to SSH mirrors via configure-forge-remotes +# ([bootstrap.hooks.final]). +FROM_URL="https://tangled.org/spencergilbert.dev/dotfiles" -# Where the repo is pulled from (canonical forge). -PULL_URL="git@tangled.org:did:plc:an5o2a52tfyhntuwsopwqnof" - -# Every forge that `git push` should fan out to. -PUSH_URLS=( - "$PULL_URL" - "git@gitlab.com:spencergilbert/dotfiles.git" - "git@github.com:spencergilbert/dotfiles.git" -) - -# Point origin at the pull URL and mirror pushes to every forge above. -# Idempotent: re-running it resets pushurl entries instead of duplicating them. -configure_remotes() { - if git -C "$REPO_DIR" remote get-url origin >/dev/null 2>&1; then - git -C "$REPO_DIR" remote set-url origin "$PULL_URL" - else - git -C "$REPO_DIR" remote add origin "$PULL_URL" - fi - - git -C "$REPO_DIR" config --unset-all remote.origin.pushurl || true - for url in "${PUSH_URLS[@]}"; do - git -C "$REPO_DIR" config --add remote.origin.pushurl "$url" - done - git -C "$REPO_DIR" config remote.pushdefault origin -} +command -v "$MISE_BIN" >/dev/null 2>&1 || curl -fsSL https://mise.run | sh if [ -d "$REPO_DIR/.git" ]; then - configure_remotes - # Forges reject pushes of shallow history; deepen if we were cloned with --depth. - if [ -f "$REPO_DIR/.git/shallow" ]; then - git -C "$REPO_DIR" fetch --unshallow origin || true - fi - git -C "$REPO_DIR" pull --rebase --autostash -else - git clone --depth 1 "$CLONE_URL" "$REPO_DIR" - configure_remotes + # Older checkouts pulled via SSH, which `mise bootstrap --from` rejects + # as an origin mismatch — normalize once (idempotent thereafter). + git -C "$REPO_DIR" remote set-url origin "$FROM_URL" fi -command -v "$MISE_BIN" >/dev/null 2>&1 || curl -fsSL https://mise.run | sh - -cd "$REPO_DIR" +"$MISE_BIN" bootstrap --from "$FROM_URL" --from-dir "$REPO_DIR" --update --yes +# `--from` trusts the checkout for that invocation only; persist it so later +# bare `mise` invocations don't prompt. "$MISE_BIN" trust "$REPO_DIR" -"$MISE_BIN" bootstrap --yes diff --git a/mise.toml b/mise.toml index 83ee503..608be57 100644 --- a/mise.toml +++ b/mise.toml @@ -11,6 +11,9 @@ root = "~/.dotfiles" [bootstrap.hooks.pre-dotfiles] run = "mkdir -p -m 700 $HOME/.ssh/sockets" +[bootstrap.hooks.final] +run = "mise run configure-forge-remotes" + [dotfiles] "~/.config/bat/" = "bat/" "~/.config/fish/" = { source = "fish/", mode = "symlink-each" }