From 6d8ab1d0639f19227786a67103eca9582e219dd2 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 3 Jul 2026 17:35:44 +0200 Subject: [PATCH] Run the immediate startup branch refresh before spawning the async one At the INITIAL startup stage two branch refreshes happen: an immediate one sorted by whatever reflog we have (empty, so not by recency), and an async one that loads the reflog first and re-sorts by recency. Until now the async one was spawned first and the immediate one ran afterwards; this inverts that so the immediate refresh runs before the async one is spawned. With RefreshingBranchesMutex still in place this is behavior-preserving (the mutex serializes the two either way). It's a preparatory step for replacing that mutex with a branch-load sequence guard: running the immediate refresh first establishes a happens-before relation between the two loads' sequence numbers, so the recency-sorted one is guaranteed the higher sequence. This also lets refreshReflogCommitsConsideringStartup fold into refreshReflogAndBranches, whose two-phase logic is now all in one place. Co-Authored-By: Claude Opus 4.8 (1M context) --- pkg/gui/controllers/helpers/refresh_helper.go | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index 75d5d2fd4..95c7fa4a7 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -377,19 +377,18 @@ func getModeName(mode types.RefreshMode) string { } } -// during startup, the bottleneck is fetching the reflog entries. We need these -// on startup to sort the branches by recency. So we have two phases: INITIAL, and COMPLETE. -// In the initial phase we don't get any reflog commits, but we asynchronously get them -// and refresh the branches after that -// refreshReflogCommitsConsideringStartup returns the reflog commits that the -// caller should hand to refreshBranches for recency sorting. In the COMPLETE -// (normal) case that's the freshly-loaded reflog; in the INITIAL case the -// reflog is loaded asynchronously (and drives its own branches refresh once -// ready), so we return the current model value for the immediate, -// non-recency-sorted branches refresh the caller does in the meantime. -func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() []*models.Commit { +// During startup, the bottleneck is fetching the reflog entries, which we need +// in order to sort the branches by recency. So we have two phases: INITIAL and +// COMPLETE. In the INITIAL phase we don't have any reflog commits yet, so we +// show the branches right away sorted by whatever we have (typically nothing, +// i.e. not by recency), then load the reflog on a worker and refresh the +// branches again, this time recency-sorted. From then on we're in the COMPLETE +// phase and load the reflog synchronously before refreshing the branches. +func (self *RefreshHelper) refreshReflogAndBranches(refreshWorktrees bool, keepBranchSelectionIndex bool) { switch self.c.State().GetRepoState().GetStartupStage() { case types.INITIAL: + self.refreshBranches(refreshWorktrees, keepBranchSelectionIndex, false, self.c.Model().ReflogCommits) + self.c.OnWorker(func(_ gocui.Task) error { reflogCommits, _ := self.refreshReflogCommits() self.refreshBranches(false, true, true, reflogCommits) @@ -397,22 +396,10 @@ func (self *RefreshHelper) refreshReflogCommitsConsideringStartup() []*models.Co return nil }) - return self.c.Model().ReflogCommits - case types.COMPLETE: reflogCommits, _ := self.refreshReflogCommits() - return reflogCommits + self.refreshBranches(refreshWorktrees, keepBranchSelectionIndex, true, reflogCommits) } - - return self.c.Model().ReflogCommits -} - -func (self *RefreshHelper) refreshReflogAndBranches(refreshWorktrees bool, keepBranchSelectionIndex bool) { - loadBehindCounts := self.c.State().GetRepoState().GetStartupStage() == types.COMPLETE - - reflogCommits := self.refreshReflogCommitsConsideringStartup() - - self.refreshBranches(refreshWorktrees, keepBranchSelectionIndex, loadBehindCounts, reflogCommits) } func (self *RefreshHelper) refreshCommitsAndCommitFiles(commitSelection types.CommitSelectionBehavior) {