summaryrefslogtreecommitdiffstats
path: root/pkg/gui/line_by_line_panel.go
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2020-10-08 08:01:04 +1100
committerJesse Duffield <jessedduffield@gmail.com>2020-10-10 00:23:01 +1100
commit4c9ec88be57ed75c198d19020374bae0365b6e00 (patch)
tree8b69a8fd7ab64009aa028c61bd9a8a109a721efd /pkg/gui/line_by_line_panel.go
parent9011271a014025c514adf72b1d1ee69fbc7f3373 (diff)
fix mutex deadlock
Diffstat (limited to 'pkg/gui/line_by_line_panel.go')
-rw-r--r--pkg/gui/line_by_line_panel.go120
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()