1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-23 12:18:51 +02:00
lazygit/pkg/gui/controllers/remote_branches_controller.go
T. 2335772db6 Make opening git difftool more consistent
The default shortcut to open git difftool (ctrl+t) is not available on
the "Local Branches" window. It is available when selecting a commit
from a local branch, a remote branch, or a tag from the "Local Branches"
window.

This is inconsistent since branches or tags are also commits, the
shortcut should also work on them directly.

This commit remedies this inconsistency by allowing the use of the
shortcut directly on a branch or a tag. The shortcut works both in the
"standard" mode and the "diffing" mode.
2024-06-30 10:27:28 +02:00

199 lines
7.0 KiB
Go

package controllers
import (
"strings"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)
type RemoteBranchesController struct {
baseController
*ListControllerTrait[*models.RemoteBranch]
c *ControllerCommon
}
var _ types.IController = &RemoteBranchesController{}
func NewRemoteBranchesController(
c *ControllerCommon,
) *RemoteBranchesController {
return &RemoteBranchesController{
baseController: baseController{},
ListControllerTrait: NewListControllerTrait[*models.RemoteBranch](
c,
c.Contexts().RemoteBranches,
c.Contexts().RemoteBranches.GetSelected,
c.Contexts().RemoteBranches.GetSelectedItems,
),
c: c,
}
}
func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
return []*types.Binding{
{
Key: opts.GetKey(opts.Config.Universal.Select),
Handler: self.withItem(self.checkoutBranch),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.Checkout,
Tooltip: self.c.Tr.RemoteBranchCheckoutTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Universal.New),
Handler: self.withItem(self.newLocalBranch),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.NewBranch,
},
{
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.merge)),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.Merge,
Tooltip: self.c.Tr.MergeBranchTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.rebase)),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.RebaseBranch,
Tooltip: self.c.Tr.RebaseBranchTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.withItem(self.delete),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.Delete,
Tooltip: self.c.Tr.DeleteRemoteBranchTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
Handler: self.withItem(self.setAsUpstream),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.SetAsUpstream,
Tooltip: self.c.Tr.SetAsUpstreamTooltip,
DisplayOnScreen: true,
},
{
Key: opts.GetKey(opts.Config.Branches.SortOrder),
Handler: self.createSortMenu,
Description: self.c.Tr.SortOrder,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
Handler: self.withItem(self.createResetMenu),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.ViewResetOptions,
Tooltip: self.c.Tr.ResetTooltip,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
Handler: self.withItem(func(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().Diff.OpenDiffToolForRef(selectedBranch)
}),
GetDisabledReason: self.require(self.singleItemSelected()),
Description: self.c.Tr.OpenDiffTool,
},
}
}
func (self *RemoteBranchesController) GetOnRenderToMain() func() error {
return func() error {
return self.c.Helpers().Diff.WithDiffModeCheck(func() error {
var task types.UpdateTask
remoteBranch := self.context().GetSelected()
if remoteBranch == nil {
task = types.NewRenderStringTask("No branches for this remote")
} else {
cmdObj := self.c.Git().Branch.GetGraphCmdObj(remoteBranch.FullRefName())
task = types.NewRunCommandTask(cmdObj.GetCmd())
}
return self.c.RenderToMainViews(types.RefreshMainOpts{
Pair: self.c.MainViewPairs().Normal,
Main: &types.ViewUpdateOpts{
Title: "Remote Branch",
Task: task,
},
})
})
}
}
func (self *RemoteBranchesController) context() *context.RemoteBranchesContext {
return self.c.Contexts().RemoteBranches
}
func (self *RemoteBranchesController) delete(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().BranchesHelper.ConfirmDeleteRemote(selectedBranch.RemoteName, selectedBranch.Name)
}
func (self *RemoteBranchesController) merge(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranch.FullName())
}
func (self *RemoteBranchesController) rebase(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranch.FullName())
}
func (self *RemoteBranchesController) createSortMenu() error {
return self.c.Helpers().Refs.CreateSortOrderMenu([]string{"alphabetical", "date"}, func(sortOrder string) error {
if self.c.GetAppState().RemoteBranchSortOrder != sortOrder {
self.c.GetAppState().RemoteBranchSortOrder = sortOrder
self.c.SaveAppStateAndLogError()
self.c.Contexts().RemoteBranches.SetSelection(0)
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.REMOTES}})
}
return nil
},
self.c.GetAppState().RemoteBranchSortOrder)
}
func (self *RemoteBranchesController) createResetMenu(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().Refs.CreateGitResetMenu(selectedBranch.FullName())
}
func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.RemoteBranch) error {
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef()
message := utils.ResolvePlaceholderString(
self.c.Tr.SetUpstreamMessage,
map[string]string{
"checkedOut": checkedOutBranch.Name,
"selected": selectedBranch.FullName(),
},
)
return self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.SetUpstreamTitle,
Prompt: message,
HandleConfirm: func() error {
self.c.LogAction(self.c.Tr.Actions.SetBranchUpstream)
if err := self.c.Git().Branch.SetUpstream(selectedBranch.RemoteName, selectedBranch.Name, checkedOutBranch.Name); err != nil {
return err
}
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
},
})
}
func (self *RemoteBranchesController) newLocalBranch(selectedBranch *models.RemoteBranch) error {
// will set to the remote's branch name without the remote name
nameSuggestion := strings.SplitAfterN(selectedBranch.RefName(), "/", 2)[1]
return self.c.Helpers().Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), nameSuggestion)
}
func (self *RemoteBranchesController) checkoutBranch(selectedBranch *models.RemoteBranch) error {
return self.c.Helpers().Refs.CheckoutRemoteBranch(selectedBranch.FullName(), selectedBranch.Name)
}