Skip to content

Resolve default remote for sync/init when multiple remotes exist#120

Merged
jallum merged 10 commits into
jallum:mainfrom
MacMorgan:default-remote-configuration
May 9, 2026
Merged

Resolve default remote for sync/init when multiple remotes exist#120
jallum merged 10 commits into
jallum:mainfrom
MacMorgan:default-remote-configuration

Conversation

@MacMorgan

@MacMorgan MacMorgan commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Previously bw sync would push to every remote that had the beadwork branch, and bw init silently picked one. With multiple remotes this is ambiguous and surprising.

This PR introduces a RemoteResolver callback through repo.Init, repo.ForceReinit, repo.Sync, and repo.Push. The resolver selects a single remote using a short-circuit chain:

  1. If a remote already has the beadwork branch, use it (bootstrap case)
  2. If a remote named origin exists, use it silently
  3. If git config beadwork.remote is set, use that
  4. If stdin is a TTY, present a numbered menu and persist the choice to git config beadwork.remote
  5. Otherwise, error with instructions on how to set the remote non-interactively

The prompt logic is shared between sync and init via remote_prompt.go. Each command keeps its own stdin variable (syncStdin / initStdin) so tests can drive them independently without shared state.

MacMorgan and others added 7 commits May 7, 2026 09:06
bw sync now probes every git remote; any that has the beadwork branch
gets fetched, merged, and pushed to. When no remote has it yet, a single
remote is picked via: only-one-remote, then git config beadwork.remote,
then a remote named origin, then an interactive prompt (TTY only, via
term.IsTerminal — no /dev/tty fallback), with the selection persisted
to git config so subsequent syncs don't re-prompt. Non-interactive runs
fail with a message that names the remotes and the config fix.

Drops the .bwconfig remote= fallback shipped with the configurable-
default-remote feature; remote selection is now git-config-or-origin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When `bw init` runs in a repo with 2+ remotes and none have the
beadwork branch yet, init now asks the user which remote bw should
sync with going forward and persists the choice to
git config beadwork.remote. Short-circuits match sync: single-remote
and existing git config / origin-by-name skip the prompt silently (no
persist needed — sync re-applies the same rules).

Unlike sync, init's prompt is not gated on term.IsTerminal. `bw init`
is a human-initiated setup step; callers who really can't interact
can set git config beadwork.remote beforehand and the resolver is
never invoked.

Init also now probes every remote for the beadwork branch rather than
only the configured one, so fresh clones with a non-origin seed
remote bootstrap correctly without needing git config.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
promptForRemoteWithReader and gitConfigSet are used by both the sync
and init resolvers; putting them in sync.go was misleading. Move them
to their own file and inline the single-use promptForRemote wrapper
into the sync resolver. No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
makeRemoteResolver now takes a stdin source and is shared by both
commands; makeInitRemoteResolver is gone. Init therefore inherits the
same isInteractiveStdin gate as sync: non-interactive runs that would
otherwise need to prompt now error out with the same "no default
remote — ..." message. Callers who can't interact set
git config beadwork.remote before running bw init.

Tests: TestCmdInitMultiRemotePrompts now stubs isInteractiveStdin to
true; the former TestCmdInitMultiRemoteIgnoresTTYStub is inverted to
TestCmdInitNonInteractiveFailsWithoutPrompt, mirroring sync's gate
test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jallum jallum force-pushed the default-remote-configuration branch from c651d21 to abab0db Compare May 7, 2026 13:11
jallum added 2 commits May 7, 2026 10:56
Replace multi-remote fan-out with single-target sync: targetRemotes now
returns the first remote (alphabetically) that has the beadwork branch
rather than all of them, emitting a warning to stderr when more than one
is found. This removes the three-phase multi-remote loop from syncTo,
collapsing it to a straightforward fetch/merge/push against one remote.
pushTo is removed; Push inlines the single-call.

Tests updated to assert the new behaviour: the primary remote advances
and secondary remotes are left untouched.
@jallum jallum changed the title added default remote configuration Resolve default remote for sync/init when multiple remotes exist May 7, 2026
@jallum jallum merged commit edb4a00 into jallum:main May 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants