Skip to content

Commit 6c69ded

Browse files
committed
Pause background refreshes while driving a git operation
Several commands (rewording or amending an earlier commit, custom patch operations, etc.) are implemented by starting an interactive rebase that stops at a commit, amending it, and continuing. When no conflict occurs, the user isn't meant to notice a rebase happened at all. But a background file refresh can fire while the rebase is mid-flight and render a dirty working copy of whatever the behind-the-scenes rebase is doing (e.g. applying a custom patch). To fix this, we pause the background routines for the duration of any waiting-status operation — exactly the window in which lazygit is driving the git operation itself and will refresh once at the end. The boundary is also right for the conflict case: when a rebase stops on a conflict the operation returns, the pause releases, and background refreshes resume for the interactive resolution that follows.
1 parent d2995aa commit 6c69ded

4 files changed

Lines changed: 26 additions & 0 deletions

File tree

pkg/gui/controllers/helpers/app_status_helper.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,22 @@ func (self *AppStatusHelper) WithWaitingStatus(message string, f func(gocui.Task
6666
}
6767

6868
func (self *AppStatusHelper) WithWaitingStatusImpl(message string, f func(gocui.Task) error, task gocui.Task) error {
69+
// A waiting status means lazygit is driving a git operation itself (often
70+
// one that internally runs a rebase and continues it). Pause the background
71+
// routines for its duration so they don't refresh from an intermediate
72+
// state and reveal, say, the half-finished history of a reword.
73+
self.c.PauseBackgroundRefreshes(true)
74+
defer self.c.PauseBackgroundRefreshes(false)
75+
6976
return self.statusMgr().WithWaitingStatus(message, self.renderAppStatus, func(waitingStatusHandle *status.WaitingStatusHandle) error {
7077
return f(appStatusHelperTask{task, waitingStatusHandle})
7178
})
7279
}
7380

7481
func (self *AppStatusHelper) WithWaitingStatusSync(message string, f func() error) error {
82+
self.c.PauseBackgroundRefreshes(true)
83+
defer self.c.PauseBackgroundRefreshes(false)
84+
7585
return self.statusMgr().WithWaitingStatus(message, func() {}, func(*status.WaitingStatusHandle) error {
7686
stop := make(chan struct{})
7787
defer func() { close(stop) }()

pkg/gui/controllers/helpers/inline_status_helper.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ func (self *InlineStatusHelper) WithInlineStatus(opts InlineStatusOpts, f func(g
6868
visible := view.Visible && self.windowHelper.TopViewInWindow(context.GetWindowName(), false) == view
6969
if visible && context.IsItemVisible(opts.Item) {
7070
self.c.OnWorker(func(task gocui.Task) error {
71+
// An inline status is just a waiting status rendered on the item
72+
// rather than in the bottom line, so it gets the same treatment:
73+
// pause the background routines while we drive the operation. (The
74+
// off-screen branch below goes through WithWaitingStatus, which
75+
// already does this.)
76+
self.c.PauseBackgroundRefreshes(true)
77+
defer self.c.PauseBackgroundRefreshes(false)
78+
7179
self.start(opts)
7280
defer self.stop(opts)
7381

pkg/gui/gui_common.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ func (self *guiCommon) Resume() error {
5050
return self.gui.resume()
5151
}
5252

53+
func (self *guiCommon) PauseBackgroundRefreshes(pause bool) {
54+
self.gui.BackgroundRoutineMgr.PauseBackgroundRefreshes(pause)
55+
}
56+
5357
func (self *guiCommon) Context() types.IContextMgr {
5458
return self.gui.State.ContextMgr
5559
}

pkg/gui/types/common.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ type IGuiCommon interface {
5959
Suspend() error
6060
Resume() error
6161

62+
// Pause or resume the background routines. Calls nest, so every pause must be balanced
63+
// by a resume.
64+
PauseBackgroundRefreshes(pause bool)
65+
6266
Context() IContextMgr
6367
ContextForKey(key ContextKey) Context
6468

0 commit comments

Comments
 (0)