diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index deaeee042..af935b085 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -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} diff --git a/pkg/tasks/tasks_test.go b/pkg/tasks/tasks_test.go index c50a54cac..6cc1cf9d6 100644 --- a/pkg/tasks/tasks_test.go +++ b/pkg/tasks/tasks_test.go @@ -522,3 +522,25 @@ func TestQueuedReadRequestsAreAnsweredWhenTheTaskStops(t *testing.T) { assert.EqualValues(t, 2, answered.Load()) } + +// The callers of ReadToEnd hand their follow-up work to the UI thread from then, and +// that work holds a task of its own from the moment it is enqueued. If the task that +// ReadToEnd holds were done before then runs, lazygit would count as idle for a moment +// in between, and an integration test would carry on before the follow-up work is done. +func TestReadToEndHoldsItsTaskUntilThenReturns(t *testing.T) { + noop := func() {} + task := gocui.NewFakeTask() + + manager := NewViewBufferManager( + utils.NewDummyLog(), bytes.NewBuffer(nil), noop, noop, noop, noop, noop, noop, + func() gocui.Task { return task }, + func(f func()) error { f(); return nil }, + ) + + // With no command task serving read requests, ReadToEnd answers right away. + var statusDuringThen gocui.TaskStatus + manager.ReadToEnd(func() { statusDuringThen = task.Status() }) + + assert.Equal(t, gocui.TaskStatusBusy, statusDuringThen) + assert.Equal(t, gocui.TaskStatusDone, task.Status()) +}