lazygit/pkg/gui/controllers/remote_branches_controller.go
Jesse Duffield 54bd94ad24 Add SetSelection function for list contexts and use it in most places
The only time we should call SetSelectedLineIdx is when we are happy for a
select range to be retained which means things like moving the selected line
index to top top/bottom or up/down a page as the user navigates.

But in every other case we should now call SetSelection because that will
set the selected index and cancel the range which is almost always what we
want.
2024-01-19 10:47:21 +11:00

176 lines
5.7 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
c *ControllerCommon
}
var _ types.IController = &RemoteBranchesController{}
func NewRemoteBranchesController(
common *ControllerCommon,
) *RemoteBranchesController {
return &RemoteBranchesController{
baseController: baseController{},
c: common,
}
}
func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
return []*types.Binding{
{
Key: opts.GetKey(opts.Config.Universal.Select),
// gonna use the exact same handler as the 'n' keybinding because everybody wants this to happen when they checkout a remote branch
Handler: self.checkSelected(self.newLocalBranch),
Description: self.c.Tr.Checkout,
},
{
Key: opts.GetKey(opts.Config.Universal.New),
Handler: self.checkSelected(self.newLocalBranch),
Description: self.c.Tr.NewBranch,
},
{
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.merge)),
Description: self.c.Tr.MergeIntoCurrentBranch,
},
{
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.rebase)),
Description: self.c.Tr.RebaseBranch,
},
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.checkSelected(self.delete),
Description: self.c.Tr.DeleteRemoteTag,
},
{
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
Handler: self.checkSelected(self.setAsUpstream),
Description: self.c.Tr.SetAsUpstream,
},
{
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.checkSelected(self.createResetMenu),
Description: self.c.Tr.ViewResetOptions,
OpensMenu: true,
},
}
}
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() types.Context {
return self.context()
}
func (self *RemoteBranchesController) context() *context.RemoteBranchesContext {
return self.c.Contexts().RemoteBranches
}
func (self *RemoteBranchesController) checkSelected(callback func(*models.RemoteBranch) error) func() error {
return func() error {
selectedItem := self.context().GetSelected()
if selectedItem == nil {
return nil
}
return callback(selectedItem)
}
}
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
})
}
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 self.c.Error(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)
}