Drop the now-unused UI-thread CheckMergeOrRebase path

With the last synchronous commit-surgery callers moved to workers,
nothing runs CheckMergeOrRebase on the UI thread anymore, so
CheckMergeOrRebaseWithRefreshOptionsFromUIThread has no callers. Remove
it and fold the shared checkMergeOrRebaseImpl back into
CheckMergeOrRebaseWithRefreshOptions, which is now always on a worker.
The runAction closure loses its calledFromWorker parameter for the same
reason.

genericMergeCommandImpl keeps its calledFromWorker flag: the
merge/rebase-continue subprocess path still runs on the UI thread when
invoked straight from the menu, and on a worker for the recursive
auto-skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller 2026-07-08 18:05:11 +02:00
parent d802cbdddf
commit a324f8aef1

View file

@ -89,11 +89,11 @@ func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error {
// non-subprocess path runs on a worker with a waiting status.
//
// showWaitingStatus is false only for the recursive auto-skip in
// checkMergeOrRebaseImpl: that call already runs on the caller's thread (the
// worker of the enclosing waiting status, or the UI thread for the synchronous
// callers), so it must not spin up a second one. calledFromWorker says which of
// those two the body runs on, so the post-action refresh picks Refresh vs
// RefreshFromWorker correctly.
// CheckMergeOrRebaseWithRefreshOptions, which already runs on a worker, so it
// must not spin up a second waiting status. calledFromWorker is used only by the
// subprocess path below: it's true for that recursive worker skip and false for
// genericMergeCommand's UI-thread invocation, so the post-action refresh picks
// RefreshFromWorker vs Refresh correctly.
func (self *MergeAndRebaseHelper) genericMergeCommandImpl(command string, showWaitingStatus bool, calledFromWorker bool) error {
status := self.c.Git().Status.WorkingTreeState()
@ -139,21 +139,23 @@ func (self *MergeAndRebaseHelper) genericMergeCommandImpl(command string, showWa
return err
}
runAction := func(calledFromWorker bool) error {
// runAction always ends up on a worker: either the waiting status below spins
// one up, or we're the recursive auto-skip reached from
// CheckMergeOrRebaseWithRefreshOptions, which already runs on one.
runAction := func() error {
result := self.c.Git().Rebase.GenericMergeOrRebaseAction(commandType, command)
return self.checkMergeOrRebaseImpl(result,
return self.CheckMergeOrRebaseWithRefreshOptions(result,
types.RefreshOptions{
CommitSelection: commitSelectionAfterMerge(result == nil && selectHeadCommitOnSuccess),
}, calledFromWorker)
})
}
if showWaitingStatus {
return self.c.WithWaitingStatus(status.Title(self.c.Tr), func(gocui.Task) error {
// The waiting status ran runAction on a worker.
return runAction(true)
return runAction()
})
}
return runAction(calledFromWorker)
return runAction()
}
// commitSelectionAfterMerge maps whether a merge/rebase/pull created a new
@ -209,33 +211,19 @@ func (self *MergeAndRebaseHelper) RecordWhetherMergeOrRebaseStartedInLazygit() {
}
// CheckMergeOrRebaseWithRefreshOptions handles the result of a merge/rebase
// step and refreshes. It's for callers running on a worker (the
// WithWaitingStatus / WithInlineStatus handlers), which is the large majority;
// UI-thread callers use CheckMergeOrRebaseWithRefreshOptionsFromUIThread.
// step and refreshes. It always runs on a worker (the WithWaitingStatus /
// WithWaitingStatusBlockingInput / WithInlineStatus handlers).
func (self *MergeAndRebaseHelper) CheckMergeOrRebaseWithRefreshOptions(result error, refreshOptions types.RefreshOptions) error {
return self.checkMergeOrRebaseImpl(result, refreshOptions, true)
}
// CheckMergeOrRebaseWithRefreshOptionsFromUIThread is like
// CheckMergeOrRebaseWithRefreshOptions, but for the callers that run the
// merge/rebase synchronously on the UI thread (the WithWaitingStatusSync
// move/revert/squash-fixups/cherry-pick-paste/patch-discard handlers, kept sync
// so rapid key presses batch) rather than on a worker.
func (self *MergeAndRebaseHelper) CheckMergeOrRebaseWithRefreshOptionsFromUIThread(result error, refreshOptions types.RefreshOptions) error {
return self.checkMergeOrRebaseImpl(result, refreshOptions, false)
}
func (self *MergeAndRebaseHelper) checkMergeOrRebaseImpl(result error, refreshOptions types.RefreshOptions, calledFromWorker bool) error {
self.refreshAfterMergeOrRebase(refreshOptions, calledFromWorker)
self.refreshAfterMergeOrRebase(refreshOptions, true)
self.RecordWhetherMergeOrRebaseStartedInLazygit()
if result == nil {
return nil
} else if strings.Contains(result.Error(), "No changes - did you forget to use") {
return self.genericMergeCommandImpl(REBASE_OPTION_SKIP, false, calledFromWorker)
return self.genericMergeCommandImpl(REBASE_OPTION_SKIP, false, true)
} else if strings.Contains(result.Error(), "The previous cherry-pick is now empty") {
return self.genericMergeCommandImpl(REBASE_OPTION_SKIP, false, calledFromWorker)
return self.genericMergeCommandImpl(REBASE_OPTION_SKIP, false, true)
} else if strings.Contains(result.Error(), "No rebase in progress?") {
// assume in this case that we're already done
return nil
@ -245,8 +233,8 @@ func (self *MergeAndRebaseHelper) checkMergeOrRebaseImpl(result error, refreshOp
// refreshAfterMergeOrRebase issues the post-action refresh on the entry point
// that matches the thread the merge/rebase ran on: RefreshFromWorker for the
// worker callers, Refresh for the ones that stayed synchronously on the UI
// thread.
// worker callers, Refresh for the merge/rebase-continue subprocess path that
// stays on the UI thread.
func (self *MergeAndRebaseHelper) refreshAfterMergeOrRebase(refreshOptions types.RefreshOptions, calledFromWorker bool) {
if calledFromWorker {
self.c.RefreshFromWorker(refreshOptions)