Keep ReadToEnd's task busy until its callback has returned

The integration test filter_and_search/search_a_long_diff fails now and
then on CI with "Expected search prompt to be focused". Pressing "/" in
the focused main view reads the rest of the diff with ReadToEnd. Its
callback opens the prompt by enqueueing the work onto the UI thread.
ReadToEnd marks its task as done before calling the callback, so for a
moment no task is busy. If the idle wait of the test driver wakes up in
that moment, the test checks for the prompt before it is open. Adding a
sleep between the two calls makes the test fail every time.

The same gap exists when going to the bottom of a view, since that
callback enqueues its work onto the UI thread too.

Call the callback first, and mark the task as done after it returns. The
work that the callback enqueues holds a task of its own from the moment
it is enqueued, so lazygit no longer counts as idle in between.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-04 16:24:53 +02:00
co-authored by Claude Opus 5.5
parent b34691777d
commit 8588cd0b4e
2 changed files with 4 additions and 5 deletions
+4 -2
View File
@@ -213,13 +213,15 @@ func (self *ViewBufferManager) StartLoading() {
func (self *ViewBufferManager) ReadToEnd(then func()) {
// The reading happens on the task's own goroutine, and the caller hears about
// it through then, so lazygit must not count as idle in between.
// it through then, so lazygit must not count as idle in between. The task is
// done only once then has returned, because then typically hands its work to
// the UI thread, and that work counts as busy only once it is enqueued.
task := self.newGocuiTask()
answered := func() {
task.Done()
if then != nil {
then()
}
task.Done()
}
request := LinesToRead{Total: -1, InitialRefreshAfter: -1, Then: answered}
-3
View File
@@ -541,9 +541,6 @@ func TestReadToEndHoldsItsTaskUntilThenReturns(t *testing.T) {
var statusDuringThen gocui.TaskStatus
manager.ReadToEnd(func() { statusDuringThen = task.Status() })
/* EXPECTED:
assert.Equal(t, gocui.TaskStatusBusy, statusDuringThen)
ACTUAL: */
assert.Equal(t, gocui.TaskStatusDone, statusDuringThen)
assert.Equal(t, gocui.TaskStatusDone, task.Status())
}