1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-15 00:15:32 +02:00

fix mutex deadlock

This commit is contained in:
Jesse Duffield
2020-10-08 08:01:04 +11:00
parent 9011271a01
commit 4c9ec88be5
8 changed files with 149 additions and 152 deletions

View File

@ -77,7 +77,7 @@ func (gui *Gui) handleDiscardOldFileChange(g *gocui.Gui, v *gocui.View) error {
} }
func (gui *Gui) refreshCommitFilesView() error { func (gui *Gui) refreshCommitFilesView() error {
if err := gui.refreshPatchBuildingPanel(-1); err != nil { if err := gui.handleRefreshPatchBuildingPanel(-1); err != nil {
return err return err
} }
@ -179,7 +179,7 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error {
if err := gui.switchContext(gui.Contexts.PatchBuilding.Context); err != nil { if err := gui.switchContext(gui.Contexts.PatchBuilding.Context); err != nil {
return err return err
} }
return gui.refreshPatchBuildingPanel(selectedLineIdx) return gui.handleRefreshPatchBuildingPanel(selectedLineIdx)
} }
if gui.GitCommand.PatchManager.Active() && gui.GitCommand.PatchManager.To != commitFile.Parent { if gui.GitCommand.PatchManager.Active() && gui.GitCommand.PatchManager.To != commitFile.Parent {

View File

@ -185,7 +185,7 @@ func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error
} }
gui.switchContext(gui.Contexts.Staging.Context) gui.switchContext(gui.Contexts.Staging.Context)
return gui.refreshStagingPanel(forceSecondaryFocused, selectedLineIdx) // TODO: check if this is broken, try moving into context code return gui.handleRefreshStagingPanel(forceSecondaryFocused, selectedLineIdx) // TODO: check if this is broken, try moving into context code
} }
func (gui *Gui) handleFilePress() error { func (gui *Gui) handleFilePress() error {

View File

@ -142,7 +142,7 @@ type IListPanelState interface {
// for now the staging panel state, unlike the other panel states, is going to be // for now the staging panel state, unlike the other panel states, is going to be
// non-mutative, so that we don't accidentally end up // non-mutative, so that we don't accidentally end up
// with mismatches of data. We might change this in the future // with mismatches of data. We might change this in the future
type lineByLinePanelState struct { type lBlPanelState struct {
SelectedLineIdx int SelectedLineIdx int
FirstLineIdx int FirstLineIdx int
LastLineIdx int LastLineIdx int
@ -234,7 +234,7 @@ type panelStates struct {
SubCommits *subCommitPanelState SubCommits *subCommitPanelState
Stash *stashPanelState Stash *stashPanelState
Menu *menuPanelState Menu *menuPanelState
LineByLine *lineByLinePanelState LineByLine *lBlPanelState
Merging *mergingPanelState Merging *mergingPanelState
CommitFiles *commitFilesPanelState CommitFiles *commitFilesPanelState
Submodules *submodulePanelState Submodules *submodulePanelState

View File

@ -1112,21 +1112,21 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "main", ViewName: "main",
Contexts: []string{MAIN_STAGING_CONTEXT_KEY}, Contexts: []string{MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.Select), Key: gui.getKey(config.Universal.Select),
Handler: gui.handleToggleStagedSelection, Handler: gui.wrappedHandler(gui.handleToggleStagedSelection),
Description: gui.Tr.StageSelection, Description: gui.Tr.StageSelection,
}, },
{ {
ViewName: "main", ViewName: "main",
Contexts: []string{MAIN_STAGING_CONTEXT_KEY}, Contexts: []string{MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.Remove), Key: gui.getKey(config.Universal.Remove),
Handler: gui.handleResetSelection, Handler: gui.wrappedHandler(gui.handleResetSelection),
Description: gui.Tr.ResetSelection, Description: gui.Tr.ResetSelection,
}, },
{ {
ViewName: "main", ViewName: "main",
Contexts: []string{MAIN_STAGING_CONTEXT_KEY}, Contexts: []string{MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.TogglePanel), Key: gui.getKey(config.Universal.TogglePanel),
Handler: gui.handleTogglePanel, Handler: gui.wrappedHandler(gui.handleTogglePanel),
Description: gui.Tr.TogglePanel, Description: gui.Tr.TogglePanel,
}, },
{ {

View File

@ -24,12 +24,7 @@ const (
// returns whether the patch is empty so caller can escape if necessary // returns whether the patch is empty so caller can escape if necessary
// both diffs should be non-coloured because we'll parse them and colour them here // both diffs should be non-coloured because we'll parse them and colour them here
func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int) (bool, error) { func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int, state *lBlPanelState) (bool, error) {
gui.Mutexes.LineByLinePanelMutex.Lock()
defer gui.Mutexes.LineByLinePanelMutex.Unlock()
state := gui.State.Panels.LineByLine
patchParser, err := patch.NewPatchParser(gui.Log, diff) patchParser, err := patch.NewPatchParser(gui.Log, diff)
if err != nil { if err != nil {
return false, nil return false, nil
@ -66,7 +61,7 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
firstLineIdx, lastLineIdx = selectedLineIdx, selectedLineIdx firstLineIdx, lastLineIdx = selectedLineIdx, selectedLineIdx
} }
gui.State.Panels.LineByLine = &lineByLinePanelState{ state = &lBlPanelState{
PatchParser: patchParser, PatchParser: patchParser,
SelectedLineIdx: selectedLineIdx, SelectedLineIdx: selectedLineIdx,
SelectMode: selectMode, SelectMode: selectMode,
@ -75,12 +70,13 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
Diff: diff, Diff: diff,
SecondaryFocused: secondaryFocused, SecondaryFocused: secondaryFocused,
} }
gui.State.Panels.LineByLine = state
if err := gui.refreshMainViewForLineByLine(); err != nil { if err := gui.refreshMainViewForLineByLine(state); err != nil {
return false, err return false, err
} }
if err := gui.focusSelection(selectMode == HUNK); err != nil { if err := gui.focusSelection(selectMode == HUNK, state); err != nil {
return false, err return false, err
} }
@ -102,35 +98,34 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
} }
func (gui *Gui) handleSelectPrevLine() error { func (gui *Gui) handleSelectPrevLine() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.LBLCycleLine(-1) return gui.LBLCycleLine(-1, state)
}) })
} }
func (gui *Gui) handleSelectNextLine() error { func (gui *Gui) handleSelectNextLine() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.LBLCycleLine(+1) return gui.LBLCycleLine(+1, state)
}) })
} }
func (gui *Gui) handleSelectPrevHunk() error { func (gui *Gui) handleSelectPrevHunk() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, -1) newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, -1)
return gui.selectNewHunk(newHunk) return gui.selectNewHunk(newHunk, state)
}) })
} }
func (gui *Gui) handleSelectNextHunk() error { func (gui *Gui) handleSelectNextHunk() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 1) newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 1)
return gui.selectNewHunk(newHunk) return gui.selectNewHunk(newHunk, state)
}) })
} }
func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk) error { func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk, state *lBlPanelState) error {
state := gui.State.Panels.LineByLine
state.SelectedLineIdx = state.PatchParser.GetNextStageableLineIndex(newHunk.FirstLineIdx) state.SelectedLineIdx = state.PatchParser.GetNextStageableLineIndex(newHunk.FirstLineIdx)
if state.SelectMode == HUNK { if state.SelectMode == HUNK {
state.FirstLineIdx, state.LastLineIdx = newHunk.FirstLineIdx, newHunk.LastLineIdx() state.FirstLineIdx, state.LastLineIdx = newHunk.FirstLineIdx, newHunk.LastLineIdx()
@ -138,27 +133,23 @@ func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk) error {
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
} }
if err := gui.refreshMainViewForLineByLine(); err != nil { if err := gui.refreshMainViewForLineByLine(state); err != nil {
return err return err
} }
return gui.focusSelection(true) return gui.focusSelection(true, state)
} }
func (gui *Gui) LBLCycleLine(change int) error { func (gui *Gui) LBLCycleLine(change int, state *lBlPanelState) error {
state := gui.State.Panels.LineByLine
if state.SelectMode == HUNK { if state.SelectMode == HUNK {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, change) newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, change)
return gui.selectNewHunk(newHunk) return gui.selectNewHunk(newHunk, state)
} }
return gui.LBLSelectLine(state.SelectedLineIdx + change) return gui.LBLSelectLine(state.SelectedLineIdx+change, state)
} }
func (gui *Gui) LBLSelectLine(newSelectedLineIdx int) error { func (gui *Gui) LBLSelectLine(newSelectedLineIdx int, state *lBlPanelState) error {
state := gui.State.Panels.LineByLine
if newSelectedLineIdx < 0 { if newSelectedLineIdx < 0 {
newSelectedLineIdx = 0 newSelectedLineIdx = 0
} else if newSelectedLineIdx > len(state.PatchParser.PatchLines)-1 { } else if newSelectedLineIdx > len(state.PatchParser.PatchLines)-1 {
@ -178,15 +169,15 @@ func (gui *Gui) LBLSelectLine(newSelectedLineIdx int) error {
state.FirstLineIdx = state.SelectedLineIdx state.FirstLineIdx = state.SelectedLineIdx
} }
if err := gui.refreshMainViewForLineByLine(); err != nil { if err := gui.refreshMainViewForLineByLine(state); err != nil {
return err return err
} }
return gui.focusSelection(false) return gui.focusSelection(false, state)
} }
func (gui *Gui) handleLBLMouseDown(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleLBLMouseDown(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if gui.popupPanelFocused() { if gui.popupPanelFocused() {
return nil return nil
} }
@ -197,41 +188,41 @@ func (gui *Gui) handleLBLMouseDown(g *gocui.Gui, v *gocui.View) error {
state.SelectMode = RANGE state.SelectMode = RANGE
return gui.LBLSelectLine(newSelectedLineIdx) return gui.LBLSelectLine(newSelectedLineIdx, state)
}) })
} }
func (gui *Gui) handleMouseDrag(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleMouseDrag(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(*lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if gui.popupPanelFocused() { if gui.popupPanelFocused() {
return nil return nil
} }
return gui.LBLSelectLine(v.SelectedLineIdx()) return gui.LBLSelectLine(v.SelectedLineIdx(), state)
}) })
} }
func (gui *Gui) handleMouseScrollUp(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleMouseScrollUp(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if gui.popupPanelFocused() { if gui.popupPanelFocused() {
return nil return nil
} }
state.SelectMode = LINE state.SelectMode = LINE
return gui.LBLCycleLine(-1) return gui.LBLCycleLine(-1, state)
}) })
} }
func (gui *Gui) handleMouseScrollDown(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleMouseScrollDown(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if gui.popupPanelFocused() { if gui.popupPanelFocused() {
return nil return nil
} }
state.SelectMode = LINE state.SelectMode = LINE
return gui.LBLCycleLine(1) return gui.LBLCycleLine(1, state)
}) })
} }
@ -239,9 +230,7 @@ func (gui *Gui) getSelectedCommitFileName() string {
return gui.State.CommitFiles[gui.State.Panels.CommitFiles.SelectedLineIdx].Name return gui.State.CommitFiles[gui.State.Panels.CommitFiles.SelectedLineIdx].Name
} }
func (gui *Gui) refreshMainViewForLineByLine() error { func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error {
state := gui.State.Panels.LineByLine
var includedLineIndices []int var includedLineIndices []int
// I'd prefer not to have knowledge of contexts using this file but I'm not sure // I'd prefer not to have knowledge of contexts using this file but I'm not sure
// how to get around this // how to get around this
@ -269,9 +258,8 @@ func (gui *Gui) refreshMainViewForLineByLine() error {
// focusSelection works out the best focus for the staging panel given the // focusSelection works out the best focus for the staging panel given the
// selected line and size of the hunk // selected line and size of the hunk
func (gui *Gui) focusSelection(includeCurrentHunk bool) error { func (gui *Gui) focusSelection(includeCurrentHunk bool, state *lBlPanelState) error {
stagingView := gui.getMainView() stagingView := gui.getMainView()
state := gui.State.Panels.LineByLine
_, viewHeight := stagingView.Size() _, viewHeight := stagingView.Size()
bufferHeight := viewHeight - 1 bufferHeight := viewHeight - 1
@ -309,7 +297,7 @@ func (gui *Gui) focusSelection(includeCurrentHunk bool) error {
} }
func (gui *Gui) handleToggleSelectRange() error { func (gui *Gui) handleToggleSelectRange() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if state.SelectMode == RANGE { if state.SelectMode == RANGE {
state.SelectMode = LINE state.SelectMode = LINE
} else { } else {
@ -317,12 +305,12 @@ func (gui *Gui) handleToggleSelectRange() error {
} }
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
return gui.refreshMainViewForLineByLine() return gui.refreshMainViewForLineByLine(state)
}) })
} }
func (gui *Gui) handleToggleSelectHunk() error { func (gui *Gui) handleToggleSelectHunk() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if state.SelectMode == HUNK { if state.SelectMode == HUNK {
state.SelectMode = LINE state.SelectMode = LINE
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
@ -332,23 +320,20 @@ func (gui *Gui) handleToggleSelectHunk() error {
state.FirstLineIdx, state.LastLineIdx = selectedHunk.FirstLineIdx, selectedHunk.LastLineIdx() state.FirstLineIdx, state.LastLineIdx = selectedHunk.FirstLineIdx, selectedHunk.LastLineIdx()
} }
if err := gui.refreshMainViewForLineByLine(); err != nil { if err := gui.refreshMainViewForLineByLine(state); err != nil {
return err return err
} }
return gui.focusSelection(state.SelectMode == HUNK) return gui.focusSelection(state.SelectMode == HUNK, state)
}) })
} }
func (gui *Gui) escapeLineByLinePanel() { func (gui *Gui) escapeLineByLinePanel() {
_ = gui.withLBLActiveCheck(func(*lineByLinePanelState) error {
gui.State.Panels.LineByLine = nil gui.State.Panels.LineByLine = nil
return nil
})
} }
func (gui *Gui) handleOpenFileAtLine() error { func (gui *Gui) handleOpenFileAtLine() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
// again, would be good to use inheritance here (or maybe even composition) // again, would be good to use inheritance here (or maybe even composition)
var filename string var filename string
switch gui.State.MainContext { switch gui.State.MainContext {
@ -377,47 +362,48 @@ func (gui *Gui) handleOpenFileAtLine() error {
} }
func (gui *Gui) handleLineByLineNextPage() error { func (gui *Gui) handleLineByLineNextPage() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newSelectedLineIdx := state.SelectedLineIdx + gui.pageDelta(gui.getMainView()) newSelectedLineIdx := state.SelectedLineIdx + gui.pageDelta(gui.getMainView())
return gui.lineByLineNavigateTo(newSelectedLineIdx) return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
}) })
} }
func (gui *Gui) handleLineByLinePrevPage() error { func (gui *Gui) handleLineByLinePrevPage() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newSelectedLineIdx := state.SelectedLineIdx - gui.pageDelta(gui.getMainView()) newSelectedLineIdx := state.SelectedLineIdx - gui.pageDelta(gui.getMainView())
return gui.lineByLineNavigateTo(newSelectedLineIdx) return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
}) })
} }
func (gui *Gui) handleLineByLineGotoBottom() error { func (gui *Gui) handleLineByLineGotoBottom() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newSelectedLineIdx := len(state.PatchParser.PatchLines) - 1 newSelectedLineIdx := len(state.PatchParser.PatchLines) - 1
return gui.lineByLineNavigateTo(newSelectedLineIdx) return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
}) })
} }
func (gui *Gui) handleLineByLineGotoTop() error { func (gui *Gui) handleLineByLineGotoTop() error {
return gui.lineByLineNavigateTo(0) return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
} return gui.lineByLineNavigateTo(0, state)
func (gui *Gui) handlelineByLineNavigateTo(selectedLineIdx int) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
return gui.lineByLineNavigateTo(selectedLineIdx)
}) })
} }
func (gui *Gui) lineByLineNavigateTo(selectedLineIdx int) error { func (gui *Gui) handlelineByLineNavigateTo(selectedLineIdx int) error {
state := gui.State.Panels.LineByLine return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
state.SelectMode = LINE return gui.lineByLineNavigateTo(selectedLineIdx, state)
})
return gui.LBLSelectLine(selectedLineIdx)
} }
func (gui *Gui) withLBLActiveCheck(f func(*lineByLinePanelState) error) error { func (gui *Gui) lineByLineNavigateTo(selectedLineIdx int, state *lBlPanelState) error {
state.SelectMode = LINE
return gui.LBLSelectLine(selectedLineIdx, state)
}
func (gui *Gui) withLBLActiveCheck(f func(*lBlPanelState) error) error {
gui.Mutexes.LineByLinePanelMutex.Lock() gui.Mutexes.LineByLinePanelMutex.Lock()
defer gui.Mutexes.LineByLinePanelMutex.Unlock() defer gui.Mutexes.LineByLinePanelMutex.Unlock()

View File

@ -17,7 +17,7 @@ func (gui *Gui) getFromAndReverseArgsForDiff(to string) (string, bool) {
return from, reverse return from, reverse
} }
func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error { func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int, state *lBlPanelState) error {
if !gui.GitCommand.PatchManager.Active() { if !gui.GitCommand.PatchManager.Active() {
return gui.handleEscapePatchBuildingPanel() return gui.handleEscapePatchBuildingPanel()
} }
@ -45,7 +45,7 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error {
return err return err
} }
empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, false, selectedLineIdx) empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, false, selectedLineIdx, state)
if err != nil { if err != nil {
return err return err
} }
@ -57,8 +57,15 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error {
return nil return nil
} }
func (gui *Gui) handleRefreshPatchBuildingPanel(selectedLineIdx int) error {
gui.Mutexes.LineByLinePanelMutex.Lock()
defer gui.Mutexes.LineByLinePanelMutex.Unlock()
return gui.refreshPatchBuildingPanel(selectedLineIdx, gui.State.Panels.LineByLine)
}
func (gui *Gui) handleToggleSelectionForPatch() error { func (gui *Gui) handleToggleSelectionForPatch() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { err := gui.withLBLActiveCheck(func(state *lBlPanelState) error {
toggleFunc := gui.GitCommand.PatchManager.AddFileLineRange toggleFunc := gui.GitCommand.PatchManager.AddFileLineRange
filename := gui.getSelectedCommitFileName() filename := gui.getSelectedCommitFileName()
includedLineIndices, err := gui.GitCommand.PatchManager.GetFileIncLineIndices(filename) includedLineIndices, err := gui.GitCommand.PatchManager.GetFileIncLineIndices(filename)
@ -81,16 +88,18 @@ func (gui *Gui) handleToggleSelectionForPatch() error {
gui.Log.Error(err) gui.Log.Error(err)
} }
return nil
})
if err != nil {
return err
}
if err := gui.refreshCommitFilesView(); err != nil { if err := gui.refreshCommitFilesView(); err != nil {
return err return err
} }
if err := gui.refreshPatchBuildingPanel(-1); err != nil {
return err
}
return nil return nil
})
} }
func (gui *Gui) handleEscapePatchBuildingPanel() error { func (gui *Gui) handleEscapePatchBuildingPanel() error {

View File

@ -7,17 +7,11 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/patch" "github.com/jesseduffield/lazygit/pkg/commands/patch"
) )
func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx int) error { func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx int, state *lBlPanelState) error {
gui.splitMainPanel(true) gui.splitMainPanel(true)
state := gui.State.Panels.LineByLine
file := gui.getSelectedFile() file := gui.getSelectedFile()
if file == nil { if file == nil || (!file.HasUnstagedChanges && !file.HasStagedChanges) {
return gui.handleStagingEscape()
}
if !file.HasUnstagedChanges && !file.HasStagedChanges {
return gui.handleStagingEscape() return gui.handleStagingEscape()
} }
@ -56,7 +50,7 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
diff, secondaryDiff = secondaryDiff, diff diff, secondaryDiff = secondaryDiff, diff
} }
empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, secondaryFocused, selectedLineIdx) empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, secondaryFocused, selectedLineIdx, state)
if err != nil { if err != nil {
return err return err
} }
@ -69,17 +63,24 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
} }
func (gui *Gui) handleTogglePanelClick(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleTogglePanelClick(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
state.SecondaryFocused = !state.SecondaryFocused state.SecondaryFocused = !state.SecondaryFocused
return gui.refreshStagingPanel(false, v.SelectedLineIdx()) return gui.refreshStagingPanel(false, v.SelectedLineIdx(), state)
}) })
} }
func (gui *Gui) handleTogglePanel(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleRefreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx int) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { gui.Mutexes.LineByLinePanelMutex.Lock()
defer gui.Mutexes.LineByLinePanelMutex.Unlock()
return gui.refreshStagingPanel(forceSecondaryFocused, selectedLineIdx, gui.State.Panels.LineByLine)
}
func (gui *Gui) handleTogglePanel() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
state.SecondaryFocused = !state.SecondaryFocused state.SecondaryFocused = !state.SecondaryFocused
return gui.refreshStagingPanel(false, -1) return gui.refreshStagingPanel(false, -1, state)
}) })
} }
@ -89,17 +90,17 @@ func (gui *Gui) handleStagingEscape() error {
return gui.switchContext(gui.Contexts.Files.Context) return gui.switchContext(gui.Contexts.Files.Context)
} }
func (gui *Gui) handleToggleStagedSelection(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleToggleStagedSelection() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.applySelection(state.SecondaryFocused) return gui.applySelection(state.SecondaryFocused, state)
}) })
} }
func (gui *Gui) handleResetSelection(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleResetSelection() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if state.SecondaryFocused { if state.SecondaryFocused {
// for backwards compatibility // for backwards compatibility
return gui.applySelection(true) return gui.applySelection(true, state)
} }
if !gui.Config.GetUserConfig().Gui.SkipUnstageLineWarning { if !gui.Config.GetUserConfig().Gui.SkipUnstageLineWarning {
@ -108,24 +109,25 @@ func (gui *Gui) handleResetSelection(g *gocui.Gui, v *gocui.View) error {
prompt: gui.Tr.UnstageLinesPrompt, prompt: gui.Tr.UnstageLinesPrompt,
handlersManageFocus: true, handlersManageFocus: true,
handleConfirm: func() error { handleConfirm: func() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if err := gui.switchContext(gui.Contexts.Staging.Context); err != nil { if err := gui.switchContext(gui.Contexts.Staging.Context); err != nil {
return err return err
} }
return gui.applySelection(true) return gui.applySelection(true, state)
})
}, },
handleClose: func() error { handleClose: func() error {
return gui.switchContext(gui.Contexts.Staging.Context) return gui.switchContext(gui.Contexts.Staging.Context)
}, },
}) })
} else { } else {
return gui.applySelection(true) return gui.applySelection(true, state)
} }
}) })
} }
func (gui *Gui) applySelection(reverse bool) error { func (gui *Gui) applySelection(reverse bool, state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
file := gui.getSelectedFile() file := gui.getSelectedFile()
if file == nil { if file == nil {
return nil return nil
@ -155,9 +157,8 @@ func (gui *Gui) applySelection(reverse bool) error {
if err := gui.refreshSidePanels(refreshOptions{scope: []int{FILES}}); err != nil { if err := gui.refreshSidePanels(refreshOptions{scope: []int{FILES}}); err != nil {
return err return err
} }
if err := gui.refreshStagingPanel(false, -1); err != nil { if err := gui.refreshStagingPanel(false, -1, state); err != nil {
return err return err
} }
return nil return nil
})
} }

View File

@ -405,7 +405,8 @@ func (gui *Gui) wrappedHandler(f func() error) func(g *gocui.Gui, v *gocui.View)
// secondaryViewFocused tells us whether it appears that the secondary view is focused. The view is actually never focused for real: we just swap the main and secondary views and then you're still focused on the main view so that we can give you access to all its keybindings for free. I will probably regret this design decision soon enough. // secondaryViewFocused tells us whether it appears that the secondary view is focused. The view is actually never focused for real: we just swap the main and secondary views and then you're still focused on the main view so that we can give you access to all its keybindings for free. I will probably regret this design decision soon enough.
func (gui *Gui) secondaryViewFocused() bool { func (gui *Gui) secondaryViewFocused() bool {
return gui.State.Panels.LineByLine != nil && gui.State.Panels.LineByLine.SecondaryFocused state := gui.State.Panels.LineByLine
return state != nil && state.SecondaryFocused
} }
func (gui *Gui) clearEditorView(v *gocui.View) { func (gui *Gui) clearEditorView(v *gocui.View) {