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 | |
parent | 9011271a014025c514adf72b1d1ee69fbc7f3373 (diff) |
fix mutex deadlock
-rw-r--r-- | pkg/gui/commit_files_panel.go | 4 | ||||
-rw-r--r-- | pkg/gui/files_panel.go | 2 | ||||
-rw-r--r-- | pkg/gui/gui.go | 4 | ||||
-rw-r--r-- | pkg/gui/keybindings.go | 6 | ||||
-rw-r--r-- | pkg/gui/line_by_line_panel.go | 120 | ||||
-rw-r--r-- | pkg/gui/patch_building_panel.go | 31 | ||||
-rw-r--r-- | pkg/gui/staging_panel.go | 113 | ||||
-rw-r--r-- | pkg/gui/view_helpers.go | 3 |
8 files changed, 140 insertions, 143 deletions
diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index 6a5109f08..c560e667b 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -77,7 +77,7 @@ func (gui *Gui) handleDiscardOldFileChange(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) refreshCommitFilesView() error { - if err := gui.refreshPatchBuildingPanel(-1); err != nil { + if err := gui.handleRefreshPatchBuildingPanel(-1); err != nil { return err } @@ -179,7 +179,7 @@ func (gui *Gui) enterCommitFile(selectedLineIdx int) error { if err := gui.switchContext(gui.Contexts.PatchBuilding.Context); err != nil { return err } - return gui.refreshPatchBuildingPanel(selectedLineIdx) + return gui.handleRefreshPatchBuildingPanel(selectedLineIdx) } if gui.GitCommand.PatchManager.Active() && gui.GitCommand.PatchManager.To != commitFile.Parent { diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 0f498a9ac..f9423eb01 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -185,7 +185,7 @@ func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error } 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 { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index d928413e7..f0e36daf5 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -142,7 +142,7 @@ type IListPanelState interface { // 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 // with mismatches of data. We might change this in the future -type lineByLinePanelState struct { +type lBlPanelState struct { SelectedLineIdx int FirstLineIdx int LastLineIdx int @@ -234,7 +234,7 @@ type panelStates struct { SubCommits *subCommitPanelState Stash *stashPanelState Menu *menuPanelState - LineByLine *lineByLinePanelState + LineByLine *lBlPanelState Merging *mergingPanelState CommitFiles *commitFilesPanelState Submodules *submodulePanelState diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index b9ada7628..2093bfca7 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -1112,21 +1112,21 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { ViewName: "main", Contexts: []string{MAIN_STAGING_CONTEXT_KEY}, Key: gui.getKey(config.Universal.Select), - Handler: gui.handleToggleStagedSelection, + Handler: gui.wrappedHandler(gui.handleToggleStagedSelection), Description: gui.Tr.StageSelection, }, { ViewName: "main", Contexts: []string{MAIN_STAGING_CONTEXT_KEY}, Key: gui.getKey(config.Universal.Remove), - Handler: gui.handleResetSelection, + Handler: gui.wrappedHandler(gui.handleResetSelection), Description: gui.Tr.ResetSelection, }, { ViewName: "main", Contexts: []string{MAIN_STAGING_CONTEXT_KEY}, Key: gui.getKey(config.Universal.TogglePanel), - Handler: gui.handleTogglePanel, + Handler: gui.wrappedHandler(gui.handleTogglePanel), Description: gui.Tr.TogglePanel, }, { 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() diff --git a/pkg/gui/patch_building_panel.go b/pkg/gui/patch_building_panel.go index 3f6a71c95..6ae41de6e 100644 --- a/pkg/gui/patch_building_panel.go +++ b/pkg/gui/patch_building_panel.go @@ -17,7 +17,7 @@ func (gui *Gui) getFromAndReverseArgsForDiff(to string) (string, bool) { return from, reverse } -func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error { +func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int, state *lBlPanelState) error { if !gui.GitCommand.PatchManager.Active() { return gui.handleEscapePatchBuildingPanel() } @@ -45,7 +45,7 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error { return err } - empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, false, selectedLineIdx) + empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, false, selectedLineIdx, state) if err != nil { return err } @@ -57,8 +57,15 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int) error { 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 { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { + err := gui.withLBLActiveCheck(func(state *lBlPanelState) error { toggleFunc := gui.GitCommand.PatchManager.AddFileLineRange filename := gui.getSelectedCommitFileName() includedLineIndices, err := gui.GitCommand.PatchManager.GetFileIncLineIndices(filename) @@ -81,16 +88,18 @@ func (gui *Gui) handleToggleSelectionForPatch() error { gui.Log.Error(err) } - if err := gui.refreshCommitFilesView(); err != nil { - return err - } - - if err := gui.refreshPatchBuildingPanel(-1); err != nil { - return err - } - return nil }) + + if err != nil { + return err + } + + if err := gui.refreshCommitFilesView(); err != nil { + return err + } + + return nil } func (gui *Gui) handleEscapePatchBuildingPanel() error { diff --git a/pkg/gui/staging_panel.go b/pkg/gui/staging_panel.go index 68c7c8391..66b3006fc 100644 --- a/pkg/gui/staging_panel.go +++ b/pkg/gui/staging_panel.go @@ -7,17 +7,11 @@ import ( "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) - state := gui.State.Panels.LineByLine - file := gui.getSelectedFile() - if file == nil { - return gui.handleStagingEscape() - } - - if !file.HasUnstagedChanges && !file.HasStagedChanges { + if file == nil || (!file.HasUnstagedChanges && !file.HasStagedChanges) { return gui.handleStagingEscape() } @@ -56,7 +50,7 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx diff, secondaryDiff = secondaryDiff, diff } - empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, secondaryFocused, selectedLineIdx) + empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, secondaryFocused, selectedLineIdx, state) if err != nil { return err } @@ -69,17 +63,24 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx } 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 - return gui.refreshStagingPanel(false, v.SelectedLineIdx()) + return gui.refreshStagingPanel(false, v.SelectedLineIdx(), state) }) } -func (gui *Gui) handleTogglePanel(g *gocui.Gui, v *gocui.View) error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { +func (gui *Gui) handleRefreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx int) 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 - 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) } -func (gui *Gui) handleToggleStagedSelection(g *gocui.Gui, v *gocui.View) error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { - return gui.applySelection(state.SecondaryFocused) +func (gui *Gui) handleToggleStagedSelection() error { + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { + return gui.applySelection(state.SecondaryFocused, state) }) } -func (gui *Gui) handleResetSelection(g *gocui.Gui, v *gocui.View) error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { +func (gui *Gui) handleResetSelection() error { + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { if state.SecondaryFocused { // for backwards compatibility - return gui.applySelection(true) + return gui.applySelection(true, state) } if !gui.Config.GetUserConfig().Gui.SkipUnstageLineWarning { @@ -108,56 +109,56 @@ func (gui *Gui) handleResetSelection(g *gocui.Gui, v *gocui.View) error { prompt: gui.Tr.UnstageLinesPrompt, handlersManageFocus: true, handleConfirm: func() error { - if err := gui.switchContext(gui.Contexts.Staging.Context); err != nil { - return err - } + return gui.withLBLActiveCheck(func(state *lBlPanelState) error { + if err := gui.switchContext(gui.Contexts.Staging.Context); err != nil { + return err + } - return gui.applySelection(true) + return gui.applySelection(true, state) + }) }, handleClose: func() error { return gui.switchContext(gui.Contexts.Staging.Context) }, }) } else { - return gui.applySelection(true) + return gui.applySelection(true, state) } }) } -func (gui *Gui) applySelection(reverse bool) error { - return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error { - file := gui.getSelectedFile() - if file == nil { - return nil - } +func (gui *Gui) applySelection(reverse bool, state *lBlPanelState) error { + file := gui.getSelectedFile() + if file == nil { + return nil + } - patch := patch.ModifiedPatchForRange(gui.Log, file.Name, state.Diff, state.FirstLineIdx, state.LastLineIdx, reverse, false) + patch := patch.ModifiedPatchForRange(gui.Log, file.Name, state.Diff, state.FirstLineIdx, state.LastLineIdx, reverse, false) - if patch == "" { - return nil - } + if patch == "" { + return nil + } - // apply the patch then refresh this panel - // create a new temp file with the patch, then call git apply with that patch - applyFlags := []string{} - if !reverse || state.SecondaryFocused { - applyFlags = append(applyFlags, "cached") - } - err := gui.GitCommand.ApplyPatch(patch, applyFlags...) - if err != nil { - return gui.surfaceError(err) - } + // apply the patch then refresh this panel + // create a new temp file with the patch, then call git apply with that patch + applyFlags := []string{} + if !reverse || state.SecondaryFocused { + applyFlags = append(applyFlags, "cached") + } + err := gui.GitCommand.ApplyPatch(patch, applyFlags...) + if err != nil { + return gui.surfaceError(err) + } - if state.SelectMode == RANGE { - state.SelectMode = LINE - } + if state.SelectMode == RANGE { + state.SelectMode = LINE + } - if err := gui.refreshSidePanels(refreshOptions{scope: []int{FILES}}); err != nil { - return err - } - if err := gui.refreshStagingPanel(false, -1); err != nil { - return err - } - return nil - }) + if err := gui.refreshSidePanels(refreshOptions{scope: []int{FILES}}); err != nil { + return err + } + if err := gui.refreshStagingPanel(false, -1, state); err != nil { + return err + } + return nil } diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 64faa5940..bc4c5bada 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -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. 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) { |