From 1b0cc02e1e5106308ec0e1e4ae233987f3d50795 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 10 Jul 2026 12:21:45 +0200 Subject: [PATCH] Refresh once when dropping multiple stash entries Dropping a range of stashes ran a refresh after each drop. A refresh issued from the UI thread does its git work on a worker and applies the model update in the background, so firing one per iteration let the workers race: an earlier drop's refresh (which read a stash list that still contained a later-dropped entry) could apply its result last, leaving the stash view showing an entry that git had already removed. Refresh once, after all the drops, so a single worker reads the final stash list. The indices are captured up front and dropped highest-first, so the remaining lower indices stay valid without an intervening refresh. It's also cheaper: one `git stash list` instead of one per entry. Co-Authored-By: Claude Opus 4.8 (1M context) --- pkg/gui/controllers/stash_controller.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/gui/controllers/stash_controller.go b/pkg/gui/controllers/stash_controller.go index 06e6991c6..a2b7e9e97 100644 --- a/pkg/gui/controllers/stash_controller.go +++ b/pkg/gui/controllers/stash_controller.go @@ -170,11 +170,16 @@ func (self *StashController) handleStashDrop(stashEntries []*models.StashEntry) Prompt: self.c.Tr.SureDropStashEntry, HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.DropStash) + // Refresh once at the end rather than after each drop: an async + // refresh from the UI thread finishes in the background, so firing + // one per iteration lets the workers race and an earlier, stale + // result can land last. The indices are captured up front and we + // drop highest-first, so the remaining lower indices stay valid + // without an intervening refresh. + defer self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH}}) for i := len(stashEntries) - 1; i >= 0; i-- { self.c.LogCommand(fmt.Sprintf(self.c.Tr.Log.DroppingStash, stashEntries[i].Hash), false) - err := self.c.Git().Stash.Drop(stashEntries[i].Index) - self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.STASH}}) - if err != nil { + if err := self.c.Git().Stash.Drop(stashEntries[i].Index); err != nil { return err } }