summaryrefslogtreecommitdiffstats
path: root/pkg/gui/branches_panel.go
diff options
context:
space:
mode:
authorMark Kopenga <mkopenga@gmail.com>2018-12-08 16:41:39 +0100
committerGitHub <noreply@github.com>2018-12-08 16:41:39 +0100
commit19a6a32625d59c61ecfe91ef8626390eb34a922a (patch)
treeb02d1a9c8477d2614f99cc80b40b54accf28c127 /pkg/gui/branches_panel.go
parent270658fc009dc254a80501fc1c9f5f82acd27239 (diff)
parentff856b763033a241370bfde98d7386b43b7d0893 (diff)
Merge branch 'master' into https-ask-for-username-password
Diffstat (limited to 'pkg/gui/branches_panel.go')
-rw-r--r--pkg/gui/branches_panel.go187
1 files changed, 129 insertions, 58 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index 059f0af50..e54d6e8c1 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -7,25 +7,116 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/git"
- "github.com/jesseduffield/lazygit/pkg/utils"
)
+// list panel functions
+
+func (gui *Gui) getSelectedBranch() *commands.Branch {
+ selectedLine := gui.State.Panels.Branches.SelectedLine
+ if selectedLine == -1 {
+ return nil
+ }
+
+ return gui.State.Branches[selectedLine]
+}
+
+// may want to standardise how these select methods work
+func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error {
+ // This really shouldn't happen: there should always be a master branch
+ if len(gui.State.Branches) == 0 {
+ return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo"))
+ }
+ branch := gui.getSelectedBranch()
+ if err := gui.focusPoint(0, gui.State.Panels.Branches.SelectedLine, v); err != nil {
+ return err
+ }
+ go func() {
+ _ = gui.RenderSelectedBranchUpstreamDifferences()
+ }()
+ go func() {
+ graph, err := gui.GitCommand.GetBranchGraph(branch.Name)
+ if err != nil && strings.HasPrefix(graph, "fatal: ambiguous argument") {
+ graph = gui.Tr.SLocalize("NoTrackingThisBranch")
+ }
+ _ = gui.renderString(g, "main", graph)
+ }()
+ return nil
+}
+
+func (gui *Gui) RenderSelectedBranchUpstreamDifferences() error {
+ // here we tell the selected branch that it is selected.
+ // this is necessary for showing stats on a branch that is selected, because
+ // the displaystring function doesn't have access to gui state to tell if it's selected
+ for i, branch := range gui.State.Branches {
+ branch.Selected = i == gui.State.Panels.Branches.SelectedLine
+ }
+
+ branch := gui.getSelectedBranch()
+ branch.Pushables, branch.Pullables = gui.GitCommand.GetBranchUpstreamDifferenceCount(branch.Name)
+ return gui.renderListPanel(gui.getBranchesView(gui.g), gui.State.Branches)
+}
+
+// gui.refreshStatus is called at the end of this because that's when we can
+// be sure there is a state.Branches array to pick the current branch from
+func (gui *Gui) refreshBranches(g *gocui.Gui) error {
+ g.Update(func(g *gocui.Gui) error {
+ builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand)
+ if err != nil {
+ return err
+ }
+ gui.State.Branches = builder.Build()
+
+ gui.refreshSelectedLine(&gui.State.Panels.Branches.SelectedLine, len(gui.State.Branches))
+ if err := gui.resetOrigin(gui.getBranchesView(gui.g)); err != nil {
+ return err
+ }
+ if err := gui.RenderSelectedBranchUpstreamDifferences(); err != nil {
+ return err
+ }
+
+ return gui.refreshStatus(g)
+ })
+ return nil
+}
+
+func (gui *Gui) handleBranchesNextLine(g *gocui.Gui, v *gocui.View) error {
+ panelState := gui.State.Panels.Branches
+ gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), false)
+ return gui.handleBranchSelect(gui.g, v)
+}
+
+func (gui *Gui) handleBranchesPrevLine(g *gocui.Gui, v *gocui.View) error {
+ panelState := gui.State.Panels.Branches
+ gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), true)
+
+ return gui.handleBranchSelect(gui.g, v)
+}
+
+// specific functions
+
func (gui *Gui) handleBranchPress(g *gocui.Gui, v *gocui.View) error {
- index := gui.getItemPosition(gui.getBranchesView(g))
- if index == 0 {
+ if gui.State.Panels.Branches.SelectedLine == -1 {
+ return nil
+ }
+ if gui.State.Panels.Branches.SelectedLine == 0 {
return gui.createErrorPanel(g, gui.Tr.SLocalize("AlreadyCheckedOutBranch"))
}
- branch := gui.getSelectedBranch(gui.getBranchesView(g))
+ branch := gui.getSelectedBranch()
if err := gui.GitCommand.Checkout(branch.Name, false); err != nil {
- gui.createErrorPanel(g, err.Error())
+ if err := gui.createErrorPanel(g, err.Error()); err != nil {
+ return err
+ }
+ } else {
+ gui.State.Panels.Branches.SelectedLine = 0
}
+
return gui.refreshSidePanels(g)
}
func (gui *Gui) handleCreatePullRequestPress(g *gocui.Gui, v *gocui.View) error {
- branch := gui.getSelectedBranch(gui.getBranchesView(g))
pullRequest := commands.NewPullRequest(gui.GitCommand)
+ branch := gui.getSelectedBranch()
if err := pullRequest.Create(branch); err != nil {
return gui.createErrorPanel(g, err.Error())
}
@@ -60,7 +151,7 @@ func (gui *Gui) handleGitFetch(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error {
- branch := gui.getSelectedBranch(v)
+ branch := gui.getSelectedBranch()
message := gui.Tr.SLocalize("SureForceCheckout")
title := gui.Tr.SLocalize("ForceCheckoutBranch")
return gui.createConfirmationPanel(g, v, title, message, func(g *gocui.Gui, v *gocui.View) error {
@@ -108,8 +199,11 @@ func (gui *Gui) handleForceDeleteBranch(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) deleteBranch(g *gocui.Gui, v *gocui.View, force bool) error {
+ selectedBranch := gui.getSelectedBranch()
+ if selectedBranch == nil {
+ return nil
+ }
checkedOutBranch := gui.State.Branches[0]
- selectedBranch := gui.getSelectedBranch(v)
if checkedOutBranch.Name == selectedBranch.Name {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantDeleteCheckOutBranch"))
}
@@ -144,7 +238,7 @@ func (gui *Gui) deleteNamedBranch(g *gocui.Gui, v *gocui.View, selectedBranch *c
func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error {
checkedOutBranch := gui.State.Branches[0]
- selectedBranch := gui.getSelectedBranch(v)
+ selectedBranch := gui.getSelectedBranch()
defer gui.refreshSidePanels(g)
if checkedOutBranch.Name == selectedBranch.Name {
return gui.createErrorPanel(g, gui.Tr.SLocalize("CantMergeBranchIntoItself"))
@@ -155,59 +249,36 @@ func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error {
return nil
}
-func (gui *Gui) getSelectedBranch(v *gocui.View) *commands.Branch {
- lineNumber := gui.getItemPosition(v)
- return gui.State.Branches[lineNumber]
-}
-
-func (gui *Gui) renderBranchesOptions(g *gocui.Gui) error {
- return gui.renderGlobalOptions(g)
-}
-
-// may want to standardise how these select methods work
-func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error {
- if err := gui.renderBranchesOptions(g); err != nil {
- return err
+func (gui *Gui) handleFastForward(g *gocui.Gui, v *gocui.View) error {
+ branch := gui.getSelectedBranch()
+ if branch == nil {
+ return nil
}
- // This really shouldn't happen: there should always be a master branch
- if len(gui.State.Branches) == 0 {
- return gui.renderString(g, "main", gui.Tr.SLocalize("NoBranchesThisRepo"))
+ if branch.Pushables == "" {
+ return nil
+ }
+ if branch.Pushables == "?" {
+ return gui.createErrorPanel(gui.g, "Cannot fast-forward a branch with no upstream")
+ }
+ if branch.Pushables != "0" {
+ return gui.createErrorPanel(gui.g, "Cannot fast-forward a branch with commits to push")
}
+ upstream := "origin" // hardcoding for now
+ message := gui.Tr.TemplateLocalize(
+ "Fetching",
+ Teml{
+ "from": fmt.Sprintf("%s/%s", upstream, branch.Name),
+ "to": branch.Name,
+ },
+ )
go func() {
- branch := gui.getSelectedBranch(v)
- diff, err := gui.GitCommand.GetBranchGraph(branch.Name)
- if err != nil && strings.HasPrefix(diff, "fatal: ambiguous argument") {
- diff = gui.Tr.SLocalize("NoTrackingThisBranch")
+ _ = gui.createMessagePanel(gui.g, v, "", message)
+ if err := gui.GitCommand.FastForward(branch.Name); err != nil {
+ _ = gui.createErrorPanel(gui.g, err.Error())
+ } else {
+ _ = gui.closeConfirmationPrompt(gui.g)
+ _ = gui.RenderSelectedBranchUpstreamDifferences()
}
- gui.renderString(g, "main", diff)
}()
return nil
}
-
-// gui.refreshStatus is called at the end of this because that's when we can
-// be sure there is a state.Branches array to pick the current branch from
-func (gui *Gui) refreshBranches(g *gocui.Gui) error {
- g.Update(func(g *gocui.Gui) error {
- v, err := g.View("branches")
- if err != nil {
- panic(err)
- }
- builder, err := git.NewBranchListBuilder(gui.Log, gui.GitCommand)
- if err != nil {
- return err
- }
- gui.State.Branches = builder.Build()
-
- v.Clear()
- list, err := utils.RenderList(gui.State.Branches)
- if err != nil {
- return err
- }
-
- fmt.Fprint(v, list)
-
- gui.resetOrigin(v)
- return gui.refreshStatus(g)
- })
- return nil
-}