Guard every refresh's entry point, not just the commits scope

With every scope's worker reads now captured on the UI thread and every
worker caller on RefreshFromWorker, the debug entry-point assertion no longer
needs to be scoped to the commits refresh. Move it to the top of
performRefresh so it guards every refresh regardless of which scopes it
touches, and drop the per-scope gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-07-06 16:20:11 +02:00
parent fd6b20847a
commit 5162a768eb

View file

@ -119,13 +119,13 @@ func (self *RefreshHelper) performRefresh(options types.RefreshOptions, calledFr
// runs inline or has to hop (see captureOnUIThread).
fRunsOnUIThread := options.Mode == types.BLOCK_UI || !calledFromWorker
// Record the caller's own goroutine now, before a BLOCK_UI refresh dispatches
// f onto the UI thread, so the debug assertion below can verify the caller
// picked the entry point matching its thread regardless of the mode. Only
// read in debug (goid stays out of production control flow).
callerIsUIThread := false
if self.c.GetConfig().GetDebug() {
callerIsUIThread = self.c.GocuiGui().IsUIThread()
// Debug-only guard: every refresh must be issued from the entry point that
// matches its goroutine — Refresh on the UI thread, RefreshFromWorker on a
// worker. We check the caller's own goroutine here, before a BLOCK_UI
// refresh dispatches f onto the UI thread, so it holds regardless of the
// mode. goid stays out of production control flow (debug only).
if self.c.GetConfig().GetDebug() && self.c.GocuiGui().IsUIThread() == calledFromWorker {
panic("Refresh called from a worker, or RefreshFromWorker called from the UI thread")
}
f := func() {
@ -212,18 +212,6 @@ func (self *RefreshHelper) performRefresh(options types.RefreshOptions, calledFr
var loadedRemotes []*models.Remote
includeWorktreesWithBranches := false
if scopeSet.Includes(types.COMMITS) || scopeSet.Includes(types.BRANCHES) {
// Debug-only guard: the caller must have picked the entry point that
// matches its goroutine — Refresh on the UI thread, RefreshFromWorker
// on a worker. We check the caller's own thread (captured above,
// before any BLOCK_UI dispatch), so it holds regardless of the mode.
// It's scoped to the commits refresh for now, the one scope whose
// worker reads have moved to the UI-thread capture below; once the
// other scopes are converted too it can move up to guard every
// refresh unconditionally.
if self.c.GetConfig().GetDebug() && callerIsUIThread == calledFromWorker {
panic("Refresh called from a worker, or RefreshFromWorker called from the UI thread")
}
// whenever we change commits, we should update branches because the upstream/downstream
// counts can change. Whenever we change branches we should also change commits
// e.g. in the case of switching branches.