diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2022-02-06 15:54:26 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2022-03-17 19:13:40 +1100 |
commit | 722410aded4e3d14356c7ab94bfa15abe10359fa (patch) | |
tree | 8e8a57503b0b57bccca5fa8cd146bc699960033f | |
parent | b93b8cc00a2f2ea339b1ecdbc380320556490d3b (diff) |
refactor controllers
56 files changed, 1409 insertions, 1556 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 7fcf050b3..959085645 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -1,18 +1,5 @@ package gui -import ( - "errors" - "fmt" - "strings" - - "github.com/jesseduffield/lazygit/pkg/commands/git_commands" - "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/types" - "github.com/jesseduffield/lazygit/pkg/utils" -) - -// list panel functions - func (gui *Gui) branchesRenderToMain() error { var task updateTask branch := gui.State.Contexts.Branches.GetSelected() @@ -31,368 +18,3 @@ func (gui *Gui) branchesRenderToMain() error { }, }) } - -// specific functions - -func (gui *Gui) handleBranchPress() error { - branch := gui.State.Contexts.Branches.GetSelected() - if branch == nil { - return nil - } - - if branch == gui.getCheckedOutBranch() { - return gui.c.ErrorMsg(gui.c.Tr.AlreadyCheckedOutBranch) - } - - gui.c.LogAction(gui.c.Tr.Actions.CheckoutBranch) - return gui.helpers.Refs.CheckoutRef(branch.Name, types.CheckoutRefOptions{}) -} - -func (gui *Gui) handleCreatePullRequestPress() error { - branch := gui.State.Contexts.Branches.GetSelected() - return gui.createPullRequest(branch.Name, "") -} - -func (gui *Gui) handleCreatePullRequestMenu() error { - selectedBranch := gui.State.Contexts.Branches.GetSelected() - if selectedBranch == nil { - return nil - } - checkedOutBranch := gui.getCheckedOutBranch() - - return gui.createPullRequestMenu(selectedBranch, checkedOutBranch) -} - -func (gui *Gui) handleCopyPullRequestURLPress() error { - hostingServiceMgr := gui.getHostingServiceMgr() - - branch := gui.State.Contexts.Branches.GetSelected() - - branchExistsOnRemote := gui.git.Remote.CheckRemoteBranchExists(branch.Name) - - if !branchExistsOnRemote { - return gui.c.Error(errors.New(gui.c.Tr.NoBranchOnRemote)) - } - - url, err := hostingServiceMgr.GetPullRequestURL(branch.Name, "") - if err != nil { - return gui.c.Error(err) - } - gui.c.LogAction(gui.c.Tr.Actions.CopyPullRequestURL) - if err := gui.os.CopyToClipboard(url); err != nil { - return gui.c.Error(err) - } - - gui.c.Toast(gui.c.Tr.PullRequestURLCopiedToClipboard) - - return nil -} - -func (gui *Gui) handleGitFetch() error { - return gui.c.WithLoaderPanel(gui.c.Tr.FetchWait, func() error { - if err := gui.fetch(); err != nil { - _ = gui.c.Error(err) - } - return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) - }) -} - -func (gui *Gui) handleForceCheckout() error { - branch := gui.State.Contexts.Branches.GetSelected() - message := gui.c.Tr.SureForceCheckout - title := gui.c.Tr.ForceCheckoutBranch - - return gui.c.Ask(types.AskOpts{ - Title: title, - Prompt: message, - HandleConfirm: func() error { - gui.c.LogAction(gui.c.Tr.Actions.ForceCheckoutBranch) - if err := gui.git.Branch.Checkout(branch.Name, git_commands.CheckoutOptions{Force: true}); err != nil { - _ = gui.c.Error(err) - } - return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) - }, - }) -} - -func (gui *Gui) handleCheckoutByName() error { - return gui.c.Prompt(types.PromptOpts{ - Title: gui.c.Tr.BranchName + ":", - FindSuggestionsFunc: gui.helpers.Suggestions.GetRefsSuggestionsFunc(), - HandleConfirm: func(response string) error { - gui.c.LogAction("Checkout branch") - return gui.helpers.Refs.CheckoutRef(response, types.CheckoutRefOptions{ - OnRefNotFound: func(ref string) error { - return gui.c.Ask(types.AskOpts{ - Title: gui.c.Tr.BranchNotFoundTitle, - Prompt: fmt.Sprintf("%s %s%s", gui.c.Tr.BranchNotFoundPrompt, ref, "?"), - HandleConfirm: func() error { - return gui.createNewBranchWithName(ref) - }, - }) - }, - }) - }}, - ) -} - -func (gui *Gui) getCheckedOutBranch() *models.Branch { - if len(gui.State.Model.Branches) == 0 { - return nil - } - - return gui.State.Model.Branches[0] -} - -func (gui *Gui) createNewBranchWithName(newBranchName string) error { - branch := gui.State.Contexts.Branches.GetSelected() - if branch == nil { - return nil - } - - if err := gui.git.Branch.New(newBranchName, branch.Name); err != nil { - return gui.c.Error(err) - } - - gui.State.Contexts.Branches.SetSelectedLineIdx(0) - return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) -} - -func (gui *Gui) handleDeleteBranch() error { - return gui.deleteBranch(false) -} - -func (gui *Gui) deleteBranch(force bool) error { - selectedBranch := gui.State.Contexts.Branches.GetSelected() - if selectedBranch == nil { - return nil - } - checkedOutBranch := gui.getCheckedOutBranch() - if checkedOutBranch.Name == selectedBranch.Name { - return gui.c.ErrorMsg(gui.c.Tr.CantDeleteCheckOutBranch) - } - return gui.deleteNamedBranch(selectedBranch, force) -} - -func (gui *Gui) deleteNamedBranch(selectedBranch *models.Branch, force bool) error { - title := gui.c.Tr.DeleteBranch - var templateStr string - if force { - templateStr = gui.c.Tr.ForceDeleteBranchMessage - } else { - templateStr = gui.c.Tr.DeleteBranchMessage - } - message := utils.ResolvePlaceholderString( - templateStr, - map[string]string{ - "selectedBranchName": selectedBranch.Name, - }, - ) - - return gui.c.Ask(types.AskOpts{ - Title: title, - Prompt: message, - HandleConfirm: func() error { - gui.c.LogAction(gui.c.Tr.Actions.DeleteBranch) - if err := gui.git.Branch.Delete(selectedBranch.Name, force); err != nil { - errMessage := err.Error() - if !force && strings.Contains(errMessage, "git branch -D ") { - return gui.deleteNamedBranch(selectedBranch, true) - } - return gui.c.ErrorMsg(errMessage) - } - return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) - }, - }) -} - -func (gui *Gui) mergeBranchIntoCheckedOutBranch(branchName string) error { - if gui.git.Branch.IsHeadDetached() { - return gui.c.ErrorMsg("Cannot merge branch in detached head state. You might have checked out a commit directly or a remote branch, in which case you should checkout the local branch you want to be on") - } - checkedOutBranchName := gui.getCheckedOutBranch().Name - if checkedOutBranchName == branchName { - return gui.c.ErrorMsg(gui.c.Tr.CantMergeBranchIntoItself) - } - prompt := utils.ResolvePlaceholderString( - gui.c.Tr.ConfirmMerge, - map[string]string{ - "checkedOutBranch": checkedOutBranchName, - "selectedBranch": branchName, - }, - ) - - return gui.c.Ask(types.AskOpts{ - Title: gui.c.Tr.MergingTitle, - Prompt: prompt, - HandleConfirm: func() error { - gui.c.LogAction(gui.c.Tr.Actions.Merge) - err := gui.git.Branch.Merge(branchName, git_commands.MergeOpts{}) - return gui.helpers.Rebase.CheckMergeOrRebase(err) - }, - }) -} - -func (gui *Gui) handleMerge() error { - selectedBranchName := gui.State.Contexts.Branches.GetSelected().Name - return gui.mergeBranchIntoCheckedOutBranch(selectedBranchName) -} - -func (gui *Gui) handleRebaseOntoLocalBranch() error { - selectedBranchName := gui.State.Contexts.Branches.GetSelected().Name - return gui.handleRebaseOntoBranch(selectedBranchName) -} - -func (gui *Gui) handleRebaseOntoBranch(selectedBranchName string) error { - checkedOutBranch := gui.getCheckedOutBranch().Name - if selectedBranchName == checkedOutBranch { - return gui.c.ErrorMsg(gui.c.Tr.CantRebaseOntoSelf) - } - prompt := utils.ResolvePlaceholderString( - gui.c.Tr.ConfirmRebase, - map[string]string{ - "checkedOutBranch": checkedOutBranch, - "selectedBranch": selectedBranchName, - }, - ) - - return gui.c.Ask(types.AskOpts{ - Title: gui.c.Tr.RebasingTitle, - Prompt: prompt, - HandleConfirm: func() error { - gui.c.LogAction(gui.c.Tr.Actions.RebaseBranch) - err := gui.git.Rebase.RebaseBranch(selectedBranchName) - return gui.helpers.Rebase.CheckMergeOrRebase(err) - }, - }) -} - -func (gui *Gui) handleFastForward() error { - branch := gui.State.Contexts.Branches.GetSelected() - if branch == nil || !branch.IsRealBranch() { - return nil - } - - if !branch.IsTrackingRemote() { - return gui.c.ErrorMsg(gui.c.Tr.FwdNoUpstream) - } - if !branch.RemoteBranchStoredLocally() { - return gui.c.ErrorMsg(gui.c.Tr.FwdNoLocalUpstream) - } - if branch.HasCommitsToPush() { - return gui.c.ErrorMsg(gui.c.Tr.FwdCommitsToPush) - } - - action := gui.c.Tr.Actions.FastForwardBranch - - message := utils.ResolvePlaceholderString( - gui.c.Tr.Fetching, - map[string]string{ - "from": fmt.Sprintf("%s/%s", branch.UpstreamRemote, branch.UpstreamBranch), - "to": branch.Name, - }, - ) - - return gui.c.WithLoaderPanel(message, func() error { - if branch == gui.getCheckedOutBranch() { - gui.c.LogAction(action) - - err := gui.git.Sync.Pull( - git_commands.PullOptions{ - RemoteName: branch.UpstreamRemote, - BranchName: branch.Name, - FastForwardOnly: true, - }, - ) - if err != nil { - _ = gui.c.Error(err) - } - - return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) - } else { - gui.c.LogAction(action) - err := gui.git.Sync.FastForward(branch.Name, branch.UpstreamRemote, branch.UpstreamBranch) - if err != nil { - _ = gui.c.Error(err) - } - _ = gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) - } - - return nil - }) -} - -func (gui *Gui) handleCreateResetToBranchMenu() error { - branch := gui.State.Contexts.Branches.GetSelected() - if branch == nil { - return nil - } - - return gui.helpers.Refs.CreateGitResetMenu(branch.Name) -} - -func (gui *Gui) handleRenameBranch() error { - branch := gui.State.Contexts.Branches.GetSelected() - if branch == nil || !branch.IsRealBranch() { - return nil - } - - promptForNewName := func() error { - return gui.c.Prompt(types.PromptOpts{ - Title: gui.c.Tr.NewBranchNamePrompt + " " + branch.Name + ":", - InitialContent: branch.Name, - HandleConfirm: func(newBranchName string) error { - gui.c.LogAction(gui.c.Tr.Actions.RenameBranch) - if err := gui.git.Branch.Rename(branch.Name, newBranchName); err != nil { - return gui.c.Error(err) - } - - // need to find where the branch is now so that we can re-select it. That means we need to refetch the branches synchronously and then find our branch - gui.refreshBranches() - - // now that we've got our stuff again we need to find that branch and reselect it. - for i, newBranch := range gui.State.Model.Branches { - if newBranch.Name == newBranchName { - gui.State.Contexts.Branches.SetSelectedLineIdx(i) - if err := gui.State.Contexts.Branches.HandleRender(); err != nil { - return err - } - } - } - - return nil - }, - }) - } - - // I could do an explicit check here for whether the branch is tracking a remote branch - // but if we've selected it we'll already know that via Pullables and Pullables. - // Bit of a hack but I'm lazy. - if !branch.IsTrackingRemote() { - return promptForNewName() - } - - return gui.c.Ask(types.AskOpts{ - Title: gui.c.Tr.LcRenameBranch, - Prompt: gui.c.Tr.RenameBranchWarning, - HandleConfirm: promptForNewName, - }) -} - -func (gui *Gui) handleEnterBranch() error { - branch := gui.State.Contexts.Branches.GetSelected() - if branch == nil { - return nil - } - - return gui.switchToSubCommitsContext(branch.RefName()) -} - -func (gui *Gui) handleNewBranchOffBranch() error { - selectedBranch := gui.State.Contexts.Branches.GetSelected() - if selectedBranch == nil { - return nil - } - - return gui.helpers.Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), "") -} diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go index fbbedcb6f..8f1201ccb 100644 --- a/pkg/gui/commit_files_panel.go +++ b/pkg/gui/commit_files_panel.go @@ -85,7 +85,7 @@ func (gui *Gui) handleDiscardOldFileChange() error { return gui.c.WithWaitingStatus(gui.c.Tr.RebasingStatus, func() error { gui.c.LogAction(gui.c.Tr.Actions.DiscardOldFileChange) if err := gui.git.Rebase.DiscardOldFileChanges(gui.State.Model.Commits, gui.State.Contexts.BranchCommits.GetSelectedLineIdx(), fileName); err != nil { - if err := gui.helpers.Rebase.CheckMergeOrRebase(err); err != nil { + if err := gui.helpers.MergeAndRebase.CheckMergeOrRebase(err); err != nil { return err } } @@ -265,7 +265,7 @@ func (gui *Gui) SwitchToCommitFilesContext(opts controllers.SwitchToCommitFilesC gui.State.Contexts.CommitFiles.SetRefName(opts.RefName) gui.State.Contexts.CommitFiles.SetCanRebase(opts.CanRebase) gui.State.Contexts.CommitFiles.SetParentContext(opts.Context) - gui.State.Contexts.CommitFiles.SetWindowName(opts.WindowName) + gui.State.Contexts.CommitFiles.SetWindowName(opts.Context.GetWindowName()) if err := gui.refreshCommitFilesView(); err != nil { return err diff --git a/pkg/gui/context/branches_context.go b/pkg/gui/context/branches_context.go index 4b82844f4..146810a86 100644 --- a/pkg/gui/context/branches_context.go +++ b/pkg/gui/context/branches_context.go @@ -23,7 +23,7 @@ func NewBranchesContext( onRenderToMain func(...types.OnFocusOpts) error, onFocusLost func() error, - c *types.ControllerCommon, + c *types.HelperCommon, ) *BranchesContext { viewModel := NewBranchesViewModel(getModel) diff --git a/pkg/gui/context/commit_files_context.go b/pkg/gui/context/commit_files_context.go index 1c555387b..8f9bd91f7 100644 --- a/pkg/gui/context/commit_files_context.go +++ b/pkg/gui/context/commit_files_context.go @@ -23,7 +23,7 @@ func NewCommitFilesContext( onRenderToMain func(...types.OnFocusOpts) error, onFocusLost func() error, - c *types.ControllerCommon, + c *types.HelperCommon, ) *CommitFilesContext { viewModel := filetree.NewCommitFileTreeViewModel(getModel, c.Log, c.UserConfig.Gui.ShowFileTree) diff --git a/pkg/gui/context/list_context_trait.go b/pkg/gui/context/list_context_trait.go index b716bb25e..6deb5dfc1 100644 --- a/pkg/gui/context/list_context_trait.go +++ b/pkg/gui/context/list_context_trait.go @@ -10,7 +10,7 @@ import ( type ListContextTrait struct { types.Context - c *types.ControllerCommon + c *types.HelperCommon list types.IList viewTrait *ViewTrait getDisplayStrings func(startIdx int, length int) [][]string diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go index 533d97cb2..9da4721e3 100644 --- a/pkg/gui/context/local_commits_context.go +++ b/pkg/gui/context/local_commits_context.go @@ -23,7 +23,7 @@ func NewLocalCommitsContext( onRenderToMain func(...types.OnFocusOpts) error, onFocusLost func() error, - c *types.ControllerCommon, + c *types.HelperCommon, ) *LocalCommitsContext { viewModel := NewLocalCommitsViewModel(getModel) @@ -61,8 +61,14 @@ func (self *LocalCommitsContext) GetSelectedItemId() string { type LocalCommitsViewModel struct { *traits.ListCursor + getModel func() []*models.Commit + + // If this is true we limit the amount of commits we load, for the sake of keeping things fast. + // If the user attempts to scroll past the end of the list, we will load more commits. limitCommits bool - getModel func() []*models.Commit + + // If this is true we'll use git log --all when fetching the commits. + showWholeGitGraph bool } func NewLocalCommitsViewModel(getModel func() []*models.Commit) *LocalCommitsViewModel { @@ -95,3 +101,11 @@ func (self *LocalCommitsViewModel) SetLimitCommits(value bool) { func (self *LocalCommitsViewModel) GetLimitCommits() bool { return self.limitCommits } + +func (self *LocalCommitsViewModel) SetShowWholeGitGraph(value bool) { + self.showWholeGitGraph = value +} + +func (self *LocalCommitsViewModel) GetShowWholeGitGraph() bool { + return self.showWholeGitGraph +} diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go index 47c6b885f..2e75ba25a 100644 --- a/pkg/gui/context/menu_context.go +++ b/pkg/gui/context/menu_context.go @@ -21,7 +21,7 @@ func NewMenuContext( onRenderToMain func(...types.OnFocusOpts) error, onFocusLost func() error, - c *types.ControllerCommon, + c *types.HelperCommon, getOptionsMap func() map[string]string, ) *MenuContext { viewModel := NewMenuViewModel() diff --git a/pkg/gui/context/reflog_commits_context.go b/pkg/gui/context/reflog_commits_context.go index e3130c251..4a53fe393 100644 --- a/pkg/gui/context/reflog_commits_context.go +++ b/pkg/gui/context/reflog_commits_context.go @@ -23,7 +23,7 @@ func NewReflogCommitsContext( onRenderToMain func(...types.OnFocusOpts) error, onFocusLost func() error, - c *types.ControllerCommon, + c *types.HelperCommon, ) *ReflogCommitsContext { viewModel := NewReflogCommitsViewModel(getModel) diff --git a/pkg/gui/context/remote_branches_context.go b/pkg/gui/context/remote_branches_context.go index 6ec5f887b..c851c96ac 100644 --- a/pkg/gui/context/remote_branches_context.go +++ b/pkg/gui/context/remote_branches_context.go @@ -23,7 +23,7 @@ func NewRemoteBranchesContext( onRenderToMain func(...types.OnFocusOpts) error, onFocusLost func() error, - c *types.ControllerCommon, + c *types.HelperCommon, ) *RemoteBranchesContext { viewModel := NewRemoteBranchesViewModel(getModel) diff --git a/pkg/gui/context/remotes_context.go b/pkg/gui/context/remotes_context.go index 28d0db20a..2b6afdeb5 100644 --- a/pkg/gui/context/remotes_context.go +++ b/pkg/gui/context/remotes_context.go @@ -23,7 +23,7 @@ func NewRemotesContext( onRenderToMain func(...types.OnFocusOp |