diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2018-12-08 16:54:54 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2018-12-11 22:02:12 +1100 |
commit | 9489a9447396b30bca86ea3df201cacfdffdb1a9 (patch) | |
tree | ae251c28096f2bde6b1647603852782c58329d4c /pkg/gui/merge_panel.go | |
parent | e0ff46fe53503d74fc63c90fc5ddc4d9468b60d5 (diff) |
Make merge panel its own panel
Diffstat (limited to 'pkg/gui/merge_panel.go')
-rw-r--r-- | pkg/gui/merge_panel.go | 137 |
1 files changed, 83 insertions, 54 deletions
diff --git a/pkg/gui/merge_panel.go b/pkg/gui/merge_panel.go index 404266d29..07ba55894 100644 --- a/pkg/gui/merge_panel.go +++ b/pkg/gui/merge_panel.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/fatih/color" + "github.com/golang-collections/collections/stack" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/utils" @@ -21,6 +22,7 @@ func (gui *Gui) findConflicts(content string) ([]commands.Conflict, error) { var newConflict commands.Conflict for i, line := range utils.SplitLines(content) { trimmedLine := strings.TrimPrefix(line, "++") + gui.Log.Info(trimmedLine) if trimmedLine == "<<<<<<< HEAD" || trimmedLine == "<<<<<<< MERGE_HEAD" || trimmedLine == "<<<<<<< Updated upstream" { newConflict = commands.Conflict{Start: i} } else if trimmedLine == "=======" { @@ -65,28 +67,28 @@ func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflic } func (gui *Gui) handleSelectTop(g *gocui.Gui, v *gocui.View) error { - gui.State.ConflictTop = true + gui.State.Panels.Merging.ConflictTop = true return gui.refreshMergePanel(g) } func (gui *Gui) handleSelectBottom(g *gocui.Gui, v *gocui.View) error { - gui.State.ConflictTop = false + gui.State.Panels.Merging.ConflictTop = false return gui.refreshMergePanel(g) } func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error { - if gui.State.ConflictIndex >= len(gui.State.Conflicts)-1 { + if gui.State.Panels.Merging.ConflictIndex >= len(gui.State.Panels.Merging.Conflicts)-1 { return nil } - gui.State.ConflictIndex++ + gui.State.Panels.Merging.ConflictIndex++ return gui.refreshMergePanel(g) } func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error { - if gui.State.ConflictIndex <= 0 { + if gui.State.Panels.Merging.ConflictIndex <= 0 { return nil } - gui.State.ConflictIndex-- + gui.State.Panels.Merging.ConflictIndex-- return gui.refreshMergePanel(g) } @@ -134,15 +136,15 @@ func (gui *Gui) pushFileSnapshot(g *gocui.Gui) error { if err != nil { return err } - gui.State.EditHistory.Push(content) + gui.State.Panels.Merging.EditHistory.Push(content) return nil } func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error { - if gui.State.EditHistory.Len() == 0 { + if gui.State.Panels.Merging.EditHistory.Len() == 0 { return nil } - prevContent := gui.State.EditHistory.Pop().(string) + prevContent := gui.State.Panels.Merging.EditHistory.Pop().(string) gitFile, err := gui.getSelectedFile(g) if err != nil { return err @@ -152,22 +154,29 @@ func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error { - conflict := gui.State.Conflicts[gui.State.ConflictIndex] + conflict := gui.State.Panels.Merging.Conflicts[gui.State.Panels.Merging.ConflictIndex] gui.pushFileSnapshot(g) pick := "bottom" - if gui.State.ConflictTop { + if gui.State.Panels.Merging.ConflictTop { pick = "top" } err := gui.resolveConflict(g, conflict, pick) if err != nil { panic(err) } + + // if that was the last conflict, finish the merge for this file + if len(gui.State.Panels.Merging.Conflicts) == 1 { + if err := gui.handleCompleteMerge(); err != nil { + return err + } + } gui.refreshMergePanel(g) return nil } func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error { - conflict := gui.State.Conflicts[gui.State.ConflictIndex] + conflict := gui.State.Panels.Merging.Conflicts[gui.State.Panels.Merging.ConflictIndex] gui.pushFileSnapshot(g) err := gui.resolveConflict(g, conflict, "both") if err != nil { @@ -177,6 +186,7 @@ func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) refreshMergePanel(g *gocui.Gui) error { + panelState := gui.State.Panels.Merging cat, err := gui.catSelectedFile(g) if err != nil { return err @@ -184,47 +194,56 @@ func (gui *Gui) refreshMergePanel(g *gocui.Gui) error { if cat == "" { return nil } - gui.State.Conflicts, err = gui.findConflicts(cat) + gui.Log.Info(cat) + panelState.Conflicts, err = gui.findConflicts(cat) if err != nil { return err } - if len(gui.State.Conflicts) == 0 { - return gui.handleCompleteMerge(g) - } else if gui.State.ConflictIndex > len(gui.State.Conflicts)-1 { - gui.State.ConflictIndex = len(gui.State.Conflicts) - 1 + // handle potential fixes that the user made in their editor since we last refreshed + if len(panelState.Conflicts) == 0 { + return gui.handleCompleteMerge() + } else if panelState.ConflictIndex > len(panelState.Conflicts)-1 { + panelState.ConflictIndex = len(panelState.Conflicts) - 1 } - hasFocus := gui.currentViewName(g) == "main" - content, err := gui.coloredConflictFile(cat, gui.State.Conflicts, gui.State.ConflictIndex, gui.State.ConflictTop, hasFocus) + + gui.g.SetViewOnTop("merging") + hasFocus := gui.currentViewName(g) == "merging" + content, err := gui.coloredConflictFile(cat, panelState.Conflicts, panelState.ConflictIndex, panelState.ConflictTop, hasFocus) if err != nil { return err } + if err := gui.renderString(g, "merging", content); err != nil { + return err + } if err := gui.scrollToConflict(g); err != nil { return err } - return gui.renderString(g, "main", content) + return nil } func (gui *Gui) scrollToConflict(g *gocui.Gui) error { - mainView, err := g.View("main") - if err != nil { - return err - } - if len(gui.State.Conflicts) == 0 { + panelState := gui.State.Panels.Merging + if len(panelState.Conflicts) == 0 { return nil } - conflict := gui.State.Conflicts[gui.State.ConflictIndex] - ox, _ := mainView.Origin() - _, height := mainView.Size() + mergingView := gui.getMergingView() + conflict := panelState.Conflicts[panelState.ConflictIndex] + gui.Log.Info(utils.AsJson(conflict)) + ox, _ := mergingView.Origin() + _, height := mergingView.Size() conflictMiddle := (conflict.End + conflict.Start) / 2 newOriginY := int(math.Max(0, float64(conflictMiddle-(height/2)))) - return mainView.SetOrigin(ox, newOriginY) + gui.Log.Info(utils.AsJson("origin Y")) + gui.Log.Info(utils.AsJson(newOriginY)) + gui.g.Update(func(g *gocui.Gui) error { + return mergingView.SetOrigin(ox, newOriginY) + }) + return nil } func (gui *Gui) switchToMerging(g *gocui.Gui) error { - gui.State.ConflictIndex = 0 - gui.State.ConflictTop = true - _, err := g.SetCurrentView("main") + _, err := g.SetCurrentView("merging") if err != nil { return err } @@ -242,34 +261,44 @@ func (gui *Gui) renderMergeOptions() error { } func (gui *Gui) handleEscapeMerge(g *gocui.Gui, v *gocui.View) error { - filesView, err := g.View("files") - if err != nil { - return err + gui.State.Panels.Merging.EditHistory = stack.New() + gui.g.SetViewOnBottom("merging") + gui.refreshFiles() + // it's possible this method won't be called from the merging view so we need to + // ensure we only 'return' focus if we already have it + if gui.g.CurrentView() == gui.getMergingView() { + return gui.switchFocus(g, v, gui.getFilesView()) } - gui.refreshFiles(g) - return gui.switchFocus(g, v, filesView) + return nil } -func (gui *Gui) handleCompleteMerge(g *gocui.Gui) error { - filesView, err := g.View("files") - if err != nil { - return err - } - gui.stageSelectedFile(g) - gui.refreshFiles(g) - if rebase, err := gui.GitCommand.IsInRebaseState(); rebase && err == nil { - if err := gui.GitCommand.ContinueRebaseBranch(); err != nil { - if strings.Contains(err.Error(), "No changes - did you forget to use") { - if err := gui.GitCommand.SkipRebaseBranch(); err != nil { - gui.Log.Errorln(err) +func (gui *Gui) handleCompleteMerge() error { + filesView := gui.getFilesView() + gui.stageSelectedFile(gui.g) + gui.refreshFiles() + // if there are no more files with merge conflicts, we should ask whether the user wants to continue + if !gui.anyFilesWithMergeConflicts() { + // ask if user wants to continue + if err := gui.createConfirmationPanel(gui.g, filesView, "continue", "all merge conflicts, resolved. Continue?", func(g *gocui.Gui, v *gocui.View) error { + if err := gui.genericRebaseCommand("continue"); err != nil { + if err == gui.Errors.ErrSubProcess { + return err + } + if strings.Contains(err.Error(), "No changes - did you forget to use") { + if err := gui.genericRebaseCommand("skip"); err != nil { + if err == gui.Errors.ErrSubProcess { + return err + } + gui.createErrorPanel(gui.g, err.Error()) + } + } else { + gui.createErrorPanel(gui.g, err.Error()) } - } else { - gui.Log.Errorln(err) } - } - if err := gui.refreshSidePanels(g); err != nil { + return gui.refreshSidePanels(gui.g) + }, nil); err != nil { return err } } - return gui.switchFocus(g, nil, filesView) + return gui.handleEscapeMerge(gui.g, gui.getMergingView()) } |