diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2022-02-26 19:06:22 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2022-03-17 19:13:40 +1100 |
commit | ee1337b93190d7354b64ce84bf5c9bccba48fe4e (patch) | |
tree | 0b7a8b96ffa0417d0a9356ea0d2ed836f292250f /pkg/gui/controllers | |
parent | d543e767d4b856e975de67a4c10e64e0a656b329 (diff) |
add remote branches controller
Diffstat (limited to 'pkg/gui/controllers')
-rw-r--r-- | pkg/gui/controllers/branches_controller.go | 96 | ||||
-rw-r--r-- | pkg/gui/controllers/remote_branches_controller.go | 161 |
2 files changed, 191 insertions, 66 deletions
diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go index ff5989656..a151d4bcc 100644 --- a/pkg/gui/controllers/branches_controller.go +++ b/pkg/gui/controllers/branches_controller.go @@ -31,96 +31,70 @@ func NewBranchesController( func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { return []*types.Binding{ { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Universal.Select), - Handler: self.handleBranchPress, + Handler: self.checkSelected(self.press), Description: self.c.Tr.LcCheckout, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.CreatePullRequest), - Handler: self.handleCreatePullRequestPress, + Handler: self.checkSelected(self.handleCreatePullRequest), Description: self.c.Tr.LcCreatePullRequest, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions), Handler: self.checkSelected(self.handleCreatePullRequestMenu), Description: self.c.Tr.LcCreatePullRequestOptions, OpensMenu: true, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL), - Handler: self.handleCopyPullRequestURLPress, + Handler: self.copyPullRequestURL, Description: self.c.Tr.LcCopyPullRequestURL, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.CheckoutBranchByName), - Handler: self.handleCheckoutByName, + Handler: self.checkoutByName, Description: self.c.Tr.LcCheckoutByName, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch), - Handler: self.handleForceCheckout, + Handler: self.forceCheckout, Description: self.c.Tr.LcForceCheckout, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Universal.New), - Handler: self.checkSelected(self.handleNewBranchOffBranch), + Handler: self.checkSelected(self.newBranch), Description: self.c.Tr.LcNewBranch, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Universal.Remove), - Handler: self.checkSelectedAndReal(self.handleDeleteBranch), + Handler: self.checkSelectedAndReal(self.delete), Description: self.c.Tr.LcDeleteBranch, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.RebaseBranch), - Handler: opts.Guards.OutsideFilterMode(self.handleRebaseOntoLocalBranch), + Handler: opts.Guards.OutsideFilterMode(self.rebase), Description: self.c.Tr.LcRebaseBranch, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch), - Handler: opts.Guards.OutsideFilterMode(self.handleMerge), + Handler: opts.Guards.OutsideFilterMode(self.merge), Description: self.c.Tr.LcMergeIntoCurrentBranch, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.FastForward), - Handler: self.checkSelectedAndReal(self.handleFastForward), + Handler: self.checkSelectedAndReal(self.fastForward), Description: self.c.Tr.FastForward, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Commits.ViewResetOptions), - Handler: self.checkSelected(self.handleCreateResetToBranchMenu), + Handler: self.checkSelected(self.createResetMenu), Description: self.c.Tr.LcViewResetOptions, OpensMenu: true, }, { - ViewName: "branches", - Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)}, Key: opts.GetKey(opts.Config.Branches.RenameBranch), - Handler: self.checkSelectedAndReal(self.handleRenameBranch), + Handler: self.checkSelectedAndReal(self.rename), Description: self.c.Tr.LcRenameBranch, }, } @@ -134,23 +108,17 @@ func (self *BranchesController) context() *context.BranchesContext { return self.contexts.Branches } -func (self *BranchesController) handleBranchPress() error { - branch := self.context().GetSelected() - if branch == nil { - return nil - } - - if branch == self.helpers.Refs.GetCheckedOutRef() { +func (self *BranchesController) press(selectedBranch *models.Branch) error { + if selectedBranch == self.helpers.Refs.GetCheckedOutRef() { return self.c.ErrorMsg(self.c.Tr.AlreadyCheckedOutBranch) } self.c.LogAction(self.c.Tr.Actions.CheckoutBranch) - return self.helpers.Refs.CheckoutRef(branch.Name, types.CheckoutRefOptions{}) + return self.helpers.Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{}) } -func (self *BranchesController) handleCreatePullRequestPress() error { - branch := self.context().GetSelected() - return self.createPullRequest(branch.Name, "") +func (self *BranchesController) handleCreatePullRequest(selectedBranch *models.Branch) error { + return self.createPullRequest(selectedBranch.Name, "") } func (self *BranchesController) handleCreatePullRequestMenu(selectedBranch *models.Branch) error { @@ -159,7 +127,7 @@ func (self *BranchesController) handleCreatePullRequestMenu(selectedBranch *mode return self.createPullRequestMenu(selectedBranch, checkedOutBranch) } -func (self *BranchesController) handleCopyPullRequestURLPress() error { +func (self *BranchesController) copyPullRequestURL() error { branch := self.context().GetSelected() branchExistsOnRemote := self.git.Remote.CheckRemoteBranchExists(branch.Name) @@ -182,7 +150,7 @@ func (self *BranchesController) handleCopyPullRequestURLPress() error { return nil } -func (self *BranchesController) handleForceCheckout() error { +func (self *BranchesController) forceCheckout() error { branch := self.context().GetSelected() message := self.c.Tr.SureForceCheckout title := self.c.Tr.ForceCheckoutBranch @@ -200,7 +168,7 @@ func (self *BranchesController) handleForceCheckout() error { }) } -func (self *BranchesController) handleCheckoutByName() error { +func (self *BranchesController) checkoutByName() error { return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.BranchName + ":", FindSuggestionsFunc: self.helpers.Suggestions.GetRefsSuggestionsFunc(), @@ -235,19 +203,15 @@ func (self *BranchesController) createNewBranchWithName(newBranchName string) er return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) } -func (self *BranchesController) handleDeleteBranch(branch *models.Branch) error { - return self.deleteBranch(branch, false) -} - -func (self *BranchesController) deleteBranch(branch *models.Branch, force bool) error { +func (self *BranchesController) delete(branch *models.Branch) error { checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() if checkedOutBranch.Name == branch.Name { return self.c.ErrorMsg(self.c.Tr.CantDeleteCheckOutBranch) } - return self.deleteNamedBranch(branch, force) + return self.deleteWithForce(branch, false) } -func (self *BranchesController) deleteNamedBranch(selectedBranch *models.Branch, force bool) error { +func (self *BranchesController) deleteWithForce(selectedBranch *models.Branch, force bool) error { title := self.c.Tr.DeleteBranch var templateStr string if force { @@ -270,7 +234,7 @@ func (self *BranchesController) deleteNamedBranch(selectedBranch *models.Branch, if err := self.git.Branch.Delete(selectedBranch.Name, force); err != nil { errMessage := err.Error() if !force && strings.Contains(errMessage, "git branch -D ") { - return self.deleteNamedBranch(selectedBranch, true) + return self.deleteWithForce(selectedBranch, true) } return self.c.ErrorMsg(errMessage) } @@ -279,17 +243,17 @@ func (self *BranchesController) deleteNamedBranch(selectedBranch *models.Branch, }) } -func (self *BranchesController) handleMerge() error { +func (self *BranchesController) merge() error { selectedBranchName := self.context().GetSelected().Name return self.helpers.MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName) } -func (self *BranchesController) handleRebaseOntoLocalBranch() error { +func (self *BranchesController) rebase() error { selectedBranchName := self.context().GetSelected().Name return self.helpers.MergeAndRebase.RebaseOntoRef(selectedBranchName) } -func (self *BranchesController) handleFastForward(branch *models.Branch) error { +func (self *BranchesController) fastForward(branch *models.Branch) error { if !branch.IsTrackingRemote() { return self.c.ErrorMsg(self.c.Tr.FwdNoUpstream) } @@ -339,11 +303,11 @@ func (self *BranchesController) handleFastForward(branch *models.Branch) error { }) } -func (self *BranchesController) handleCreateResetToBranchMenu(selectedBranch *models.Branch) error { +func (self *BranchesController) createResetMenu(selectedBranch *models.Branch) error { return self.helpers.Refs.CreateGitResetMenu(selectedBranch.Name) } -func (self *BranchesController) handleRenameBranch(branch *models.Branch) error { +func (self *BranchesController) rename(branch *models.Branch) error { promptForNewName := func() error { return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.NewBranchNamePrompt + " " + branch.Name + ":", @@ -386,7 +350,7 @@ func (self *BranchesController) handleRenameBranch(branch *models.Branch) error }) } -func (self *BranchesController) handleNewBranchOffBranch(selectedBranch *models.Branch) error { +func (self *BranchesController) newBranch(selectedBranch *models.Branch) error { return self.helpers.Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), "") } diff --git a/pkg/gui/controllers/remote_branches_controller.go b/pkg/gui/controllers/remote_branches_controller.go new file mode 100644 index 000000000..d469f5657 --- /dev/null +++ b/pkg/gui/controllers/remote_branches_controller.go @@ -0,0 +1,161 @@ +package controllers + +import ( + "fmt" + "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 + *controllerCommon +} + +var _ types.IController = &RemoteBranchesController{} + +func NewRemoteBranchesController( + common *controllerCommon, +) *RemoteBranchesController { + return &RemoteBranchesController{ + baseController: baseController{}, + controllerCommon: 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.LcCheckout, + }, + { + Key: opts.GetKey(opts.Config.Universal.New), + Handler: self.checkSelected(self.newLocalBranch), + Description: self.c.Tr.LcNewBranch, + }, + { + Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch), + Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.merge)), + Description: self.c.Tr.LcMergeIntoCurrentBranch, + }, + { + Key: opts.GetKey(opts.Config.Branches.RebaseBranch), + Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.rebase)), + Description: self.c.Tr.LcRebaseBranch, + }, + { + Key: opts.GetKey(opts.Config.Universal.Remove), + Handler: self.checkSelected(self.delete), + Description: self.c.Tr.LcDeleteBranch, + }, + { + Key: opts.GetKey(opts.Config.Branches.SetUpstream), + Handler: self.checkSelected(self.setAsUpstream), + Description: self.c.Tr.LcSetUpstream, + }, + { + Key: opts.GetKey(opts.Config.Universal.Return), + Handler: self.escape, + Description: self.c.Tr.ReturnToRemotesList, + }, + { + Key: opts.GetKey(opts.Config.Commits.ViewResetOptions), + Handler: self.checkSelected(self.createResetMenu), + Description: self.c.Tr.LcViewResetOptions, + OpensMenu: true, + }, + } +} + +func (self *RemoteBranchesController) Context() types.Context { + return self.context() +} + +func (self *RemoteBranchesController) context() *context.RemoteBranchesContext { + return self.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) escape() error { + return self.c.PushContext(self.contexts.Remotes) +} + +func (self *RemoteBranchesController) delete(selectedBranch *models.RemoteBranch) error { + message := fmt.Sprintf("%s '%s'?", self.c.Tr.DeleteRemoteBranchMessage, selectedBranch.FullName()) + + return self.c.Ask(types.AskOpts{ + Title: self.c.Tr.DeleteRemoteBranch, + Prompt: message, + HandleConfirm: func() error { + return self.c.WithWaitingStatus(self.c.Tr.DeletingStatus, func() error { + self.c.LogAction(self.c.Tr.Actions.DeleteRemoteBranch) + err := self.git.Remote.DeleteRemoteBranch(selectedBranch.RemoteName, selectedBranch.Name) + if err != nil { + _ = self.c.Error(err) + } + + return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}}) + }) + }, + }) +} + +func (self *RemoteBranchesController) merge(selectedBranch *models.RemoteBranch) error { + return self.helpers.MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranch.FullName()) +} + +func (self *RemoteBranchesController) rebase(selectedBranch *models.RemoteBranch) error { + return self.helpers.MergeAndRebase.RebaseOntoRef(selectedBranch.FullName()) +} + +func (self *RemoteBranchesController) createResetMenu(selectedBranch *models.RemoteBranch) error { + return self.helpers.Refs.CreateGitResetMenu(selectedBranch.FullName()) +} + +func (self *RemoteBranchesController) setAsUpstream(selectedBranch *models.RemoteBranch) error { + checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() + + message := utils.ResolvePlaceholderString( + self.c.Tr.SetUpstreamMessage, + map[string]string{ + "checkedOut": checkedOutBranch.Name, + "selected": selectedBranch.FullName(), + }, + ) + + return self.c.Ask(types.AskOpts{ + Title: self.c.Tr.SetUpstreamTitle, + Prompt: message, + HandleConfirm: func() error { + self.c.LogAction(self.c.Tr.Actions.SetBranchUpstream) + if err := self.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.helpers.Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), nameSuggestion) +} |