From fceba3121209658009109b98b2907db66e586e26 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 6 Jul 2026 17:26:30 +0200 Subject: [PATCH] Capture moveCommitsToNewBranch's model reads on the UI thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two move helpers run inside the WithWaitingStatus worker that withNewBranchNamePrompt dispatches to, but read Model().Files/Submodules (to decide whether to auto-stash) and Model().Commits (the unpushed commits to cherry-pick off the base branch) from there, racing the UI thread's model writes. Compute mustStash — needed by both paths — at the top, and the unpushed commits in the off-of-main menu item, on the UI thread, and pass them into the helpers. --- pkg/gui/controllers/helpers/refs_helper.go | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pkg/gui/controllers/helpers/refs_helper.go b/pkg/gui/controllers/helpers/refs_helper.go index 70ff18593..61f3a232d 100644 --- a/pkg/gui/controllers/helpers/refs_helper.go +++ b/pkg/gui/controllers/helpers/refs_helper.go @@ -424,6 +424,8 @@ func (self *RefsHelper) MoveCommitsToNewBranch() error { return err } + mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) + withNewBranchNamePrompt := func(baseBranchName string, f func(string) error) error { prompt := utils.ResolvePlaceholderString( self.c.Tr.NewBranchNameBranchOff, @@ -462,7 +464,9 @@ func (self *RefsHelper) MoveCommitsToNewBranch() error { Title: self.c.Tr.MoveCommitsToNewBranch, Prompt: prompt, HandleConfirm: func() error { - return withNewBranchNamePrompt(currentBranch.Name, self.moveCommitsToNewBranchStackedOnCurrentBranch) + return withNewBranchNamePrompt(currentBranch.Name, func(newBranchName string) error { + return self.moveCommitsToNewBranchStackedOnCurrentBranch(newBranchName, mustStash) + }) }, }) return nil @@ -482,27 +486,31 @@ func (self *RefsHelper) MoveCommitsToNewBranch() error { { Label: fmt.Sprintf(self.c.Tr.MoveCommitsToNewBranchFromBaseItem, shortBaseBranchName), OnPress: func() error { + commitsToCherryPick := lo.Filter(self.c.Model().Commits, func(commit *models.Commit, _ int) bool { + return commit.Status == models.StatusUnpushed + }) return withNewBranchNamePrompt(shortBaseBranchName, func(newBranchName string) error { - return self.moveCommitsToNewBranchOffOfMainBranch(newBranchName, baseBranchRef) + return self.moveCommitsToNewBranchOffOfMainBranch(newBranchName, baseBranchRef, commitsToCherryPick, mustStash) }) }, }, { Label: fmt.Sprintf(self.c.Tr.MoveCommitsToNewBranchStackedItem, currentBranch.Name), OnPress: func() error { - return withNewBranchNamePrompt(currentBranch.Name, self.moveCommitsToNewBranchStackedOnCurrentBranch) + return withNewBranchNamePrompt(currentBranch.Name, func(newBranchName string) error { + return self.moveCommitsToNewBranchStackedOnCurrentBranch(newBranchName, mustStash) + }) }, }, }, }) } -func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchName string) error { +func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchName string, mustStash bool) error { if err := self.c.Git().Branch.NewWithoutCheckout(newBranchName, "HEAD"); err != nil { return err } - mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) if mustStash { if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil { return err @@ -532,12 +540,7 @@ func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchNa return nil } -func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName string, baseBranchRef string) error { - commitsToCherryPick := lo.Filter(self.c.Model().Commits, func(commit *models.Commit, _ int) bool { - return commit.Status == models.StatusUnpushed - }) - - mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) +func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName string, baseBranchRef string, commitsToCherryPick []*models.Commit, mustStash bool) error { if mustStash { if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil { return err