diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2020-10-08 08:01:04 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2020-10-10 00:23:01 +1100 |
commit | 4c9ec88be57ed75c198d19020374bae0365b6e00 (patch) | |
tree | 8b69a8fd7ab64009aa028c61bd9a8a109a721efd /pkg/gui/line_by_line_panel.go | |
parent | 9011271a014025c514adf72b1d1ee69fbc7f3373 (diff) |
fix mutex deadlock
Diffstat (limited to 'pkg/gui/line_by_line_panel.go')
-rw-r--r-- | pkg/gui/line_by_line_panel.go | 120 |
1 files changed, 53 insertions, 67 deletions
diff --git a/pkg/gui/line_by_line_panel.go b/pkg/gui/line_by_line_panel.go index 96c29bc6d..e21fef4ca 100644 --- a/pkg/gui/line_by_line_panel.go +++ b/pkg/gui/line_by_line_panel.go @@ -24,12 +24,7 @@ const ( // 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 -func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int) (bool, error) { - gui.Mutexes.LineByLinePanelMutex.Lock() - defer gui.Mutexes.LineByLinePanelMutex.Unlock() - - state := gui.State.Panels.LineByLine - +func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int, state *lBlPanelState) (bool, error) { patchParser, err := patch.NewPatchParser(gui.Log, diff) if err != nil { return false, nil @@ -66,7 +61,7 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second firstLineIdx, lastLineIdx = selectedLineIdx, selectedLineIdx } - gui.State.Panels.LineByLine = &lineByLinePanelState{ + state = &lBlPanelState{ PatchParser: patchParser, SelectedLineIdx: selectedLineIdx, SelectMode: selectMode, @@ -75,12 +70,13 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second Diff: diff, SecondaryFocused: secondaryFocused, } + gui.State.Panels.LineByLine = state - if err := gui.refreshMainViewForLineByLine(); err != nil { + if err := gui.refreshMainViewForLineByLine(state); err != nil { return false, err } - if err := gui.focusSelection(selectMode == HUNK); err != nil { + if err := gui.focusSelection(selectMode == HUNK, state); err != nil { return false, err } @@ -102,35 +98,34 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second } func (gui *Gui) handleSelectPrevLine() error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { - return gui.LBLCycleLine(-1) + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { + return gui.LBLCycleLine(-1, state) }) } func (gui *Gui) handleSelectNextLine() error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { - return gui.LBLCycleLine(+1) + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { + return gui.LBLCycleLine(+1, state) }) } 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) - return gui.selectNewHunk(newHunk) + return gui.selectNewHunk(newHunk, state) }) } 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) - return gui.selectNewHunk(newHunk) + return gui.selectNewHunk(newHunk, state) }) } -func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk) error { - state := gui.State.Panels.LineByLine +func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk, state *lBlPanelState) error { state.SelectedLineIdx = state.PatchParser.GetNextStageableLineIndex(newHunk.FirstLineIdx) if state.SelectMode == HUNK { 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 } - if err := gui.refreshMainViewForLineByLine(); err != nil { + if err := gui.refreshMainViewForLineByLine(state); err != nil { return err } - return gui.focusSelection(true) + return gui.focusSelection(true, state) } -func (gui *Gui) LBLCycleLine(change int) error { - state := gui.State.Panels.LineByLine - +func (gui *Gui) LBLCycleLine(change int, state *lBlPanelState) error { if state.SelectMode == HUNK { 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 { - state := gui.State.Panels.LineByLine - +func (gui *Gui) LBLSelectLine(newSelectedLineIdx int, state *lBlPanelState) error { if newSelectedLineIdx < 0 { newSelectedLineIdx = 0 } else if newSelectedLineIdx > len(state.PatchParser.PatchLines)-1 { @@ -178,15 +169,15 @@ func (gui *Gui) LBLSelectLine(newSelectedLineIdx int) error { state.FirstLineIdx = state.SelectedLineIdx } - if err := gui.refreshMainViewForLineByLine(); err != nil { + if err := gui.refreshMainViewForLineByLine(state); err != nil { return err } - return gui.focusSelection(false) + return gui.focusSelection(false, state) } 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() { return nil } @@ -197,41 +188,41 @@ func (gui *Gui) handleLBLMouseDown(g *gocui.Gui, v *gocui.View) error { state.SelectMode = RANGE - return gui.LBLSelectLine(newSelectedLineIdx) + return gui.LBLSelectLine(newSelectedLineIdx, state) }) } 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() { return nil } - return gui.LBLSelectLine(v.SelectedLineIdx()) + return gui.LBLSelectLine(v.SelectedLineIdx(), state) }) } 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() { return nil } state.SelectMode = LINE - return gui.LBLCycleLine(-1) + return gui.LBLCycleLine(-1, state) }) } 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() { return nil } 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 } -func (gui *Gui) refreshMainViewForLineByLine() error { - state := gui.State.Panels.LineByLine - +func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error { var includedLineIndices []int // I'd prefer not to have knowledge of contexts using this file but I'm not sure // 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 // 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() - state := gui.State.Panels.LineByLine _, viewHeight := stagingView.Size() bufferHeight := viewHeight - 1 @@ -309,7 +297,7 @@ func (gui *Gui) focusSelection(includeCurrentHunk bool) error { } func (gui *Gui) handleToggleSelectRange() error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { if state.SelectMode == RANGE { state.SelectMode = LINE } else { @@ -317,12 +305,12 @@ func (gui *Gui) handleToggleSelectRange() error { } state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx - return gui.refreshMainViewForLineByLine() + return gui.refreshMainViewForLineByLine(state) }) } func (gui *Gui) handleToggleSelectHunk() error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { if state.SelectMode == HUNK { state.SelectMode = LINE 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() } - if err := gui.refreshMainViewForLineByLine(); err != nil { + if err := gui.refreshMainViewForLineByLine(state); err != nil { return err } - return gui.focusSelection(state.SelectMode == HUNK) + return gui.focusSelection(state.SelectMode == HUNK, state) }) } func (gui *Gui) escapeLineByLinePanel() { - _ = gui.withLBLActiveCheck(func(*lineByLinePanelState) error { - gui.State.Panels.LineByLine = nil - return nil - }) + gui.State.Panels.LineByLine = nil } 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) var filename string switch gui.State.MainContext { @@ -377,47 +362,48 @@ func (gui *Gui) handleOpenFileAtLine() 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()) - return gui.lineByLineNavigateTo(newSelectedLineIdx) + return gui.lineByLineNavigateTo(newSelectedLineIdx, state) }) } 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()) - return gui.lineByLineNavigateTo(newSelectedLineIdx) + return gui.lineByLineNavigateTo(newSelectedLineIdx, state) }) } 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 - return gui.lineByLineNavigateTo(newSelectedLineIdx) + return gui.lineByLineNavigateTo(newSelectedLineIdx, state) }) } 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) + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { + return gui.lineByLineNavigateTo(selectedLineIdx, state) }) } -func (gui *Gui) lineByLineNavigateTo(selectedLineIdx int) error { - state := gui.State.Panels.LineByLine +func (gui *Gui) lineByLineNavigateTo(selectedLineIdx int, state *lBlPanelState) error { state.SelectMode = LINE - return gui.LBLSelectLine(selectedLineIdx) + return gui.LBLSelectLine(selectedLineIdx, state) } -func (gui *Gui) withLBLActiveCheck(f func(*lineByLinePanelState) error) error { +func (gui *Gui) withLBLActiveCheck(f func(*lBlPanelState) error) error { gui.Mutexes.LineByLinePanelMutex.Lock() defer gui.Mutexes.LineByLinePanelMutex.Unlock() |