mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	refactor controllers
This commit is contained in:
		| @@ -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(), "") | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewBranchesContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *BranchesContext { | ||||
| 	viewModel := NewBranchesViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewReflogCommitsContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *ReflogCommitsContext { | ||||
| 	viewModel := NewReflogCommitsViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewRemoteBranchesContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *RemoteBranchesContext { | ||||
| 	viewModel := NewRemoteBranchesViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewRemotesContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *RemotesContext { | ||||
| 	viewModel := NewRemotesViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewStashContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *StashContext { | ||||
| 	viewModel := NewStashViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewSubCommitsContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *SubCommitsContext { | ||||
| 	viewModel := NewSubCommitsViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewSubmodulesContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *SubmodulesContext { | ||||
| 	viewModel := NewSubmodulesViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,7 @@ func NewSuggestionsContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *SuggestionsContext { | ||||
| 	viewModel := NewSuggestionsViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewTagsContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *TagsContext { | ||||
| 	viewModel := NewTagsViewModel(getModel) | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func NewWorkingTreeContext( | ||||
| 	onRenderToMain func(...types.OnFocusOpts) error, | ||||
| 	onFocusLost func() error, | ||||
|  | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| ) *WorkingTreeContext { | ||||
| 	viewModel := filetree.NewFileTreeViewModel(getModel, c.Log, c.UserConfig.Gui.ShowFileTree) | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/git_commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| @@ -13,33 +12,17 @@ import ( | ||||
|  | ||||
| type BisectController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c            *types.ControllerCommon | ||||
| 	context      *context.LocalCommitsContext | ||||
| 	git          *commands.GitCommand | ||||
| 	bisectHelper *BisectHelper | ||||
|  | ||||
| 	getCommits func() []*models.Commit | ||||
| 	*controllerCommon | ||||
| } | ||||
|  | ||||
| var _ types.IController = &BisectController{} | ||||
|  | ||||
| func NewBisectController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.LocalCommitsContext, | ||||
| 	git *commands.GitCommand, | ||||
| 	bisectHelper *BisectHelper, | ||||
|  | ||||
| 	getCommits func() []*models.Commit, | ||||
| 	common *controllerCommon, | ||||
| ) *BisectController { | ||||
| 	return &BisectController{ | ||||
| 		baseController: baseController{}, | ||||
| 		c:              c, | ||||
| 		context:        context, | ||||
| 		git:            git, | ||||
| 		bisectHelper:   bisectHelper, | ||||
|  | ||||
| 		getCommits: getCommits, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -119,7 +102,7 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c | ||||
| 		{ | ||||
| 			DisplayString: self.c.Tr.Bisect.ResetOption, | ||||
| 			OnPress: func() error { | ||||
| 				return self.bisectHelper.Reset() | ||||
| 				return self.helpers.Bisect.Reset() | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| @@ -146,7 +129,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo, | ||||
| 						return self.c.Error(err) | ||||
| 					} | ||||
|  | ||||
| 					return self.bisectHelper.PostBisectCommandRefresh() | ||||
| 					return self.helpers.Bisect.PostBisectCommandRefresh() | ||||
| 				}, | ||||
| 			}, | ||||
| 			{ | ||||
| @@ -161,7 +144,7 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo, | ||||
| 						return self.c.Error(err) | ||||
| 					} | ||||
|  | ||||
| 					return self.bisectHelper.PostBisectCommandRefresh() | ||||
| 					return self.helpers.Bisect.PostBisectCommandRefresh() | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| @@ -188,7 +171,7 @@ func (self *BisectController) showBisectCompleteMessage(candidateShas []string) | ||||
| 				return self.c.Error(err) | ||||
| 			} | ||||
|  | ||||
| 			return self.bisectHelper.PostBisectCommandRefresh() | ||||
| 			return self.helpers.Bisect.PostBisectCommandRefresh() | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
| @@ -222,7 +205,7 @@ func (self *BisectController) afterBisectMarkRefresh(selectCurrent bool, waitToR | ||||
| 	} else { | ||||
| 		selectFn() | ||||
|  | ||||
| 		return self.bisectHelper.PostBisectCommandRefresh() | ||||
| 		return self.helpers.Bisect.PostBisectCommandRefresh() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -230,10 +213,10 @@ func (self *BisectController) selectCurrentBisectCommit() { | ||||
| 	info := self.git.Bisect.GetInfo() | ||||
| 	if info.GetCurrentSha() != "" { | ||||
| 		// find index of commit with that sha, move cursor to that. | ||||
| 		for i, commit := range self.getCommits() { | ||||
| 		for i, commit := range self.model.Commits { | ||||
| 			if commit.Sha == info.GetCurrentSha() { | ||||
| 				self.context.SetSelectedLineIdx(i) | ||||
| 				_ = self.context.HandleFocus() | ||||
| 				self.context().SetSelectedLineIdx(i) | ||||
| 				_ = self.context().HandleFocus() | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| @@ -242,7 +225,7 @@ func (self *BisectController) selectCurrentBisectCommit() { | ||||
|  | ||||
| func (self *BisectController) checkSelected(callback func(*models.Commit) error) func() error { | ||||
| 	return func() error { | ||||
| 		commit := self.context.GetSelected() | ||||
| 		commit := self.context().GetSelected() | ||||
| 		if commit == nil { | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -252,5 +235,9 @@ func (self *BisectController) checkSelected(callback func(*models.Commit) error) | ||||
| } | ||||
|  | ||||
| func (self *BisectController) Context() types.Context { | ||||
| 	return self.context | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| func (self *BisectController) context() *context.LocalCommitsContext { | ||||
| 	return self.contexts.BranchCommits | ||||
| } | ||||
|   | ||||
							
								
								
									
										475
									
								
								pkg/gui/controllers/branches_controller.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								pkg/gui/controllers/branches_controller.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,475 @@ | ||||
| package controllers | ||||
|  | ||||
| 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/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/utils" | ||||
| ) | ||||
|  | ||||
| type BranchesController struct { | ||||
| 	baseController | ||||
| 	*controllerCommon | ||||
| } | ||||
|  | ||||
| var _ types.IController = &BranchesController{} | ||||
|  | ||||
| func NewBranchesController( | ||||
| 	common *controllerCommon, | ||||
| ) *BranchesController { | ||||
| 	return &BranchesController{ | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 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, | ||||
| 			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, | ||||
| 			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, | ||||
| 			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, | ||||
| 			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, | ||||
| 			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), | ||||
| 			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), | ||||
| 			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), | ||||
| 			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), | ||||
| 			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), | ||||
| 			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), | ||||
| 			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), | ||||
| 			Description: self.c.Tr.LcRenameBranch, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) Context() types.Context { | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| 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() { | ||||
| 		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{}) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleCreatePullRequestPress() error { | ||||
| 	branch := self.context().GetSelected() | ||||
| 	return self.createPullRequest(branch.Name, "") | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleCreatePullRequestMenu(selectedBranch *models.Branch) error { | ||||
| 	checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() | ||||
|  | ||||
| 	return self.createPullRequestMenu(selectedBranch, checkedOutBranch) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleCopyPullRequestURLPress() error { | ||||
| 	branch := self.context().GetSelected() | ||||
|  | ||||
| 	branchExistsOnRemote := self.git.Remote.CheckRemoteBranchExists(branch.Name) | ||||
|  | ||||
| 	if !branchExistsOnRemote { | ||||
| 		return self.c.Error(errors.New(self.c.Tr.NoBranchOnRemote)) | ||||
| 	} | ||||
|  | ||||
| 	url, err := self.helpers.Host.GetPullRequestURL(branch.Name, "") | ||||
| 	if err != nil { | ||||
| 		return self.c.Error(err) | ||||
| 	} | ||||
| 	self.c.LogAction(self.c.Tr.Actions.CopyPullRequestURL) | ||||
| 	if err := self.os.CopyToClipboard(url); err != nil { | ||||
| 		return self.c.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	self.c.Toast(self.c.Tr.PullRequestURLCopiedToClipboard) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleForceCheckout() error { | ||||
| 	branch := self.context().GetSelected() | ||||
| 	message := self.c.Tr.SureForceCheckout | ||||
| 	title := self.c.Tr.ForceCheckoutBranch | ||||
|  | ||||
| 	return self.c.Ask(types.AskOpts{ | ||||
| 		Title:  title, | ||||
| 		Prompt: message, | ||||
| 		HandleConfirm: func() error { | ||||
| 			self.c.LogAction(self.c.Tr.Actions.ForceCheckoutBranch) | ||||
| 			if err := self.git.Branch.Checkout(branch.Name, git_commands.CheckoutOptions{Force: true}); err != nil { | ||||
| 				_ = self.c.Error(err) | ||||
| 			} | ||||
| 			return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleCheckoutByName() error { | ||||
| 	return self.c.Prompt(types.PromptOpts{ | ||||
| 		Title:               self.c.Tr.BranchName + ":", | ||||
| 		FindSuggestionsFunc: self.helpers.Suggestions.GetRefsSuggestionsFunc(), | ||||
| 		HandleConfirm: func(response string) error { | ||||
| 			self.c.LogAction("Checkout branch") | ||||
| 			return self.helpers.Refs.CheckoutRef(response, types.CheckoutRefOptions{ | ||||
| 				OnRefNotFound: func(ref string) error { | ||||
| 					return self.c.Ask(types.AskOpts{ | ||||
| 						Title:  self.c.Tr.BranchNotFoundTitle, | ||||
| 						Prompt: fmt.Sprintf("%s %s%s", self.c.Tr.BranchNotFoundPrompt, ref, "?"), | ||||
| 						HandleConfirm: func() error { | ||||
| 							return self.createNewBranchWithName(ref) | ||||
| 						}, | ||||
| 					}) | ||||
| 				}, | ||||
| 			}) | ||||
| 		}}, | ||||
| 	) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) createNewBranchWithName(newBranchName string) error { | ||||
| 	branch := self.context().GetSelected() | ||||
| 	if branch == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if err := self.git.Branch.New(newBranchName, branch.Name); err != nil { | ||||
| 		return self.c.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	self.context().SetSelectedLineIdx(0) | ||||
| 	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 { | ||||
| 	checkedOutBranch := self.helpers.Refs.GetCheckedOutRef() | ||||
| 	if checkedOutBranch.Name == branch.Name { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.CantDeleteCheckOutBranch) | ||||
| 	} | ||||
| 	return self.deleteNamedBranch(branch, force) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) deleteNamedBranch(selectedBranch *models.Branch, force bool) error { | ||||
| 	title := self.c.Tr.DeleteBranch | ||||
| 	var templateStr string | ||||
| 	if force { | ||||
| 		templateStr = self.c.Tr.ForceDeleteBranchMessage | ||||
| 	} else { | ||||
| 		templateStr = self.c.Tr.DeleteBranchMessage | ||||
| 	} | ||||
| 	message := utils.ResolvePlaceholderString( | ||||
| 		templateStr, | ||||
| 		map[string]string{ | ||||
| 			"selectedBranchName": selectedBranch.Name, | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	return self.c.Ask(types.AskOpts{ | ||||
| 		Title:  title, | ||||
| 		Prompt: message, | ||||
| 		HandleConfirm: func() error { | ||||
| 			self.c.LogAction(self.c.Tr.Actions.DeleteBranch) | ||||
| 			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.c.ErrorMsg(errMessage) | ||||
| 			} | ||||
| 			return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleMerge() error { | ||||
| 	selectedBranchName := self.context().GetSelected().Name | ||||
| 	return self.helpers.MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleRebaseOntoLocalBranch() error { | ||||
| 	selectedBranchName := self.context().GetSelected().Name | ||||
| 	return self.helpers.MergeAndRebase.RebaseOntoRef(selectedBranchName) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleFastForward(branch *models.Branch) error { | ||||
| 	if !branch.IsTrackingRemote() { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.FwdNoUpstream) | ||||
| 	} | ||||
| 	if !branch.RemoteBranchStoredLocally() { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.FwdNoLocalUpstream) | ||||
| 	} | ||||
| 	if branch.HasCommitsToPush() { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.FwdCommitsToPush) | ||||
| 	} | ||||
|  | ||||
| 	action := self.c.Tr.Actions.FastForwardBranch | ||||
|  | ||||
| 	message := utils.ResolvePlaceholderString( | ||||
| 		self.c.Tr.Fetching, | ||||
| 		map[string]string{ | ||||
| 			"from": fmt.Sprintf("%s/%s", branch.UpstreamRemote, branch.UpstreamBranch), | ||||
| 			"to":   branch.Name, | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	return self.c.WithLoaderPanel(message, func() error { | ||||
| 		if branch == self.helpers.Refs.GetCheckedOutRef() { | ||||
| 			self.c.LogAction(action) | ||||
|  | ||||
| 			err := self.git.Sync.Pull( | ||||
| 				git_commands.PullOptions{ | ||||
| 					RemoteName:      branch.UpstreamRemote, | ||||
| 					BranchName:      branch.Name, | ||||
| 					FastForwardOnly: true, | ||||
| 				}, | ||||
| 			) | ||||
| 			if err != nil { | ||||
| 				_ = self.c.Error(err) | ||||
| 			} | ||||
|  | ||||
| 			return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) | ||||
| 		} else { | ||||
| 			self.c.LogAction(action) | ||||
| 			err := self.git.Sync.FastForward(branch.Name, branch.UpstreamRemote, branch.UpstreamBranch) | ||||
| 			if err != nil { | ||||
| 				_ = self.c.Error(err) | ||||
| 			} | ||||
| 			_ = self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.BRANCHES}}) | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleCreateResetToBranchMenu(selectedBranch *models.Branch) error { | ||||
| 	return self.helpers.Refs.CreateGitResetMenu(selectedBranch.Name) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleRenameBranch(branch *models.Branch) error { | ||||
| 	promptForNewName := func() error { | ||||
| 		return self.c.Prompt(types.PromptOpts{ | ||||
| 			Title:          self.c.Tr.NewBranchNamePrompt + " " + branch.Name + ":", | ||||
| 			InitialContent: branch.Name, | ||||
| 			HandleConfirm: func(newBranchName string) error { | ||||
| 				self.c.LogAction(self.c.Tr.Actions.RenameBranch) | ||||
| 				if err := self.git.Branch.Rename(branch.Name, newBranchName); err != nil { | ||||
| 					return self.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 | ||||
| 				_ = self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.BRANCHES}}) | ||||
|  | ||||
| 				// now that we've got our stuff again we need to find that branch and reselect it. | ||||
| 				for i, newBranch := range self.model.Branches { | ||||
| 					if newBranch.Name == newBranchName { | ||||
| 						self.context().SetSelectedLineIdx(i) | ||||
| 						if err := self.context().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 self.c.Ask(types.AskOpts{ | ||||
| 		Title:         self.c.Tr.LcRenameBranch, | ||||
| 		Prompt:        self.c.Tr.RenameBranchWarning, | ||||
| 		HandleConfirm: promptForNewName, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) handleNewBranchOffBranch(selectedBranch *models.Branch) error { | ||||
| 	return self.helpers.Refs.NewBranch(selectedBranch.RefName(), selectedBranch.RefName(), "") | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) createPullRequestMenu(selectedBranch *models.Branch, checkedOutBranch *models.Branch) error { | ||||
| 	menuItems := make([]*types.MenuItem, 0, 4) | ||||
|  | ||||
| 	fromToDisplayStrings := func(from string, to string) []string { | ||||
| 		return []string{fmt.Sprintf("%s → %s", from, to)} | ||||
| 	} | ||||
|  | ||||
| 	menuItemsForBranch := func(branch *models.Branch) []*types.MenuItem { | ||||
| 		return []*types.MenuItem{ | ||||
| 			{ | ||||
| 				DisplayStrings: fromToDisplayStrings(branch.Name, self.c.Tr.LcDefaultBranch), | ||||
| 				OnPress: func() error { | ||||
| 					return self.createPullRequest(branch.Name, "") | ||||
| 				}, | ||||
| 			}, | ||||
| 			{ | ||||
| 				DisplayStrings: fromToDisplayStrings(branch.Name, self.c.Tr.LcSelectBranch), | ||||
| 				OnPress: func() error { | ||||
| 					return self.c.Prompt(types.PromptOpts{ | ||||
| 						Title:               branch.Name + " →", | ||||
| 						FindSuggestionsFunc: self.helpers.Suggestions.GetBranchNameSuggestionsFunc(), | ||||
| 						HandleConfirm: func(targetBranchName string) error { | ||||
| 							return self.createPullRequest(branch.Name, targetBranchName) | ||||
| 						}}, | ||||
| 					) | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if selectedBranch != checkedOutBranch { | ||||
| 		menuItems = append(menuItems, | ||||
| 			&types.MenuItem{ | ||||
| 				DisplayStrings: fromToDisplayStrings(checkedOutBranch.Name, selectedBranch.Name), | ||||
| 				OnPress: func() error { | ||||
| 					return self.createPullRequest(checkedOutBranch.Name, selectedBranch.Name) | ||||
| 				}, | ||||
| 			}, | ||||
| 		) | ||||
| 		menuItems = append(menuItems, menuItemsForBranch(checkedOutBranch)...) | ||||
| 	} | ||||
|  | ||||
| 	menuItems = append(menuItems, menuItemsForBranch(selectedBranch)...) | ||||
|  | ||||
| 	return self.c.Menu(types.CreateMenuOptions{Title: fmt.Sprintf(self.c.Tr.CreatePullRequestOptions), Items: menuItems}) | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) createPullRequest(from string, to string) error { | ||||
| 	url, err := self.helpers.Host.GetPullRequestURL(from, to) | ||||
| 	if err != nil { | ||||
| 		return self.c.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	self.c.LogAction(self.c.Tr.Actions.OpenPullRequest) | ||||
|  | ||||
| 	if err := self.os.OpenLink(url); err != nil { | ||||
| 		return self.c.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) checkSelected(callback func(*models.Branch) error) func() error { | ||||
| 	return func() error { | ||||
| 		selectedItem := self.context().GetSelected() | ||||
| 		if selectedItem == nil { | ||||
| 			return nil | ||||
| 		} | ||||
|  | ||||
| 		return callback(selectedItem) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (self *BranchesController) checkSelectedAndReal(callback func(*models.Branch) error) func() error { | ||||
| 	return func() error { | ||||
| 		selectedItem := self.context().GetSelected() | ||||
| 		if selectedItem == nil || !selectedItem.IsRealBranch() { | ||||
| 			return nil | ||||
| 		} | ||||
|  | ||||
| 		return callback(selectedItem) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										39
									
								
								pkg/gui/controllers/common.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								pkg/gui/controllers/common.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/oscommands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| ) | ||||
|  | ||||
| type controllerCommon struct { | ||||
| 	c        *types.HelperCommon | ||||
| 	os       *oscommands.OSCommand | ||||
| 	git      *commands.GitCommand | ||||
| 	helpers  *helpers.Helpers | ||||
| 	model    *types.Model | ||||
| 	contexts *context.ContextTree | ||||
| 	modes    *types.Modes | ||||
| } | ||||
|  | ||||
| func NewControllerCommon( | ||||
| 	c *types.HelperCommon, | ||||
| 	os *oscommands.OSCommand, | ||||
| 	git *commands.GitCommand, | ||||
| 	helpers *helpers.Helpers, | ||||
| 	model *types.Model, | ||||
| 	contexts *context.ContextTree, | ||||
| 	modes *types.Modes, | ||||
| ) *controllerCommon { | ||||
| 	return &controllerCommon{ | ||||
| 		c:        c, | ||||
| 		os:       os, | ||||
| 		git:      git, | ||||
| 		helpers:  helpers, | ||||
| 		model:    model, | ||||
| 		contexts: contexts, | ||||
| 		modes:    modes, | ||||
| 	} | ||||
| } | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/jesseduffield/gocui" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/git_commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/oscommands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/config" | ||||
| @@ -17,73 +17,33 @@ import ( | ||||
| ) | ||||
|  | ||||
| type FilesController struct { | ||||
| 	// I've said publicly that I'm against single-letter variable names but in this | ||||
| 	// case I would actually prefer a _zero_ letter variable name in the form of | ||||
| 	// struct embedding, but Go does not allow hiding public fields in an embedded struct | ||||
| 	// to the client | ||||
| 	c       *types.ControllerCommon | ||||
| 	context *context.WorkingTreeContext | ||||
| 	model   *types.Model | ||||
| 	git     *commands.GitCommand | ||||
| 	os      *oscommands.OSCommand | ||||
| 	baseController | ||||
| 	*controllerCommon | ||||
|  | ||||
| 	getSelectedFileNode    func() *filetree.FileNode | ||||
| 	contexts               *context.ContextTree | ||||
| 	enterSubmodule         func(submodule *models.SubmoduleConfig) error | ||||
| 	getSubmodules          func() []*models.SubmoduleConfig | ||||
| 	setCommitMessage       func(message string) | ||||
| 	getCheckedOutBranch    func() *models.Branch | ||||
| 	withGpgHandling        func(cmdObj oscommands.ICmdObj, waitingStatus string, onSuccess func() error) error | ||||
| 	getFailedCommitMessage func() string | ||||
| 	getSelectedPath        func() string | ||||
| 	switchToMergeFn        func(path string) error | ||||
| 	suggestionsHelper      ISuggestionsHelper | ||||
| 	refsHelper             IRefsHelper | ||||
| 	filesHelper            IFilesHelper | ||||
| 	workingTreeHelper      IWorkingTreeHelper | ||||
| } | ||||
|  | ||||
| var _ types.IController = &FilesController{} | ||||
|  | ||||
| func NewFilesController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.WorkingTreeContext, | ||||
| 	model *types.Model, | ||||
| 	git *commands.GitCommand, | ||||
| 	os *oscommands.OSCommand, | ||||
| 	getSelectedFileNode func() *filetree.FileNode, | ||||
| 	allContexts *context.ContextTree, | ||||
| 	common *controllerCommon, | ||||
| 	enterSubmodule func(submodule *models.SubmoduleConfig) error, | ||||
| 	getSubmodules func() []*models.SubmoduleConfig, | ||||
| 	setCommitMessage func(message string), | ||||
| 	withGpgHandling func(cmdObj oscommands.ICmdObj, waitingStatus string, onSuccess func() error) error, | ||||
| 	getFailedCommitMessage func() string, | ||||
| 	getSelectedPath func() string, | ||||
| 	switchToMergeFn func(path string) error, | ||||
| 	suggestionsHelper ISuggestionsHelper, | ||||
| 	refsHelper IRefsHelper, | ||||
| 	filesHelper IFilesHelper, | ||||
| 	workingTreeHelper IWorkingTreeHelper, | ||||
| ) *FilesController { | ||||
| 	return &FilesController{ | ||||
| 		c:                      c, | ||||
| 		context:                context, | ||||
| 		model:                  model, | ||||
| 		git:                    git, | ||||
| 		os:                     os, | ||||
| 		getSelectedFileNode:    getSelectedFileNode, | ||||
| 		contexts:               allContexts, | ||||
| 		controllerCommon:       common, | ||||
| 		enterSubmodule:         enterSubmodule, | ||||
| 		getSubmodules:          getSubmodules, | ||||
| 		setCommitMessage:       setCommitMessage, | ||||
| 		withGpgHandling:        withGpgHandling, | ||||
| 		getFailedCommitMessage: getFailedCommitMessage, | ||||
| 		getSelectedPath:        getSelectedPath, | ||||
| 		switchToMergeFn:        switchToMergeFn, | ||||
| 		suggestionsHelper:      suggestionsHelper, | ||||
| 		refsHelper:             refsHelper, | ||||
| 		filesHelper:            filesHelper, | ||||
| 		workingTreeHelper:      workingTreeHelper, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -96,7 +56,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types | ||||
| 		}, | ||||
| 		// { | ||||
| 		// 	Key:     gocui.MouseLeft, | ||||
| 		// 	Handler: func() error { return self.context.HandleClick(self.checkSelectedFileNode(self.press)) }, | ||||
| 		// 	Handler: func() error { return self.context().HandleClick(self.checkSelectedFileNode(self.press)) }, | ||||
| 		// }, | ||||
| 		{ | ||||
| 			Key:         opts.GetKey("<c-b>"), // TODO: softcode | ||||
| @@ -187,6 +147,11 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types | ||||
| 			Handler:     self.OpenMergeTool, | ||||
| 			Description: self.c.Tr.LcOpenMergeTool, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Key:         opts.GetKey(opts.Config.Files.Fetch), | ||||
| 			Handler:     self.fetch, | ||||
| 			Description: self.c.Tr.LcFetch, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -249,12 +214,12 @@ func (self *FilesController) press(node *filetree.FileNode) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return self.context.HandleFocus() | ||||
| 	return self.context().HandleFocus() | ||||
| } | ||||
|  | ||||
| func (self *FilesController) checkSelectedFileNode(callback func(*filetree.FileNode) error) func() error { | ||||
| 	return func() error { | ||||
| 		node := self.getSelectedFileNode() | ||||
| 		node := self.context().GetSelectedFileNode() | ||||
| 		if node == nil { | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -264,11 +229,15 @@ func (self *FilesController) checkSelectedFileNode(callback func(*filetree.FileN | ||||
| } | ||||
|  | ||||
| func (self *FilesController) Context() types.Context { | ||||
| 	return self.context | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| func (self *FilesController) context() *context.WorkingTreeContext { | ||||
| 	return self.contexts.Files | ||||
| } | ||||
|  | ||||
| func (self *FilesController) getSelectedFile() *models.File { | ||||
| 	node := self.getSelectedFileNode() | ||||
| 	node := self.context().GetSelectedFileNode() | ||||
| 	if node == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -280,7 +249,7 @@ func (self *FilesController) enter() error { | ||||
| } | ||||
|  | ||||
| func (self *FilesController) EnterFile(opts types.OnFocusOpts) error { | ||||
| 	node := self.getSelectedFileNode() | ||||
| 	node := self.context().GetSelectedFileNode() | ||||
| 	if node == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -291,7 +260,7 @@ func (self *FilesController) EnterFile(opts types.OnFocusOpts) error { | ||||
|  | ||||
| 	file := node.File | ||||
|  | ||||
| 	submoduleConfigs := self.getSubmodules() | ||||
| 	submoduleConfigs := self.model.Submodules | ||||
| 	if file.IsSubmodule(submoduleConfigs) { | ||||
| 		submoduleConfig := file.SubmoduleConfig(submoduleConfigs) | ||||
| 		return self.enterSubmodule(submoduleConfig) | ||||
| @@ -410,7 +379,7 @@ func (self *FilesController) commitPrefixConfigForRepo() *config.CommitPrefixCon | ||||
| } | ||||
|  | ||||
| func (self *FilesController) prepareFilesForCommit() error { | ||||
| 	noStagedFiles := !self.workingTreeHelper.AnyStagedFiles() | ||||
| 	noStagedFiles := !self.helpers.WorkingTree.AnyStagedFiles() | ||||
| 	if noStagedFiles && self.c.UserConfig.Gui.SkipNoStagedFilesWarning { | ||||
| 		self.c.LogAction(self.c.Tr.Actions.StageAllFiles) | ||||
| 		err := self.git.WorkingTree.StageAll() | ||||
| @@ -442,7 +411,7 @@ func (self *FilesController) HandleCommitPress() error { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle) | ||||
| 	} | ||||
|  | ||||
| 	if !self.workingTreeHelper.AnyStagedFiles() { | ||||
| 	if !self.helpers.WorkingTree.AnyStagedFiles() { | ||||
| 		return self.promptToStageAllAndRetry(self.HandleCommitPress) | ||||
| 	} | ||||
|  | ||||
| @@ -458,7 +427,7 @@ func (self *FilesController) HandleCommitPress() error { | ||||
| 			if err != nil { | ||||
| 				return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.LcCommitPrefixPatternError, err.Error())) | ||||
| 			} | ||||
| 			prefix := rgx.ReplaceAllString(self.getCheckedOutBranch().Name, prefixReplace) | ||||
| 			prefix := rgx.ReplaceAllString(self.helpers.Refs.GetCheckedOutRef().Name, prefixReplace) | ||||
| 			self.setCommitMessage(prefix) | ||||
| 		} | ||||
| 	} | ||||
| @@ -493,7 +462,7 @@ func (self *FilesController) handleAmendCommitPress() error { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle) | ||||
| 	} | ||||
|  | ||||
| 	if !self.workingTreeHelper.AnyStagedFiles() { | ||||
| 	if !self.helpers.WorkingTree.AnyStagedFiles() { | ||||
| 		return self.promptToStageAllAndRetry(self.handleAmendCommitPress) | ||||
| 	} | ||||
|  | ||||
| @@ -519,7 +488,7 @@ func (self *FilesController) HandleCommitEditorPress() error { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle) | ||||
| 	} | ||||
|  | ||||
| 	if !self.workingTreeHelper.AnyStagedFiles() { | ||||
| 	if !self.helpers.WorkingTree.AnyStagedFiles() { | ||||
| 		return self.promptToStageAllAndRetry(self.HandleCommitEditorPress) | ||||
| 	} | ||||
|  | ||||
| @@ -556,8 +525,8 @@ func (self *FilesController) handleStatusFilterPressed() error { | ||||
| } | ||||
|  | ||||
| func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error { | ||||
| 	self.context.FileTreeViewModel.SetFilter(filter) | ||||
| 	return self.c.PostRefreshUpdate(self.context) | ||||
| 	self.context().FileTreeViewModel.SetFilter(filter) | ||||
| 	return self.c.PostRefreshUpdate(self.context()) | ||||
| } | ||||
|  | ||||
| func (self *FilesController) edit(node *filetree.FileNode) error { | ||||
| @@ -565,16 +534,16 @@ func (self *FilesController) edit(node *filetree.FileNode) error { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.ErrCannotEditDirectory) | ||||
| 	} | ||||
|  | ||||
| 	return self.filesHelper.EditFile(node.GetPath()) | ||||
| 	return self.helpers.Files.EditFile(node.GetPath()) | ||||
| } | ||||
|  | ||||
| func (self *FilesController) Open() error { | ||||
| 	node := self.getSelectedFileNode() | ||||
| 	node := self.context().GetSelectedFileNode() | ||||
| 	if node == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return self.filesHelper.OpenFile(node.GetPath()) | ||||
| 	return self.helpers.Files.OpenFile(node.GetPath()) | ||||
| } | ||||
|  | ||||
| func (self *FilesController) switchToMerge() error { | ||||
| @@ -613,16 +582,16 @@ func (self *FilesController) stash() error { | ||||
| } | ||||
|  | ||||
| func (self *FilesController) createResetMenu() error { | ||||
| 	return self.refsHelper.CreateGitResetMenu("@{upstream}") | ||||
| 	return self.helpers.Refs.CreateGitResetMenu("@{upstream}") | ||||
| } | ||||
|  | ||||
| func (self *FilesController) handleToggleDirCollapsed() error { | ||||
| 	node := self.getSelectedFileNode() | ||||
| 	node := self.context().GetSelectedFileNode() | ||||
| 	if node == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	self.context.FileTreeViewModel.ToggleCollapsed(node.GetPath()) | ||||
| 	self.context().FileTreeViewModel.ToggleCollapsed(node.GetPath()) | ||||
|  | ||||
| 	if err := self.c.PostRefreshUpdate(self.contexts.Files); err != nil { | ||||
| 		self.c.Log.Error(err) | ||||
| @@ -632,9 +601,9 @@ func (self *FilesController) handleToggleDirCollapsed() error { | ||||
| } | ||||
|  | ||||
| func (self *FilesController) toggleTreeView() error { | ||||
| 	self.context.FileTreeViewModel.ToggleShowTree() | ||||
| 	self.context().FileTreeViewModel.ToggleShowTree() | ||||
|  | ||||
| 	return self.c.PostRefreshUpdate(self.context) | ||||
| 	return self.c.PostRefreshUpdate(self.context()) | ||||
| } | ||||
|  | ||||
| func (self *FilesController) OpenMergeTool() error { | ||||
| @@ -654,7 +623,7 @@ func (self *FilesController) ResetSubmodule(submodule *models.SubmoduleConfig) e | ||||
| 	return self.c.WithWaitingStatus(self.c.Tr.LcResettingSubmoduleStatus, func() error { | ||||
| 		self.c.LogAction(self.c.Tr.Actions.ResetSubmodule) | ||||
|  | ||||
| 		file := self.workingTreeHelper.FileForSubmodule(submodule) | ||||
| 		file := self.helpers.WorkingTree.FileForSubmodule(submodule) | ||||
| 		if file != nil { | ||||
| 			if err := self.git.WorkingTree.UnStageFile(file.Names(), file.Tracked); err != nil { | ||||
| 				return self.c.Error(err) | ||||
| @@ -673,7 +642,7 @@ func (self *FilesController) ResetSubmodule(submodule *models.SubmoduleConfig) e | ||||
| } | ||||
|  | ||||
| func (self *FilesController) handleStashSave(stashFunc func(message string) error) error { | ||||
| 	if !self.workingTreeHelper.IsWorkingTreeDirty() { | ||||
| 	if !self.helpers.WorkingTree.IsWorkingTreeDirty() { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash) | ||||
| 	} | ||||
|  | ||||
| @@ -697,3 +666,25 @@ func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) e | ||||
| 	clickedViewLineIdx := opts.Cy + opts.Oy | ||||
| 	return self.EnterFile(types.OnFocusOpts{ClickedViewName: "secondary", ClickedViewLineIdx: clickedViewLineIdx}) | ||||
| } | ||||
|  | ||||
| func (self *FilesController) fetch() error { | ||||
| 	return self.c.WithLoaderPanel(self.c.Tr.FetchWait, func() error { | ||||
| 		if err := self.fetchAux(); err != nil { | ||||
| 			_ = self.c.Error(err) | ||||
| 		} | ||||
| 		return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *FilesController) fetchAux() (err error) { | ||||
| 	self.c.LogAction("Fetch") | ||||
| 	err = self.git.Sync.Fetch(git_commands.FetchOptions{}) | ||||
|  | ||||
| 	if err != nil && strings.Contains(err.Error(), "exit status 128") { | ||||
| 		_ = self.c.ErrorMsg(self.c.Tr.PassUnameWrong) | ||||
| 	} | ||||
|  | ||||
| 	_ = self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.COMMITS, types.REMOTES, types.TAGS}, Mode: types.ASYNC}) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|   | ||||
| @@ -39,7 +39,7 @@ func (self *FilesController) remove(node *filetree.FileNode) error { | ||||
| 	} else { | ||||
| 		file := node.File | ||||
|  | ||||
| 		submodules := self.getSubmodules() | ||||
| 		submodules := self.model.Submodules | ||||
| 		if file.IsSubmodule(submodules) { | ||||
| 			submodule := file.SubmoduleConfig(submodules) | ||||
|  | ||||
|   | ||||
| @@ -1,26 +1,22 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/oscommands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/utils" | ||||
| ) | ||||
|  | ||||
| type GlobalController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c  *types.ControllerCommon | ||||
| 	os *oscommands.OSCommand | ||||
| 	*controllerCommon | ||||
| } | ||||
|  | ||||
| func NewGlobalController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	os *oscommands.OSCommand, | ||||
| 	common *controllerCommon, | ||||
| ) *GlobalController { | ||||
| 	return &GlobalController{ | ||||
| 		baseController: baseController{}, | ||||
| 		c:              c, | ||||
| 		os:             os, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -63,7 +59,7 @@ func (self *GlobalController) GetCustomCommandsHistorySuggestionsFunc() func(str | ||||
| 	// reversing so that we display the latest command first | ||||
| 	history := utils.Reverse(self.c.GetAppState().CustomCommandsHistory) | ||||
|  | ||||
| 	return FuzzySearchFunc(history) | ||||
| 	return helpers.FuzzySearchFunc(history) | ||||
| } | ||||
|  | ||||
| func (self *GlobalController) Context() types.Context { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| @@ -6,12 +6,12 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| type BisectHelper struct { | ||||
| 	c   *types.ControllerCommon | ||||
| 	c   *types.HelperCommon | ||||
| 	git *commands.GitCommand | ||||
| } | ||||
| 
 | ||||
| func NewBisectHelper( | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| 	git *commands.GitCommand, | ||||
| ) *BisectHelper { | ||||
| 	return &BisectHelper{ | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| @@ -9,25 +9,25 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| type CherryPickHelper struct { | ||||
| 	c *types.ControllerCommon | ||||
| 	c *types.HelperCommon | ||||
| 
 | ||||
| 	git *commands.GitCommand | ||||
| 
 | ||||
| 	contexts *context.ContextTree | ||||
| 	getData  func() *cherrypicking.CherryPicking | ||||
| 
 | ||||
| 	rebaseHelper *RebaseHelper | ||||
| 	rebaseHelper *MergeAndRebaseHelper | ||||
| } | ||||
| 
 | ||||
| // I'm using the analogy of copy+paste in the terminology here because it's intuitively what's going on, | ||||
| // even if in truth we're running git cherry-pick | ||||
| 
 | ||||
| func NewCherryPickHelper( | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| 	git *commands.GitCommand, | ||||
| 	contexts *context.ContextTree, | ||||
| 	getData func() *cherrypicking.CherryPicking, | ||||
| 	rebaseHelper *RebaseHelper, | ||||
| 	rebaseHelper *MergeAndRebaseHelper, | ||||
| ) *CherryPickHelper { | ||||
| 	return &CherryPickHelper{ | ||||
| 		c:            c, | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| @@ -14,13 +14,13 @@ type IFilesHelper interface { | ||||
| } | ||||
| 
 | ||||
| type FilesHelper struct { | ||||
| 	c   *types.ControllerCommon | ||||
| 	c   *types.HelperCommon | ||||
| 	git *commands.GitCommand | ||||
| 	os  *oscommands.OSCommand | ||||
| } | ||||
| 
 | ||||
| func NewFilesHelper( | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| 	git *commands.GitCommand, | ||||
| 	os *oscommands.OSCommand, | ||||
| ) *FilesHelper { | ||||
							
								
								
									
										13
									
								
								pkg/gui/controllers/helpers/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								pkg/gui/controllers/helpers/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| package helpers | ||||
|  | ||||
| type Helpers struct { | ||||
| 	Refs           *RefsHelper | ||||
| 	Bisect         *BisectHelper | ||||
| 	Suggestions    *SuggestionsHelper | ||||
| 	Files          *FilesHelper | ||||
| 	WorkingTree    *WorkingTreeHelper | ||||
| 	Tags           *TagsHelper | ||||
| 	MergeAndRebase *MergeAndRebaseHelper | ||||
| 	CherryPick     *CherryPickHelper | ||||
| 	Host           *HostHelper | ||||
| } | ||||
							
								
								
									
										46
									
								
								pkg/gui/controllers/helpers/host_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								pkg/gui/controllers/helpers/host_helper.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| package helpers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/hosting_service" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| ) | ||||
|  | ||||
| // this helper just wraps our hosting_service package | ||||
|  | ||||
| type IHostHelper interface { | ||||
| 	GetPullRequestURL(from string, to string) (string, error) | ||||
| 	GetCommitURL(commitSha string) (string, error) | ||||
| } | ||||
|  | ||||
| type HostHelper struct { | ||||
| 	c   *types.HelperCommon | ||||
| 	git *commands.GitCommand | ||||
| } | ||||
|  | ||||
| func NewHostHelper( | ||||
| 	c *types.HelperCommon, | ||||
| 	git *commands.GitCommand, | ||||
| ) *HostHelper { | ||||
| 	return &HostHelper{ | ||||
| 		c:   c, | ||||
| 		git: git, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (self *HostHelper) GetPullRequestURL(from string, to string) (string, error) { | ||||
| 	return self.getHostingServiceMgr().GetPullRequestURL(from, to) | ||||
| } | ||||
|  | ||||
| func (self *HostHelper) GetCommitURL(commitSha string) (string, error) { | ||||
| 	return self.getHostingServiceMgr().GetCommitURL(commitSha) | ||||
| } | ||||
|  | ||||
| // getting this on every request rather than storing it in state in case our remoteURL changes | ||||
| // from one invocation to the next. Note however that we're currently caching config | ||||
| // results so we might want to invalidate the cache here if it becomes a problem. | ||||
| func (self *HostHelper) getHostingServiceMgr() *hosting_service.HostingServiceMgr { | ||||
| 	remoteUrl := self.git.Config.GetRemoteURL() | ||||
| 	configServices := self.c.UserConfig.Services | ||||
| 	return hosting_service.NewHostingServiceMgr(self.c.Log, self.c.Tr, remoteUrl, configServices) | ||||
| } | ||||
| @@ -1,33 +1,38 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/git_commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/types/enums" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/utils" | ||||
| ) | ||||
| 
 | ||||
| type RebaseHelper struct { | ||||
| 	c                              *types.ControllerCommon | ||||
| type MergeAndRebaseHelper struct { | ||||
| 	c                              *types.HelperCommon | ||||
| 	contexts                       *context.ContextTree | ||||
| 	git                            *commands.GitCommand | ||||
| 	takeOverMergeConflictScrolling func() | ||||
| 	refsHelper                     *RefsHelper | ||||
| } | ||||
| 
 | ||||
| func NewRebaseHelper( | ||||
| 	c *types.ControllerCommon, | ||||
| func NewMergeAndRebaseHelper( | ||||
| 	c *types.HelperCommon, | ||||
| 	contexts *context.ContextTree, | ||||
| 	git *commands.GitCommand, | ||||
| 	takeOverMergeConflictScrolling func(), | ||||
| ) *RebaseHelper { | ||||
| 	return &RebaseHelper{ | ||||
| 	refsHelper *RefsHelper, | ||||
| ) *MergeAndRebaseHelper { | ||||
| 	return &MergeAndRebaseHelper{ | ||||
| 		c:                              c, | ||||
| 		contexts:                       contexts, | ||||
| 		git:                            git, | ||||
| 		takeOverMergeConflictScrolling: takeOverMergeConflictScrolling, | ||||
| 		refsHelper:                     refsHelper, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @@ -39,7 +44,7 @@ const ( | ||||
| 	REBASE_OPTION_SKIP     string = "skip" | ||||
| ) | ||||
| 
 | ||||
| func (self *RebaseHelper) CreateRebaseOptionsMenu() error { | ||||
| func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error { | ||||
| 	options := []string{REBASE_OPTION_CONTINUE, REBASE_OPTION_ABORT} | ||||
| 
 | ||||
| 	if self.git.Status.WorkingTreeState() == enums.REBASE_MODE_REBASING { | ||||
| @@ -68,7 +73,7 @@ func (self *RebaseHelper) CreateRebaseOptionsMenu() error { | ||||
| 	return self.c.Menu(types.CreateMenuOptions{Title: title, Items: menuItems}) | ||||
| } | ||||
| 
 | ||||
| func (self *RebaseHelper) genericMergeCommand(command string) error { | ||||
| func (self *MergeAndRebaseHelper) genericMergeCommand(command string) error { | ||||
| 	status := self.git.Status.WorkingTreeState() | ||||
| 
 | ||||
| 	if status != enums.REBASE_MODE_MERGING && status != enums.REBASE_MODE_REBASING { | ||||
| @@ -120,7 +125,7 @@ func isMergeConflictErr(errStr string) bool { | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (self *RebaseHelper) CheckMergeOrRebase(result error) error { | ||||
| func (self *MergeAndRebaseHelper) CheckMergeOrRebase(result error) error { | ||||
| 	if err := self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -154,7 +159,7 @@ func (self *RebaseHelper) CheckMergeOrRebase(result error) error { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (self *RebaseHelper) AbortMergeOrRebaseWithConfirm() error { | ||||
| func (self *MergeAndRebaseHelper) AbortMergeOrRebaseWithConfirm() error { | ||||
| 	// prompt user to confirm that they want to abort, then do it | ||||
| 	mode := self.workingTreeStateNoun() | ||||
| 	return self.c.Ask(types.AskOpts{ | ||||
| @@ -166,7 +171,7 @@ func (self *RebaseHelper) AbortMergeOrRebaseWithConfirm() error { | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (self *RebaseHelper) workingTreeStateNoun() string { | ||||
| func (self *MergeAndRebaseHelper) workingTreeStateNoun() string { | ||||
| 	workingTreeState := self.git.Status.WorkingTreeState() | ||||
| 	switch workingTreeState { | ||||
| 	case enums.REBASE_MODE_NONE: | ||||
| @@ -179,7 +184,7 @@ func (self *RebaseHelper) workingTreeStateNoun() string { | ||||
| } | ||||
| 
 | ||||
| // PromptToContinueRebase asks the user if they want to continue the rebase/merge that's in progress | ||||
| func (self *RebaseHelper) PromptToContinueRebase() error { | ||||
| func (self *MergeAndRebaseHelper) PromptToContinueRebase() error { | ||||
| 	self.takeOverMergeConflictScrolling() | ||||
| 
 | ||||
| 	return self.c.Ask(types.AskOpts{ | ||||
| @@ -190,3 +195,54 @@ func (self *RebaseHelper) PromptToContinueRebase() error { | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error { | ||||
| 	checkedOutBranch := self.refsHelper.GetCheckedOutRef().Name | ||||
| 	if ref == checkedOutBranch { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.CantRebaseOntoSelf) | ||||
| 	} | ||||
| 	prompt := utils.ResolvePlaceholderString( | ||||
| 		self.c.Tr.ConfirmRebase, | ||||
| 		map[string]string{ | ||||
| 			"checkedOutBranch": checkedOutBranch, | ||||
| 			"selectedBranch":   ref, | ||||
| 		}, | ||||
| 	) | ||||
| 
 | ||||
| 	return self.c.Ask(types.AskOpts{ | ||||
| 		Title:  self.c.Tr.RebasingTitle, | ||||
| 		Prompt: prompt, | ||||
| 		HandleConfirm: func() error { | ||||
| 			self.c.LogAction(self.c.Tr.Actions.RebaseBranch) | ||||
| 			err := self.git.Rebase.RebaseBranch(ref) | ||||
| 			return self.CheckMergeOrRebase(err) | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (self *MergeAndRebaseHelper) MergeRefIntoCheckedOutBranch(refName string) error { | ||||
| 	if self.git.Branch.IsHeadDetached() { | ||||
| 		return self.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 := self.refsHelper.GetCheckedOutRef().Name | ||||
| 	if checkedOutBranchName == refName { | ||||
| 		return self.c.ErrorMsg(self.c.Tr.CantMergeBranchIntoItself) | ||||
| 	} | ||||
| 	prompt := utils.ResolvePlaceholderString( | ||||
| 		self.c.Tr.ConfirmMerge, | ||||
| 		map[string]string{ | ||||
| 			"checkedOutBranch": checkedOutBranchName, | ||||
| 			"selectedBranch":   refName, | ||||
| 		}, | ||||
| 	) | ||||
| 
 | ||||
| 	return self.c.Ask(types.AskOpts{ | ||||
| 		Title:  self.c.Tr.MergingTitle, | ||||
| 		Prompt: prompt, | ||||
| 		HandleConfirm: func() error { | ||||
| 			self.c.LogAction(self.c.Tr.Actions.Merge) | ||||
| 			err := self.git.Branch.Merge(refName, git_commands.MergeOpts{}) | ||||
| 			return self.CheckMergeOrRebase(err) | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
| 
 | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/git_commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/style" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| @@ -14,26 +15,30 @@ import ( | ||||
| 
 | ||||
| type IRefsHelper interface { | ||||
| 	CheckoutRef(ref string, options types.CheckoutRefOptions) error | ||||
| 	GetCheckedOutRef() *models.Branch | ||||
| 	CreateGitResetMenu(ref string) error | ||||
| 	ResetToRef(ref string, strength string, envVars []string) error | ||||
| 	NewBranch(from string, fromDescription string, suggestedBranchname string) error | ||||
| } | ||||
| 
 | ||||
| type RefsHelper struct { | ||||
| 	c        *types.ControllerCommon | ||||
| 	c        *types.HelperCommon | ||||
| 	git      *commands.GitCommand | ||||
| 	contexts *context.ContextTree | ||||
| 	model    *types.Model | ||||
| } | ||||
| 
 | ||||
| func NewRefsHelper( | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| 	git *commands.GitCommand, | ||||
| 	contexts *context.ContextTree, | ||||
| 	model *types.Model, | ||||
| ) *RefsHelper { | ||||
| 	return &RefsHelper{ | ||||
| 		c:        c, | ||||
| 		git:      git, | ||||
| 		contexts: contexts, | ||||
| 		model:    model, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @@ -99,6 +104,14 @@ func (self *RefsHelper) CheckoutRef(ref string, options types.CheckoutRefOptions | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (self *RefsHelper) GetCheckedOutRef() *models.Branch { | ||||
| 	if len(self.model.Branches) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return self.model.Branches[0] | ||||
| } | ||||
| 
 | ||||
| func (self *RefsHelper) ResetToRef(ref string, strength string, envVars []string) error { | ||||
| 	if err := self.git.Commit.ResetToCommit(ref, strength, envVars); err != nil { | ||||
| 		return self.c.Error(err) | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| @@ -30,7 +30,7 @@ type ISuggestionsHelper interface { | ||||
| } | ||||
| 
 | ||||
| type SuggestionsHelper struct { | ||||
| 	c *types.ControllerCommon | ||||
| 	c *types.HelperCommon | ||||
| 
 | ||||
| 	model                *types.Model | ||||
| 	refreshSuggestionsFn func() | ||||
| @@ -39,7 +39,7 @@ type SuggestionsHelper struct { | ||||
| var _ ISuggestionsHelper = &SuggestionsHelper{} | ||||
| 
 | ||||
| func NewSuggestionsHelper( | ||||
| 	c *types.ControllerCommon, | ||||
| 	c *types.HelperCommon, | ||||
| 	model *types.Model, | ||||
| 	refreshSuggestionsFn func(), | ||||
| ) *SuggestionsHelper { | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| @@ -10,11 +10,11 @@ import ( | ||||
| // and the commits context. | ||||
| 
 | ||||
| type TagsHelper struct { | ||||
| 	c   *types.ControllerCommon | ||||
| 	c   *types.HelperCommon | ||||
| 	git *commands.GitCommand | ||||
| } | ||||
| 
 | ||||
| func NewTagsHelper(c *types.ControllerCommon, git *commands.GitCommand) *TagsHelper { | ||||
| func NewTagsHelper(c *types.HelperCommon, git *commands.GitCommand) *TagsHelper { | ||||
| 	return &TagsHelper{ | ||||
| 		c:   c, | ||||
| 		git: git, | ||||
| @@ -1,4 +1,4 @@ | ||||
| package controllers | ||||
| package helpers | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| @@ -6,10 +6,10 @@ import ( | ||||
| ) | ||||
|  | ||||
| type ListControllerFactory struct { | ||||
| 	c *types.ControllerCommon | ||||
| 	c *types.HelperCommon | ||||
| } | ||||
|  | ||||
| func NewListControllerFactory(c *types.ControllerCommon) *ListControllerFactory { | ||||
| func NewListControllerFactory(c *types.HelperCommon) *ListControllerFactory { | ||||
| 	return &ListControllerFactory{ | ||||
| 		c: c, | ||||
| 	} | ||||
| @@ -25,7 +25,7 @@ func (self *ListControllerFactory) Create(context types.IListContext) *ListContr | ||||
|  | ||||
| type ListController struct { | ||||
| 	baseController | ||||
| 	c *types.ControllerCommon | ||||
| 	c *types.HelperCommon | ||||
|  | ||||
| 	context types.IListContext | ||||
| } | ||||
|   | ||||
| @@ -4,80 +4,37 @@ import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/jesseduffield/gocui" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/hosting_service" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/oscommands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/utils" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| 	CheckoutRefFn                func(refName string, opts types.CheckoutRefOptions) error | ||||
| 	CreateGitResetMenuFn         func(refName string) error | ||||
| 	SwitchToCommitFilesContextFn func(SwitchToCommitFilesContextOpts) error | ||||
| 	GetHostingServiceMgrFn       func() *hosting_service.HostingServiceMgr | ||||
| 	PullFilesFn                  func() error | ||||
| 	CheckMergeOrRebase           func(error) error | ||||
| ) | ||||
|  | ||||
| type LocalCommitsController struct { | ||||
| 	baseController | ||||
| 	c                *types.ControllerCommon | ||||
| 	context          *context.LocalCommitsContext | ||||
| 	os               *oscommands.OSCommand | ||||
| 	git              *commands.GitCommand | ||||
| 	tagsHelper       *TagsHelper | ||||
| 	refsHelper       IRefsHelper | ||||
| 	cherryPickHelper *CherryPickHelper | ||||
| 	rebaseHelper     *RebaseHelper | ||||
| 	*controllerCommon | ||||
|  | ||||
| 	model                      *types.Model | ||||
| 	CheckMergeOrRebase         CheckMergeOrRebase | ||||
| 	pullFiles                  PullFilesFn | ||||
| 	getHostingServiceMgr       GetHostingServiceMgrFn | ||||
| 	switchToCommitFilesContext SwitchToCommitFilesContextFn | ||||
| 	getShowWholeGitGraph       func() bool | ||||
| 	setShowWholeGitGraph       func(bool) | ||||
| } | ||||
|  | ||||
| var _ types.IController = &LocalCommitsController{} | ||||
|  | ||||
| func NewLocalCommitsController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.LocalCommitsContext, | ||||
| 	os *oscommands.OSCommand, | ||||
| 	git *commands.GitCommand, | ||||
| 	tagsHelper *TagsHelper, | ||||
| 	refsHelper IRefsHelper, | ||||
| 	cherryPickHelper *CherryPickHelper, | ||||
| 	rebaseHelper *RebaseHelper, | ||||
| 	model *types.Model, | ||||
| 	CheckMergeOrRebase CheckMergeOrRebase, | ||||
| 	common *controllerCommon, | ||||
| 	pullFiles PullFilesFn, | ||||
| 	getHostingServiceMgr GetHostingServiceMgrFn, | ||||
| 	switchToCommitFilesContext SwitchToCommitFilesContextFn, | ||||
| 	getShowWholeGitGraph func() bool, | ||||
| 	setShowWholeGitGraph func(bool), | ||||
| ) *LocalCommitsController { | ||||
| 	return &LocalCommitsController{ | ||||
| 		baseController:             baseController{}, | ||||
| 		c:                          c, | ||||
| 		context:                    context, | ||||
| 		os:                         os, | ||||
| 		git:                        git, | ||||
| 		tagsHelper:                 tagsHelper, | ||||
| 		refsHelper:                 refsHelper, | ||||
| 		cherryPickHelper:           cherryPickHelper, | ||||
| 		rebaseHelper:               rebaseHelper, | ||||
| 		model:                      model, | ||||
| 		CheckMergeOrRebase:         CheckMergeOrRebase, | ||||
| 		controllerCommon:           common, | ||||
| 		pullFiles:                  pullFiles, | ||||
| 		getHostingServiceMgr:       getHostingServiceMgr, | ||||
| 		switchToCommitFilesContext: switchToCommitFilesContext, | ||||
| 		getShowWholeGitGraph:       getShowWholeGitGraph, | ||||
| 		setShowWholeGitGraph:       setShowWholeGitGraph, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -185,7 +142,7 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [ | ||||
| 		}, | ||||
| 		// { | ||||
| 		// 	Key:     gocui.MouseLeft, | ||||
| 		// 	Handler: func() error { return self.context.HandleClick(self.checkSelected(self.enter)) }, | ||||
| 		// 	Handler: func() error { return self.context().HandleClick(self.checkSelected(self.enter)) }, | ||||
| 		// }, | ||||
| 	} | ||||
|  | ||||
| @@ -305,7 +262,7 @@ func (self *LocalCommitsController) reword(commit *models.Commit) error { | ||||
| 		InitialContent: message, | ||||
| 		HandleConfirm: func(response string) error { | ||||
| 			self.c.LogAction(self.c.Tr.Actions.RewordCommit) | ||||
| 			if err := self.git.Rebase.RewordCommit(self.model.Commits, self.context.GetSelectedLineIdx(), response); err != nil { | ||||
| 			if err := self.git.Rebase.RewordCommit(self.model.Commits, self.context().GetSelectedLineIdx(), response); err != nil { | ||||
| 				return self.c.Error(err) | ||||
| 			} | ||||
|  | ||||
| @@ -325,7 +282,7 @@ func (self *LocalCommitsController) rewordEditor() error { | ||||
|  | ||||
| 	self.c.LogAction(self.c.Tr.Actions.RewordCommit) | ||||
| 	subProcess, err := self.git.Rebase.RewordCommitInEditor( | ||||
| 		self.model.Commits, self.context.GetSelectedLineIdx(), | ||||
| 		self.model.Commits, self.context().GetSelectedLineIdx(), | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return self.c.Error(err) | ||||
| @@ -388,15 +345,15 @@ func (self *LocalCommitsController) pick() error { | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) interactiveRebase(action string) error { | ||||
| 	err := self.git.Rebase.InteractiveRebase(self.model.Commits, self.context.GetSelectedLineIdx(), action) | ||||
| 	return self.CheckMergeOrRebase(err) | ||||
| 	err := self.git.Rebase.InteractiveRebase(self.model.Commits, self.context().GetSelectedLineIdx(), action) | ||||
| 	return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| } | ||||
|  | ||||
| // handleMidRebaseCommand sees if the selected commit is in fact a rebasing | ||||
| // commit meaning you are trying to edit the todo file rather than actually | ||||
| // begin a rebase. It then updates the todo file with that action | ||||
| func (self *LocalCommitsController) handleMidRebaseCommand(action string) (bool, error) { | ||||
| 	selectedCommit := self.context.GetSelected() | ||||
| 	selectedCommit := self.context().GetSelected() | ||||
| 	if selectedCommit.Status != "rebasing" { | ||||
| 		return false, nil | ||||
| 	} | ||||
| @@ -416,7 +373,7 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action string) (bool, | ||||
| 	) | ||||
|  | ||||
| 	if err := self.git.Rebase.EditRebaseTodo( | ||||
| 		self.context.GetSelectedLineIdx(), action, | ||||
| 		self.context().GetSelectedLineIdx(), action, | ||||
| 	); err != nil { | ||||
| 		return false, self.c.Error(err) | ||||
| 	} | ||||
| @@ -427,7 +384,7 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action string) (bool, | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) handleCommitMoveDown() error { | ||||
| 	index := self.context.GetSelectedLineIdx() | ||||
| 	index := self.context().GetSelectedLineIdx() | ||||
| 	commits := self.model.Commits | ||||
| 	selectedCommit := self.model.Commits[index] | ||||
| 	if selectedCommit.Status == "rebasing" { | ||||
| @@ -443,7 +400,7 @@ func (self *LocalCommitsController) handleCommitMoveDown() error { | ||||
| 		if err := self.git.Rebase.MoveTodoDown(index); err != nil { | ||||
| 			return self.c.Error(err) | ||||
| 		} | ||||
| 		self.context.MoveSelectedLine(1) | ||||
| 		self.context().MoveSelectedLine(1) | ||||
| 		return self.c.Refresh(types.RefreshOptions{ | ||||
| 			Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS}, | ||||
| 		}) | ||||
| @@ -453,14 +410,14 @@ func (self *LocalCommitsController) handleCommitMoveDown() error { | ||||
| 		self.c.LogAction(self.c.Tr.Actions.MoveCommitDown) | ||||
| 		err := self.git.Rebase.MoveCommitDown(self.model.Commits, index) | ||||
| 		if err == nil { | ||||
| 			self.context.MoveSelectedLine(1) | ||||
| 			self.context().MoveSelectedLine(1) | ||||
| 		} | ||||
| 		return self.CheckMergeOrRebase(err) | ||||
| 		return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) handleCommitMoveUp() error { | ||||
| 	index := self.context.GetSelectedLineIdx() | ||||
| 	index := self.context().GetSelectedLineIdx() | ||||
| 	if index == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -478,7 +435,7 @@ func (self *LocalCommitsController) handleCommitMoveUp() error { | ||||
| 		if err := self.git.Rebase.MoveTodoDown(index - 1); err != nil { | ||||
| 			return self.c.Error(err) | ||||
| 		} | ||||
| 		self.context.MoveSelectedLine(-1) | ||||
| 		self.context().MoveSelectedLine(-1) | ||||
| 		return self.c.Refresh(types.RefreshOptions{ | ||||
| 			Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS}, | ||||
| 		}) | ||||
| @@ -488,9 +445,9 @@ func (self *LocalCommitsController) handleCommitMoveUp() error { | ||||
| 		self.c.LogAction(self.c.Tr.Actions.MoveCommitUp) | ||||
| 		err := self.git.Rebase.MoveCommitDown(self.model.Commits, index-1) | ||||
| 		if err == nil { | ||||
| 			self.context.MoveSelectedLine(-1) | ||||
| 			self.context().MoveSelectedLine(-1) | ||||
| 		} | ||||
| 		return self.CheckMergeOrRebase(err) | ||||
| 		return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -501,8 +458,8 @@ func (self *LocalCommitsController) handleCommitAmendTo() error { | ||||
| 		HandleConfirm: func() error { | ||||
| 			return self.c.WithWaitingStatus(self.c.Tr.AmendingStatus, func() error { | ||||
| 				self.c.LogAction(self.c.Tr.Actions.AmendCommit) | ||||
| 				err := self.git.Rebase.AmendTo(self.context.GetSelected().Sha) | ||||
| 				return self.CheckMergeOrRebase(err) | ||||
| 				err := self.git.Rebase.AmendTo(self.context().GetSelected().Sha) | ||||
| 				return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 			}) | ||||
| 		}, | ||||
| 	}) | ||||
| @@ -556,7 +513,7 @@ func (self *LocalCommitsController) createRevertMergeCommitMenu(commit *models.C | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) afterRevertCommit() error { | ||||
| 	self.context.MoveSelectedLine(1) | ||||
| 	self.context().MoveSelectedLine(1) | ||||
| 	return self.c.Refresh(types.RefreshOptions{ | ||||
| 		Mode: types.BLOCK_UI, Scope: []types.RefreshableView{types.COMMITS, types.BRANCHES}, | ||||
| 	}) | ||||
| @@ -564,10 +521,9 @@ func (self *LocalCommitsController) afterRevertCommit() error { | ||||
|  | ||||
| func (self *LocalCommitsController) enter(commit *models.Commit) error { | ||||
| 	return self.switchToCommitFilesContext(SwitchToCommitFilesContextOpts{ | ||||
| 		RefName:    commit.Sha, | ||||
| 		CanRebase:  true, | ||||
| 		Context:    self.context, | ||||
| 		WindowName: "commits", | ||||
| 		RefName:   commit.Sha, | ||||
| 		CanRebase: true, | ||||
| 		Context:   self.context(), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -608,14 +564,14 @@ func (self *LocalCommitsController) handleSquashAllAboveFixupCommits(commit *mod | ||||
| 			return self.c.WithWaitingStatus(self.c.Tr.SquashingStatus, func() error { | ||||
| 				self.c.LogAction(self.c.Tr.Actions.SquashAllAboveFixupCommits) | ||||
| 				err := self.git.Rebase.SquashAllAboveFixupCommits(commit.Sha) | ||||
| 				return self.CheckMergeOrRebase(err) | ||||
| 				return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 			}) | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) handleTagCommit(commit *models.Commit) error { | ||||
| 	return self.tagsHelper.CreateTagMenu(commit.Sha, func() {}) | ||||
| 	return self.helpers.Tags.CreateTagMenu(commit.Sha, func() {}) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) handleCheckoutCommit(commit *models.Commit) error { | ||||
| @@ -624,19 +580,19 @@ func (self *LocalCommitsController) handleCheckoutCommit(commit *models.Commit) | ||||
| 		Prompt: self.c.Tr.SureCheckoutThisCommit, | ||||
| 		HandleConfirm: func() error { | ||||
| 			self.c.LogAction(self.c.Tr.Actions.CheckoutCommit) | ||||
| 			return self.refsHelper.CheckoutRef(commit.Sha, types.CheckoutRefOptions{}) | ||||
| 			return self.helpers.Refs.CheckoutRef(commit.Sha, types.CheckoutRefOptions{}) | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) handleCreateCommitResetMenu(commit *models.Commit) error { | ||||
| 	return self.refsHelper.CreateGitResetMenu(commit.Sha) | ||||
| 	return self.helpers.Refs.CreateGitResetMenu(commit.Sha) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) openSearch() error { | ||||
| 	// we usually lazyload these commits but now that we're searching we need to load them now | ||||
| 	if self.context.GetLimitCommits() { | ||||
| 		self.context.SetLimitCommits(false) | ||||
| 	if self.context().GetLimitCommits() { | ||||
| 		self.context().SetLimitCommits(false) | ||||
| 		if err := self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.COMMITS}}); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @@ -649,14 +605,14 @@ func (self *LocalCommitsController) openSearch() error { | ||||
|  | ||||
| func (self *LocalCommitsController) gotoBottom() error { | ||||
| 	// we usually lazyload these commits but now that we're jumping to the bottom we need to load them now | ||||
| 	if self.context.GetLimitCommits() { | ||||
| 		self.context.SetLimitCommits(false) | ||||
| 	if self.context().GetLimitCommits() { | ||||
| 		self.context().SetLimitCommits(false) | ||||
| 		if err := self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.COMMITS}}); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	self.context.SetSelectedLineIdx(self.context.GetItemsLength() - 1) | ||||
| 	self.context().SetSelectedLineIdx(self.context().GetItemsLength() - 1) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| @@ -684,10 +640,10 @@ func (self *LocalCommitsController) handleOpenLogMenu() error { | ||||
| 			{ | ||||
| 				DisplayString: self.c.Tr.ToggleShowGitGraphAll, | ||||
| 				OnPress: func() error { | ||||
| 					self.setShowWholeGitGraph(!self.getShowWholeGitGraph()) | ||||
| 					self.context().SetShowWholeGitGraph(!self.context().GetShowWholeGitGraph()) | ||||
|  | ||||
| 					if self.getShowWholeGitGraph() { | ||||
| 						self.context.SetLimitCommits(false) | ||||
| 					if self.context().GetShowWholeGitGraph() { | ||||
| 						self.context().SetLimitCommits(false) | ||||
| 					} | ||||
|  | ||||
| 					return self.c.WithWaitingStatus(self.c.Tr.LcLoadingCommits, func() error { | ||||
| @@ -761,9 +717,7 @@ func (self *LocalCommitsController) handleOpenLogMenu() error { | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) handleOpenCommitInBrowser(commit *models.Commit) error { | ||||
| 	hostingServiceMgr := self.getHostingServiceMgr() | ||||
|  | ||||
| 	url, err := hostingServiceMgr.GetCommitURL(commit.Sha) | ||||
| 	url, err := self.helpers.Host.GetCommitURL(commit.Sha) | ||||
| 	if err != nil { | ||||
| 		return self.c.Error(err) | ||||
| 	} | ||||
| @@ -778,7 +732,7 @@ func (self *LocalCommitsController) handleOpenCommitInBrowser(commit *models.Com | ||||
|  | ||||
| func (self *LocalCommitsController) checkSelected(callback func(*models.Commit) error) func() error { | ||||
| 	return func() error { | ||||
| 		commit := self.context.GetSelected() | ||||
| 		commit := self.context().GetSelected() | ||||
| 		if commit == nil { | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -788,21 +742,25 @@ func (self *LocalCommitsController) checkSelected(callback func(*models.Commit) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) Context() types.Context { | ||||
| 	return self.context | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) context() *context.LocalCommitsContext { | ||||
| 	return self.contexts.BranchCommits | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) newBranch(commit *models.Commit) error { | ||||
| 	return self.refsHelper.NewBranch(commit.RefName(), commit.Description(), "") | ||||
| 	return self.helpers.Refs.NewBranch(commit.RefName(), commit.Description(), "") | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) copy(commit *models.Commit) error { | ||||
| 	return self.cherryPickHelper.Copy(commit, self.model.Commits, self.context) | ||||
| 	return self.helpers.CherryPick.Copy(commit, self.model.Commits, self.context()) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) copyRange(*models.Commit) error { | ||||
| 	return self.cherryPickHelper.CopyRange(self.context.GetSelectedLineIdx(), self.model.Commits, self.context) | ||||
| 	return self.helpers.CherryPick.CopyRange(self.context().GetSelectedLineIdx(), self.model.Commits, self.context()) | ||||
| } | ||||
|  | ||||
| func (self *LocalCommitsController) paste() error { | ||||
| 	return self.cherryPickHelper.Paste() | ||||
| 	return self.helpers.CherryPick.Paste() | ||||
| } | ||||
|   | ||||
| @@ -7,22 +7,17 @@ import ( | ||||
|  | ||||
| type MenuController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c       *types.ControllerCommon | ||||
| 	context *context.MenuContext | ||||
| 	*controllerCommon | ||||
| } | ||||
|  | ||||
| var _ types.IController = &MenuController{} | ||||
|  | ||||
| func NewMenuController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.MenuContext, | ||||
| 	common *controllerCommon, | ||||
| ) *MenuController { | ||||
| 	return &MenuController{ | ||||
| 		baseController: baseController{}, | ||||
|  | ||||
| 		c:       c, | ||||
| 		context: context, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -50,7 +45,7 @@ func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types. | ||||
| } | ||||
|  | ||||
| func (self *MenuController) press() error { | ||||
| 	selectedItem := self.context.GetSelected() | ||||
| 	selectedItem := self.context().GetSelected() | ||||
|  | ||||
| 	if err := self.c.PopContext(); err != nil { | ||||
| 		return err | ||||
| @@ -64,5 +59,9 @@ func (self *MenuController) press() error { | ||||
| } | ||||
|  | ||||
| func (self *MenuController) Context() types.Context { | ||||
| 	return self.context | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| func (self *MenuController) context() *context.MenuContext { | ||||
| 	return self.contexts.Menu | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| @@ -10,30 +9,22 @@ import ( | ||||
|  | ||||
| type RemotesController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c       *types.ControllerCommon | ||||
| 	*controllerCommon | ||||
| 	context *context.RemotesContext | ||||
| 	git     *commands.GitCommand | ||||
|  | ||||
| 	setRemoteBranches func([]*models.RemoteBranch) | ||||
| 	contexts          *context.ContextTree | ||||
| } | ||||
|  | ||||
| var _ types.IController = &RemotesController{} | ||||
|  | ||||
| func NewRemotesController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.RemotesContext, | ||||
| 	git *commands.GitCommand, | ||||
| 	contexts *context.ContextTree, | ||||
| 	common *controllerCommon, | ||||
| 	setRemoteBranches func([]*models.RemoteBranch), | ||||
| ) *RemotesController { | ||||
| 	return &RemotesController{ | ||||
| 		baseController:    baseController{}, | ||||
| 		c:                 c, | ||||
| 		git:               git, | ||||
| 		contexts:          contexts, | ||||
| 		context:           context, | ||||
| 		controllerCommon:  common, | ||||
| 		context:           common.contexts.Remotes, | ||||
| 		setRemoteBranches: setRemoteBranches, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,19 +1,14 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/loaders" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| ) | ||||
|  | ||||
| type SubCommitsSwitchControllerFactory struct { | ||||
| 	c                 *types.ControllerCommon | ||||
| 	subCommitsContext *context.SubCommitsContext | ||||
| 	git               *commands.GitCommand | ||||
| 	modes             *types.Modes | ||||
| 	setSubCommits     func([]*models.Commit) | ||||
| 	controllerCommon *controllerCommon | ||||
| 	setSubCommits    func([]*models.Commit) | ||||
| } | ||||
|  | ||||
| var _ types.IController = &SubCommitsSwitchController{} | ||||
| @@ -25,40 +20,28 @@ type ContextWithRefName interface { | ||||
|  | ||||
| type SubCommitsSwitchController struct { | ||||
| 	baseController | ||||
| 	*controllerCommon | ||||
| 	context ContextWithRefName | ||||
|  | ||||
| 	c                 *types.ControllerCommon | ||||
| 	context           ContextWithRefName | ||||
| 	subCommitsContext *context.SubCommitsContext | ||||
| 	git               *commands.GitCommand | ||||
| 	modes             *types.Modes | ||||
| 	setSubCommits     func([]*models.Commit) | ||||
| 	setSubCommits func([]*models.Commit) | ||||
| } | ||||
|  | ||||
| func NewSubCommitsSwitchControllerFactory( | ||||
| 	c *types.ControllerCommon, | ||||
| 	subCommitsContext *context.SubCommitsContext, | ||||
| 	git *commands.GitCommand, | ||||
| 	modes *types.Modes, | ||||
| 	common *controllerCommon, | ||||
| 	setSubCommits func([]*models.Commit), | ||||
| ) *SubCommitsSwitchControllerFactory { | ||||
| 	return &SubCommitsSwitchControllerFactory{ | ||||
| 		c:                 c, | ||||
| 		subCommitsContext: subCommitsContext, | ||||
| 		git:               git, | ||||
| 		modes:             modes, | ||||
| 		setSubCommits:     setSubCommits, | ||||
| 		controllerCommon: common, | ||||
| 		setSubCommits:    setSubCommits, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (self *SubCommitsSwitchControllerFactory) Create(context ContextWithRefName) *SubCommitsSwitchController { | ||||
| 	return &SubCommitsSwitchController{ | ||||
| 		baseController:    baseController{}, | ||||
| 		c:                 self.c, | ||||
| 		context:           context, | ||||
| 		subCommitsContext: self.subCommitsContext, | ||||
| 		git:               self.git, | ||||
| 		modes:             self.modes, | ||||
| 		setSubCommits:     self.setSubCommits, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: self.controllerCommon, | ||||
| 		context:          context, | ||||
| 		setSubCommits:    self.setSubCommits, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -94,10 +77,10 @@ func (self *SubCommitsSwitchController) viewCommits() error { | ||||
| 	} | ||||
|  | ||||
| 	self.setSubCommits(commits) | ||||
| 	self.subCommitsContext.SetSelectedLineIdx(0) | ||||
| 	self.subCommitsContext.SetParentContext(self.context) | ||||
| 	self.contexts.SubCommits.SetSelectedLineIdx(0) | ||||
| 	self.contexts.SubCommits.SetParentContext(self.context) | ||||
|  | ||||
| 	return self.c.PushContext(self.subCommitsContext) | ||||
| 	return self.c.PushContext(self.contexts.SubCommits) | ||||
| } | ||||
|  | ||||
| func (self *SubCommitsSwitchController) Context() types.Context { | ||||
|   | ||||
| @@ -5,7 +5,6 @@ import ( | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/style" | ||||
| @@ -14,10 +13,7 @@ import ( | ||||
|  | ||||
| type SubmodulesController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c       *types.ControllerCommon | ||||
| 	context *context.SubmodulesContext | ||||
| 	git     *commands.GitCommand | ||||
| 	*controllerCommon | ||||
|  | ||||
| 	enterSubmodule func(submodule *models.SubmoduleConfig) error | ||||
| } | ||||
| @@ -25,17 +21,13 @@ type SubmodulesController struct { | ||||
| var _ types.IController = &SubmodulesController{} | ||||
|  | ||||
| func NewSubmodulesController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.SubmodulesContext, | ||||
| 	git *commands.GitCommand, | ||||
| 	controllerCommon *controllerCommon, | ||||
| 	enterSubmodule func(submodule *models.SubmoduleConfig) error, | ||||
| ) *SubmodulesController { | ||||
| 	return &SubmodulesController{ | ||||
| 		baseController: baseController{}, | ||||
| 		c:              c, | ||||
| 		context:        context, | ||||
| 		git:            git, | ||||
| 		enterSubmodule: enterSubmodule, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: controllerCommon, | ||||
| 		enterSubmodule:   enterSubmodule, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -79,7 +71,7 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []* | ||||
| 		}, | ||||
| 		// { | ||||
| 		// 	Key:     gocui.MouseLeft, | ||||
| 		// 	Handler: func() error { return self.context.HandleClick(self.checkSelected(self.enter)) }, | ||||
| 		// 	Handler: func() error { return self.context().HandleClick(self.checkSelected(self.enter)) }, | ||||
| 		// }, | ||||
| 	} | ||||
| } | ||||
| @@ -227,7 +219,7 @@ func (self *SubmodulesController) remove(submodule *models.SubmoduleConfig) erro | ||||
|  | ||||
| func (self *SubmodulesController) checkSelected(callback func(*models.SubmoduleConfig) error) func() error { | ||||
| 	return func() error { | ||||
| 		submodule := self.context.GetSelected() | ||||
| 		submodule := self.context().GetSelected() | ||||
| 		if submodule == nil { | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -237,5 +229,9 @@ func (self *SubmodulesController) checkSelected(callback func(*models.SubmoduleC | ||||
| } | ||||
|  | ||||
| func (self *SubmodulesController) Context() types.Context { | ||||
| 	return self.context | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| func (self *SubmodulesController) context() *context.SubmodulesContext { | ||||
| 	return self.contexts.Submodules | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/git_commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| @@ -12,35 +11,22 @@ import ( | ||||
|  | ||||
| type SyncController struct { | ||||
| 	baseController | ||||
| 	*controllerCommon | ||||
|  | ||||
| 	c   *types.ControllerCommon | ||||
| 	git *commands.GitCommand | ||||
|  | ||||
| 	getCheckedOutBranch func() *models.Branch | ||||
| 	suggestionsHelper   ISuggestionsHelper | ||||
| 	getSuggestedRemote  func() string | ||||
| 	CheckMergeOrRebase  func(error) error | ||||
| 	getSuggestedRemote func() string | ||||
| } | ||||
|  | ||||
| var _ types.IController = &SyncController{} | ||||
|  | ||||
| func NewSyncController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	git *commands.GitCommand, | ||||
| 	getCheckedOutBranch func() *models.Branch, | ||||
| 	suggestionsHelper ISuggestionsHelper, | ||||
| 	common *controllerCommon, | ||||
| 	getSuggestedRemote func() string, | ||||
| 	CheckMergeOrRebase func(error) error, | ||||
| ) *SyncController { | ||||
| 	return &SyncController{ | ||||
| 		baseController: baseController{}, | ||||
| 		c:              c, | ||||
| 		git:            git, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
|  | ||||
| 		getCheckedOutBranch: getCheckedOutBranch, | ||||
| 		suggestionsHelper:   suggestionsHelper, | ||||
| 		getSuggestedRemote:  getSuggestedRemote, | ||||
| 		CheckMergeOrRebase:  CheckMergeOrRebase, | ||||
| 		getSuggestedRemote: getSuggestedRemote, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -75,7 +61,7 @@ func (self *SyncController) HandlePull() error { | ||||
|  | ||||
| func (self *SyncController) branchCheckedOut(f func(*models.Branch) error) func() error { | ||||
| 	return func() error { | ||||
| 		currentBranch := self.getCheckedOutBranch() | ||||
| 		currentBranch := self.helpers.Refs.GetCheckedOutRef() | ||||
| 		if currentBranch == nil { | ||||
| 			// need to wait for branches to refresh | ||||
| 			return nil | ||||
| @@ -160,7 +146,7 @@ func (self *SyncController) promptForUpstream(currentBranch *models.Branch, onCo | ||||
| 	return self.c.Prompt(types.PromptOpts{ | ||||
| 		Title:               self.c.Tr.EnterUpstream, | ||||
| 		InitialContent:      suggestedRemote + " " + currentBranch.Name, | ||||
| 		FindSuggestionsFunc: self.suggestionsHelper.GetRemoteBranchesSuggestionsFunc(" "), | ||||
| 		FindSuggestionsFunc: self.helpers.Suggestions.GetRemoteBranchesSuggestionsFunc(" "), | ||||
| 		HandleConfirm:       onConfirm, | ||||
| 	}) | ||||
| } | ||||
| @@ -189,7 +175,7 @@ func (self *SyncController) pullWithLock(opts PullFilesOptions) error { | ||||
| 		}, | ||||
| 	) | ||||
|  | ||||
| 	return self.CheckMergeOrRebase(err) | ||||
| 	return self.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| } | ||||
|  | ||||
| type pushOpts struct { | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| @@ -10,43 +9,17 @@ import ( | ||||
|  | ||||
| type TagsController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c          *types.ControllerCommon | ||||
| 	context    *context.TagsContext | ||||
| 	git        *commands.GitCommand | ||||
| 	contexts   *context.ContextTree | ||||
| 	tagsHelper *TagsHelper | ||||
|  | ||||
| 	refsHelper        IRefsHelper | ||||
| 	suggestionsHelper ISuggestionsHelper | ||||
|  | ||||
| 	switchToSubCommitsContext func(string) error | ||||
| 	*controllerCommon | ||||
| } | ||||
|  | ||||
| var _ types.IController = &TagsController{} | ||||
|  | ||||
| func NewTagsController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	context *context.TagsContext, | ||||
| 	git *commands.GitCommand, | ||||
| 	contexts *context.ContextTree, | ||||
| 	tagsHelper *TagsHelper, | ||||
| 	refsHelper IRefsHelper, | ||||
| 	suggestionsHelper ISuggestionsHelper, | ||||
|  | ||||
| 	switchToSubCommitsContext func(string) error, | ||||
| 	common *controllerCommon, | ||||
| ) *TagsController { | ||||
| 	return &TagsController{ | ||||
| 		baseController:    baseController{}, | ||||
| 		c:                 c, | ||||
| 		context:           context, | ||||
| 		git:               git, | ||||
| 		contexts:          contexts, | ||||
| 		tagsHelper:        tagsHelper, | ||||
| 		refsHelper:        refsHelper, | ||||
| 		suggestionsHelper: suggestionsHelper, | ||||
|  | ||||
| 		switchToSubCommitsContext: switchToSubCommitsContext, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -85,7 +58,7 @@ func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types. | ||||
|  | ||||
| func (self *TagsController) checkout(tag *models.Tag) error { | ||||
| 	self.c.LogAction(self.c.Tr.Actions.CheckoutTag) | ||||
| 	if err := self.refsHelper.CheckoutRef(tag.Name, types.CheckoutRefOptions{}); err != nil { | ||||
| 	if err := self.helpers.Refs.CheckoutRef(tag.Name, types.CheckoutRefOptions{}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return self.c.PushContext(self.contexts.Branches) | ||||
| @@ -123,7 +96,7 @@ func (self *TagsController) push(tag *models.Tag) error { | ||||
| 	return self.c.Prompt(types.PromptOpts{ | ||||
| 		Title:               title, | ||||
| 		InitialContent:      "origin", | ||||
| 		FindSuggestionsFunc: self.suggestionsHelper.GetRemoteSuggestionsFunc(), | ||||
| 		FindSuggestionsFunc: self.helpers.Suggestions.GetRemoteSuggestionsFunc(), | ||||
| 		HandleConfirm: func(response string) error { | ||||
| 			return self.c.WithWaitingStatus(self.c.Tr.PushingTagStatus, func() error { | ||||
| 				self.c.LogAction(self.c.Tr.Actions.PushTag) | ||||
| @@ -139,17 +112,17 @@ func (self *TagsController) push(tag *models.Tag) error { | ||||
| } | ||||
|  | ||||
| func (self *TagsController) createResetMenu(tag *models.Tag) error { | ||||
| 	return self.refsHelper.CreateGitResetMenu(tag.Name) | ||||
| 	return self.helpers.Refs.CreateGitResetMenu(tag.Name) | ||||
| } | ||||
|  | ||||
| func (self *TagsController) create() error { | ||||
| 	// leaving commit SHA blank so that we're just creating the tag for the current commit | ||||
| 	return self.tagsHelper.CreateTagMenu("", func() { self.context.SetSelectedLineIdx(0) }) | ||||
| 	return self.helpers.Tags.CreateTagMenu("", func() { self.context().SetSelectedLineIdx(0) }) | ||||
| } | ||||
|  | ||||
| func (self *TagsController) withSelectedTag(f func(tag *models.Tag) error) func() error { | ||||
| 	return func() error { | ||||
| 		tag := self.context.GetSelected() | ||||
| 		tag := self.context().GetSelected() | ||||
| 		if tag == nil { | ||||
| 			return nil | ||||
| 		} | ||||
| @@ -159,5 +132,9 @@ func (self *TagsController) withSelectedTag(f func(tag *models.Tag) error) func( | ||||
| } | ||||
|  | ||||
| func (self *TagsController) Context() types.Context { | ||||
| 	return self.context | ||||
| 	return self.context() | ||||
| } | ||||
|  | ||||
| func (self *TagsController) context() *context.TagsContext { | ||||
| 	return self.contexts.Tags | ||||
| } | ||||
|   | ||||
| @@ -6,8 +6,7 @@ import ( | ||||
|  | ||||
| // all fields mandatory (except `CanRebase` because it's boolean) | ||||
| type SwitchToCommitFilesContextOpts struct { | ||||
| 	RefName    string | ||||
| 	CanRebase  bool | ||||
| 	Context    types.Context | ||||
| 	WindowName string | ||||
| 	RefName   string | ||||
| 	CanRebase bool | ||||
| 	Context   types.Context | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/types/enums" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/utils" | ||||
| @@ -20,34 +18,17 @@ import ( | ||||
|  | ||||
| type UndoController struct { | ||||
| 	baseController | ||||
|  | ||||
| 	c   *types.ControllerCommon | ||||
| 	git *commands.GitCommand | ||||
|  | ||||
| 	refsHelper        IRefsHelper | ||||
| 	workingTreeHelper IWorkingTreeHelper | ||||
|  | ||||
| 	getFilteredReflogCommits func() []*models.Commit | ||||
| 	*controllerCommon | ||||
| } | ||||
|  | ||||
| var _ types.IController = &UndoController{} | ||||
|  | ||||
| func NewUndoController( | ||||
| 	c *types.ControllerCommon, | ||||
| 	git *commands.GitCommand, | ||||
| 	refsHelper IRefsHelper, | ||||
| 	workingTreeHelper IWorkingTreeHelper, | ||||
|  | ||||
| 	getFilteredReflogCommits func() []*models.Commit, | ||||
| 	common *controllerCommon, | ||||
| ) *UndoController { | ||||
| 	return &UndoController{ | ||||
| 		baseController:    baseController{}, | ||||
| 		c:                 c, | ||||
| 		git:               git, | ||||
| 		refsHelper:        refsHelper, | ||||
| 		workingTreeHelper: workingTreeHelper, | ||||
|  | ||||
| 		getFilteredReflogCommits: getFilteredReflogCommits, | ||||
| 		baseController:   baseController{}, | ||||
| 		controllerCommon: common, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -109,7 +90,7 @@ func (self *UndoController) reflogUndo() error { | ||||
| 			}) | ||||
| 		case CHECKOUT: | ||||
| 			self.c.LogAction(self.c.Tr.Actions.Undo) | ||||
| 			return true, self.refsHelper.CheckoutRef(action.from, types.CheckoutRefOptions{ | ||||
| 			return true, self.helpers.Refs.CheckoutRef(action.from, types.CheckoutRefOptions{ | ||||
| 				EnvVars:       undoEnvVars, | ||||
| 				WaitingStatus: undoingStatus, | ||||
| 			}) | ||||
| @@ -147,7 +128,7 @@ func (self *UndoController) reflogRedo() error { | ||||
| 			}) | ||||
| 		case CHECKOUT: | ||||
| 			self.c.LogAction(self.c.Tr.Actions.Redo) | ||||
| 			return true, self.refsHelper.CheckoutRef(action.to, types.CheckoutRefOptions{ | ||||
| 			return true, self.helpers.Refs.CheckoutRef(action.to, types.CheckoutRefOptions{ | ||||
| 				EnvVars:       redoEnvVars, | ||||
| 				WaitingStatus: redoingStatus, | ||||
| 			}) | ||||
| @@ -168,7 +149,7 @@ func (self *UndoController) reflogRedo() error { | ||||
| // Though we might support this later, hence the use of the CURRENT_REBASE action kind. | ||||
| func (self *UndoController) parseReflogForActions(onUserAction func(counter int, action reflogAction) (bool, error)) error { | ||||
| 	counter := 0 | ||||
| 	reflogCommits := self.getFilteredReflogCommits() | ||||
| 	reflogCommits := self.model.FilteredReflogCommits | ||||
| 	rebaseFinishCommitSha := "" | ||||
| 	var action *reflogAction | ||||
| 	for reflogCommitIdx, reflogCommit := range reflogCommits { | ||||
| @@ -222,14 +203,14 @@ type hardResetOptions struct { | ||||
| // only to be used in the undo flow for now (does an autostash) | ||||
| func (self *UndoController) hardResetWithAutoStash(commitSha string, options hardResetOptions) error { | ||||
| 	reset := func() error { | ||||
| 		if err := self.refsHelper.ResetToRef(commitSha, "hard", options.EnvVars); err != nil { | ||||
| 		if err := self.helpers.Refs.ResetToRef(commitSha, "hard", options.EnvVars); err != nil { | ||||
| 			return self.c.Error(err) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// if we have any modified tracked files we need to ask the user if they want us to stash for them | ||||
| 	dirtyWorkingTree := self.workingTreeHelper.IsWorkingTreeDirty() | ||||
| 	dirtyWorkingTree := self.helpers.WorkingTree.IsWorkingTreeDirty() | ||||
| 	if dirtyWorkingTree { | ||||
| 		// offer to autostash changes | ||||
| 		return self.c.Ask(types.AskOpts{ | ||||
|   | ||||
| @@ -54,7 +54,7 @@ func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (s | ||||
| 		SelectedCommitFile:     gui.getSelectedCommitFile(), | ||||
| 		SelectedCommitFilePath: gui.getSelectedCommitFilePath(), | ||||
| 		SelectedSubCommit:      gui.State.Contexts.SubCommits.GetSelected(), | ||||
| 		CheckedOutBranch:       gui.getCheckedOutBranch(), | ||||
| 		CheckedOutBranch:       gui.helpers.Refs.GetCheckedOutRef(), | ||||
| 		PromptResponses:        promptResponses, | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -189,19 +189,6 @@ func (gui *Gui) handleMouseDownMain() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (gui *Gui) fetch() (err error) { | ||||
| 	gui.c.LogAction("Fetch") | ||||
| 	err = gui.git.Sync.Fetch(git_commands.FetchOptions{}) | ||||
|  | ||||
| 	if err != nil && strings.Contains(err.Error(), "exit status 128") { | ||||
| 		_ = gui.c.ErrorMsg(gui.c.Tr.PassUnameWrong) | ||||
| 	} | ||||
|  | ||||
| 	_ = gui.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.COMMITS, types.REMOTES, types.TAGS}, Mode: types.ASYNC}) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (gui *Gui) backgroundFetch() (err error) { | ||||
| 	err = gui.git.Sync.Fetch(git_commands.FetchOptions{Background: true}) | ||||
|  | ||||
|   | ||||
							
								
								
									
										149
									
								
								pkg/gui/gui.go
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								pkg/gui/gui.go
									
									
									
									
									
								
							| @@ -20,6 +20,7 @@ import ( | ||||
| 	"github.com/jesseduffield/lazygit/pkg/config" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/context" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/controllers" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/lbl" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking" | ||||
| @@ -67,17 +68,6 @@ func NewContextManager(initialContext types.Context) ContextManager { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type Helpers struct { | ||||
| 	Refs        *controllers.RefsHelper | ||||
| 	Bisect      *controllers.BisectHelper | ||||
| 	Suggestions *controllers.SuggestionsHelper | ||||
| 	Files       *controllers.FilesHelper | ||||
| 	WorkingTree *controllers.WorkingTreeHelper | ||||
| 	Tags        *controllers.TagsHelper | ||||
| 	Rebase      *controllers.RebaseHelper | ||||
| 	CherryPick  *controllers.CherryPickHelper | ||||
| } | ||||
|  | ||||
| type Repo string | ||||
|  | ||||
| // Gui wraps the gocui Gui object which handles rendering and events | ||||
| @@ -144,9 +134,6 @@ type Gui struct { | ||||
| 	// flag as to whether or not the diff view should ignore whitespace | ||||
| 	IgnoreWhitespaceInDiffView bool | ||||
|  | ||||
| 	// if this is true, we'll load our commits using `git log --all` | ||||
| 	ShowWholeGitGraph bool | ||||
|  | ||||
| 	// we use this to decide whether we'll return to the original directory that | ||||
| 	// lazygit was opened in, or if we'll retain the one we're currently in. | ||||
| 	RetainOriginalDir bool | ||||
| @@ -161,8 +148,8 @@ type Gui struct { | ||||
| 	// process | ||||
| 	InitialDir string | ||||
|  | ||||
| 	c       *types.ControllerCommon | ||||
| 	helpers *Helpers | ||||
| 	c       *types.HelperCommon | ||||
| 	helpers *helpers.Helpers | ||||
| } | ||||
|  | ||||
| // we keep track of some stuff from one render to the next to see if certain | ||||
| @@ -488,11 +475,11 @@ func NewGui( | ||||
| 	) | ||||
|  | ||||
| 	guiCommon := &guiCommon{gui: gui, IPopupHandler: gui.PopupHandler} | ||||
| 	controllerCommon := &types.ControllerCommon{IGuiCommon: guiCommon, Common: cmn} | ||||
| 	helperCommon := &types.HelperCommon{IGuiCommon: guiCommon, Common: cmn} | ||||
|  | ||||
| 	// storing this stuff on the gui for now to ease refactoring | ||||
| 	// TODO: reset these controllers upon changing repos due to state changing | ||||
| 	gui.c = controllerCommon | ||||
| 	gui.c = helperCommon | ||||
|  | ||||
| 	authors.SetCustomAuthors(gui.UserConfig.Gui.AuthorColors) | ||||
| 	presentation.SetCustomBranches(gui.UserConfig.Gui.BranchColors) | ||||
| @@ -503,21 +490,23 @@ func NewGui( | ||||
| func (gui *Gui) resetControllers() { | ||||
| 	controllerCommon := gui.c | ||||
| 	osCommand := gui.os | ||||
| 	rebaseHelper := controllers.NewRebaseHelper(controllerCommon, gui.State.Contexts, gui.git, gui.takeOverMergeConflictScrolling) | ||||
| 	model := gui.State.Model | ||||
| 	gui.helpers = &Helpers{ | ||||
| 		Refs: controllers.NewRefsHelper( | ||||
| 			controllerCommon, | ||||
| 			gui.git, | ||||
| 			gui.State.Contexts, | ||||
| 		), | ||||
| 		Bisect:      controllers.NewBisectHelper(controllerCommon, gui.git), | ||||
| 		Suggestions: controllers.NewSuggestionsHelper(controllerCommon, model, gui.refreshSuggestions), | ||||
| 		Files:       controllers.NewFilesHelper(controllerCommon, gui.git, osCommand), | ||||
| 		WorkingTree: controllers.NewWorkingTreeHelper(model), | ||||
| 		Tags:        controllers.NewTagsHelper(controllerCommon, gui.git), | ||||
| 		Rebase:      rebaseHelper, | ||||
| 		CherryPick: controllers.NewCherryPickHelper( | ||||
| 	refsHelper := helpers.NewRefsHelper( | ||||
| 		controllerCommon, | ||||
| 		gui.git, | ||||
| 		gui.State.Contexts, | ||||
| 		model, | ||||
| 	) | ||||
| 	rebaseHelper := helpers.NewMergeAndRebaseHelper(controllerCommon, gui.State.Contexts, gui.git, gui.takeOverMergeConflictScrolling, refsHelper) | ||||
| 	gui.helpers = &helpers.Helpers{ | ||||
| 		Refs:           refsHelper, | ||||
| 		Bisect:         helpers.NewBisectHelper(controllerCommon, gui.git), | ||||
| 		Suggestions:    helpers.NewSuggestionsHelper(controllerCommon, model, gui.refreshSuggestions), | ||||
| 		Files:          helpers.NewFilesHelper(controllerCommon, gui.git, osCommand), | ||||
| 		WorkingTree:    helpers.NewWorkingTreeHelper(model), | ||||
| 		Tags:           helpers.NewTagsHelper(controllerCommon, gui.git), | ||||
| 		MergeAndRebase: rebaseHelper, | ||||
| 		CherryPick: helpers.NewCherryPickHelper( | ||||
| 			controllerCommon, | ||||
| 			gui.git, | ||||
| 			gui.State.Contexts, | ||||
| @@ -526,109 +515,58 @@ func (gui *Gui) resetControllers() { | ||||
| 		), | ||||
| 	} | ||||
|  | ||||
| 	syncController := controllers.NewSyncController( | ||||
| 	common := controllers.NewControllerCommon( | ||||
| 		controllerCommon, | ||||
| 		osCommand, | ||||
| 		gui.git, | ||||
| 		gui.getCheckedOutBranch, | ||||
| 		gui.helpers.Suggestions, | ||||
| 		gui.helpers, | ||||
| 		model, | ||||
| 		gui.State.Contexts, | ||||
| 		gui.State.Modes, | ||||
| 	) | ||||
|  | ||||
| 	syncController := controllers.NewSyncController( | ||||
| 		common, | ||||
| 		gui.getSuggestedRemote, | ||||
| 		gui.helpers.Rebase.CheckMergeOrRebase, | ||||
| 	) | ||||
|  | ||||
| 	submodulesController := controllers.NewSubmodulesController( | ||||
| 		controllerCommon, | ||||
| 		gui.State.Contexts.Submodules, | ||||
| 		gui.git, | ||||
| 		common, | ||||
| 		gui.enterSubmodule, | ||||
| 	) | ||||
|  | ||||
| 	bisectController := controllers.NewBisectController( | ||||
| 		controllerCommon, | ||||
| 		gui.State.Contexts.BranchCommits, | ||||
| 		gui.git, | ||||
| 		gui.helpers.Bisect, | ||||
| 		func() []*models.Commit { return gui.State.Model.Commits }, | ||||
| 	) | ||||
| 	bisectController := controllers.NewBisectController(common) | ||||
|  | ||||
| 	gui.Controllers = Controllers{ | ||||
| 		Submodules: submodulesController, | ||||
| 		Global: controllers.NewGlobalController( | ||||
| 			controllerCommon, | ||||
| 			osCommand, | ||||
| 		), | ||||
| 		Global:     controllers.NewGlobalController(common), | ||||
| 		Files: controllers.NewFilesController( | ||||
| 			controllerCommon, | ||||
| 			gui.State.Contexts.Files, | ||||
| 			model, | ||||
| 			gui.git, | ||||
| 			osCommand, | ||||
| 			gui.getSelectedFileNode, | ||||
| 			gui.State.Contexts, | ||||
| 			common, | ||||
| 			gui.enterSubmodule, | ||||
| 			func() []*models.SubmoduleConfig { return gui.State.Model.Submodules }, | ||||
| 			gui.getSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitMessage }), | ||||
| 			gui.withGpgHandling, | ||||
| 			func() string { return gui.State.failedCommitMessage }, | ||||
| 			gui.getSelectedPath, | ||||
| 			gui.switchToMerge, | ||||
| 			gui.helpers.Suggestions, | ||||
| 			gui.helpers.Refs, | ||||
| 			gui.helpers.Files, | ||||
| 			gui.helpers.WorkingTree, | ||||
| 		), | ||||
| 		Tags: controllers.NewTagsController( | ||||
| 			controllerCommon, | ||||
| 			gui.State.Contexts.Tags, | ||||
| 			gui.git, | ||||
| 			gui.State.Contexts, | ||||
| 			gui.helpers.Tags, | ||||
| 			gui.helpers.Refs, | ||||
| 			gui.helpers.Suggestions, | ||||
| 			gui.switchToSubCommitsContext, | ||||
| 		), | ||||
| 		Tags: controllers.NewTagsController(common), | ||||
| 		LocalCommits: controllers.NewLocalCommitsController( | ||||
| 			controllerCommon, | ||||
| 			gui.State.Contexts.BranchCommits, | ||||
| 			osCommand, | ||||
| 			gui.git, | ||||
| 			gui.helpers.Tags, | ||||
| 			gui.helpers.Refs, | ||||
| 			gui.helpers.CherryPick, | ||||
| 			gui.helpers.Rebase, | ||||
| 			model, | ||||
| 			gui.helpers.Rebase.CheckMergeOrRebase, | ||||
| 			common, | ||||
| 			syncController.HandlePull, | ||||
| 			gui.getHostingServiceMgr, | ||||
| 			gui.SwitchToCommitFilesContext, | ||||
| 			func() bool { return gui.ShowWholeGitGraph }, | ||||
| 			func(value bool) { gui.ShowWholeGitGraph = value }, | ||||
| 		), | ||||
| 		Remotes: controllers.NewRemotesController( | ||||
| 			controllerCommon, | ||||
| 			gui.State.Contexts.Remotes, | ||||
| 			gui.git, | ||||
| 			gui.State.Contexts, | ||||
| 			common, | ||||
| 			func(branches []*models.RemoteBranch) { gui.State.Model.RemoteBranches = branches }, | ||||
| 		), | ||||
| 		Menu: controllers.NewMenuController( | ||||
| 			controllerCommon, | ||||
| 			gui.State.Contexts.Menu, | ||||
| 		), | ||||
| 		Undo: controllers.NewUndoController( | ||||
| 			controllerCommon, | ||||
| 			gui.git, | ||||
| 			gui.helpers.Refs, | ||||
| 			gui.helpers.WorkingTree, | ||||
| 			func() []*models.Commit { return gui.State.Model.FilteredReflogCommits }, | ||||
| 		), | ||||
| 		Menu: controllers.NewMenuController(common), | ||||
| 		Undo: controllers.NewUndoController(common), | ||||
| 		Sync: syncController, | ||||
| 	} | ||||
|  | ||||
| 	branchesController := controllers.NewBranchesController(common) | ||||
|  | ||||
| 	switchToSubCommitsControllerFactory := controllers.NewSubCommitsSwitchControllerFactory( | ||||
| 		controllerCommon, | ||||
| 		gui.State.Contexts.SubCommits, | ||||
| 		gui.git, | ||||
| 		gui.State.Modes, | ||||
| 		common, | ||||
| 		func(commits []*models.Commit) { gui.State.Model.SubCommits = commits }, | ||||
| 	) | ||||
|  | ||||
| @@ -640,6 +578,7 @@ func (gui *Gui) resetControllers() { | ||||
| 		controllers.AttachControllers(context, switchToSubCommitsControllerFactory.Create(context)) | ||||
| 	} | ||||
|  | ||||
| 	controllers.AttachControllers(gui.State.Contexts.Branches, branchesController) | ||||
| 	controllers.AttachControllers(gui.State.Contexts.Files, gui.Controllers.Files) | ||||
| 	controllers.AttachControllers(gui.State.Contexts.Tags, gui.Controllers.Tags) | ||||
| 	controllers.AttachControllers(gui.State.Contexts.Submodules, gui.Controllers.Submodules) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -73,7 +73,7 @@ func (gui *Gui) modeStatuses() []modeStatus { | ||||
| 					formatWorkingTreeState(workingTreeState), style.FgYellow, | ||||
| 				) | ||||
| 			}, | ||||
| 			reset: gui.helpers.Rebase.AbortMergeOrRebaseWithConfirm, | ||||
| 			reset: gui.helpers.MergeAndRebase.AbortMergeOrRebaseWithConfirm, | ||||
| 		}, | ||||
| 		{ | ||||
| 			isActive: func() bool { | ||||
|   | ||||
| @@ -102,7 +102,7 @@ func (gui *Gui) handleDeletePatchFromCommit() error { | ||||
| 		commitIndex := gui.getPatchCommitIndex() | ||||
| 		gui.c.LogAction(gui.c.Tr.Actions.RemovePatchFromCommit) | ||||
| 		err := gui.git.Patch.DeletePatchesFromCommit(gui.State.Model.Commits, commitIndex) | ||||
| 		return gui.helpers.Rebase.CheckMergeOrRebase(err) | ||||
| 		return gui.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -119,7 +119,7 @@ func (gui *Gui) handleMovePatchToSelectedCommit() error { | ||||
| 		commitIndex := gui.getPatchCommitIndex() | ||||
| 		gui.c.LogAction(gui.c.Tr.Actions.MovePatchToSelectedCommit) | ||||
| 		err := gui.git.Patch.MovePatchToSelectedCommit(gui.State.Model.Commits, commitIndex, gui.State.Contexts.BranchCommits.GetSelectedLineIdx()) | ||||
| 		return gui.helpers.Rebase.CheckMergeOrRebase(err) | ||||
| 		return gui.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -137,7 +137,7 @@ func (gui *Gui) handleMovePatchIntoWorkingTree() error { | ||||
| 			commitIndex := gui.getPatchCommitIndex() | ||||
| 			gui.c.LogAction(gui.c.Tr.Actions.MovePatchIntoIndex) | ||||
| 			err := gui.git.Patch.MovePatchIntoIndex(gui.State.Model.Commits, commitIndex, stash) | ||||
| 			return gui.helpers.Rebase.CheckMergeOrRebase(err) | ||||
| 			return gui.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| @@ -167,7 +167,7 @@ func (gui *Gui) handlePullPatchIntoNewCommit() error { | ||||
| 		commitIndex := gui.getPatchCommitIndex() | ||||
| 		gui.c.LogAction(gui.c.Tr.Actions.MovePatchIntoNewCommit) | ||||
| 		err := gui.git.Patch.PullPatchIntoNewCommit(gui.State.Model.Commits, commitIndex) | ||||
| 		return gui.helpers.Rebase.CheckMergeOrRebase(err) | ||||
| 		return gui.helpers.MergeAndRebase.CheckMergeOrRebase(err) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,78 +0,0 @@ | ||||
| package gui | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/hosting_service" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/jesseduffield/lazygit/pkg/gui/types" | ||||
| ) | ||||
|  | ||||
| func (gui *Gui) createPullRequestMenu(selectedBranch *models.Branch, checkedOutBranch *models.Branch) error { | ||||
| 	menuItems := make([]*types.MenuItem, 0, 4) | ||||
|  | ||||
| 	fromToDisplayStrings := func(from string, to string) []string { | ||||
| 		return []string{fmt.Sprintf("%s → %s", from, to)} | ||||
| 	} | ||||
|  | ||||
| 	menuItemsForBranch := func(branch *models.Branch) []*types.MenuItem { | ||||
| 		return []*types.MenuItem{ | ||||
| 			{ | ||||
| 				DisplayStrings: fromToDisplayStrings(branch.Name, gui.c.Tr.LcDefaultBranch), | ||||
| 				OnPress: func() error { | ||||
| 					return gui.createPullRequest(branch.Name, "") | ||||
| 				}, | ||||
| 			}, | ||||
| 			{ | ||||
| 				DisplayStrings: fromToDisplayStrings(branch.Name, gui.c.Tr.LcSelectBranch), | ||||
| 				OnPress: func() error { | ||||
| 					return gui.c.Prompt(types.PromptOpts{ | ||||
| 						Title:               branch.Name + " →", | ||||
| 						FindSuggestionsFunc: gui.helpers.Suggestions.GetBranchNameSuggestionsFunc(), | ||||
| 						HandleConfirm: func(targetBranchName string) error { | ||||
| 							return gui.createPullRequest(branch.Name, targetBranchName) | ||||
| 						}}, | ||||
| 					) | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if selectedBranch != checkedOutBranch { | ||||
| 		menuItems = append(menuItems, | ||||
| 			&types.MenuItem{ | ||||
| 				DisplayStrings: fromToDisplayStrings(checkedOutBranch.Name, selectedBranch.Name), | ||||
| 				OnPress: func() error { | ||||
| 					return gui.createPullRequest(checkedOutBranch.Name, selectedBranch.Name) | ||||
| 				}, | ||||
| 			}, | ||||
| 		) | ||||
| 		menuItems = append(menuItems, menuItemsForBranch(checkedOutBranch)...) | ||||
| 	} | ||||
|  | ||||
| 	menuItems = append(menuItems, menuItemsForBranch(selectedBranch)...) | ||||
|  | ||||
| 	return gui.c.Menu(types.CreateMenuOptions{Title: fmt.Sprintf(gui.c.Tr.CreatePullRequestOptions), Items: menuItems}) | ||||
| } | ||||
|  | ||||
| func (gui *Gui) createPullRequest(from string, to string) error { | ||||
| 	hostingServiceMgr := gui.getHostingServiceMgr() | ||||
| 	url, err := hostingServiceMgr.GetPullRequestURL(from, to) | ||||
| 	if err != nil { | ||||
| 		return gui.c.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	gui.c.LogAction(gui.c.Tr.Actions.OpenPullRequest) | ||||
|  | ||||
| 	if err := gui.os.OpenLink(url); err != nil { | ||||
| 		return gui.c.Error(err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (gui *Gui) getHostingServiceMgr() *hosting_service.HostingServiceMgr { | ||||
| 	remoteUrl := gui.git.Config.GetRemoteURL() | ||||
| 	configServices := gui.c.UserConfig.Services | ||||
| 	return hosting_service.NewHostingServiceMgr(gui.Log, gui.Tr, remoteUrl, configServices) | ||||
| } | ||||
| @@ -65,10 +65,9 @@ func (gui *Gui) handleViewReflogCommitFiles() error { | ||||
| 	} | ||||
|  | ||||
| 	return gui.SwitchToCommitFilesContext(controllers.SwitchToCommitFilesContextOpts{ | ||||
| 		RefName:    commit.Sha, | ||||
| 		CanRebase:  false, | ||||
| 		Context:    gui.State.Contexts.ReflogCommits, | ||||
| 		WindowName: "commits", | ||||
| 		RefName:   commit.Sha, | ||||
| 		CanRebase: false, | ||||
| 		Context:   gui.State.Contexts.ReflogCommits, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -215,7 +215,7 @@ func (gui *Gui) refreshCommitsWithLimit() error { | ||||
| 			FilterPath:           gui.State.Modes.Filtering.GetPath(), | ||||
| 			IncludeRebaseCommits: true, | ||||
| 			RefName:              gui.refForLog(), | ||||
| 			All:                  gui.ShowWholeGitGraph, | ||||
| 			All:                  gui.State.Contexts.BranchCommits.GetShowWholeGitGraph(), | ||||
| 		}, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| @@ -408,7 +408,7 @@ func (gui *Gui) refreshStateFiles() error { | ||||
| 	} | ||||
|  | ||||
| 	if gui.git.Status.WorkingTreeState() != enums.REBASE_MODE_NONE && conflictFileCount == 0 && prevConflictFileCount > 0 { | ||||
| 		gui.OnUIThread(func() error { return gui.helpers.Rebase.PromptToContinueRebase() }) | ||||
| 		gui.OnUIThread(func() error { return gui.helpers.MergeAndRebase.PromptToContinueRebase() }) | ||||
| 	} | ||||
|  | ||||
| 	fileTreeViewModel.RWMutex.Lock() | ||||
| @@ -526,7 +526,7 @@ func (gui *Gui) refreshStatus() { | ||||
| 	gui.Mutexes.RefreshingStatusMutex.Lock() | ||||
| 	defer gui.Mutexes.RefreshingStatusMutex.Unlock() | ||||
|  | ||||
| 	currentBranch := gui.getCheckedOutBranch() | ||||
| 	currentBranch := gui.helpers.Refs.GetCheckedOutRef() | ||||
| 	if currentBranch == nil { | ||||
| 		// need to wait for branches to refresh | ||||
| 		return | ||||
|   | ||||
| @@ -34,7 +34,7 @@ func (gui *Gui) handleRemoteBranchesEscape() error { | ||||
|  | ||||
| func (gui *Gui) handleMergeRemoteBranch() error { | ||||
| 	selectedBranchName := gui.State.Contexts.RemoteBranches.GetSelected().FullName() | ||||
| 	return gui.mergeBranchIntoCheckedOutBranch(selectedBranchName) | ||||
| 	return gui.helpers.MergeAndRebase.MergeRefIntoCheckedOutBranch(selectedBranchName) | ||||
| } | ||||
|  | ||||
| func (gui *Gui) handleDeleteRemoteBranch() error { | ||||
| @@ -63,12 +63,12 @@ func (gui *Gui) handleDeleteRemoteBranch() error { | ||||
|  | ||||
| func (gui *Gui) handleRebaseOntoRemoteBranch() error { | ||||
| 	selectedBranchName := gui.State.Contexts.RemoteBranches.GetSelected().FullName() | ||||
| 	return gui.handleRebaseOntoBranch(selectedBranchName) | ||||
| 	return gui.helpers.MergeAndRebase.RebaseOntoRef(selectedBranchName) | ||||
| } | ||||
|  | ||||
| func (gui *Gui) handleSetBranchUpstream() error { | ||||
| 	selectedBranch := gui.State.Contexts.RemoteBranches.GetSelected() | ||||
| 	checkedOutBranch := gui.getCheckedOutBranch() | ||||
| 	checkedOutBranch := gui.helpers.Refs.GetCheckedOutRef() | ||||
|  | ||||
| 	message := utils.ResolvePlaceholderString( | ||||
| 		gui.c.Tr.SetUpstreamMessage, | ||||
| @@ -101,15 +101,6 @@ func (gui *Gui) handleCreateResetToRemoteBranchMenu() error { | ||||
| 	return gui.helpers.Refs.CreateGitResetMenu(selectedBranch.FullName()) | ||||
| } | ||||
|  | ||||
| func (gui *Gui) handleEnterRemoteBranch() error { | ||||
| 	selectedBranch := gui.State.Contexts.RemoteBranches.GetSelected() | ||||
| 	if selectedBranch == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return gui.switchToSubCommitsContext(selectedBranch.RefName()) | ||||
| } | ||||
|  | ||||
| func (gui *Gui) handleNewBranchOffRemoteBranch() error { | ||||
| 	selectedBranch := gui.State.Contexts.RemoteBranches.GetSelected() | ||||
| 	if selectedBranch == nil { | ||||
|   | ||||
| @@ -37,8 +37,6 @@ func (gui *Gui) handleStashApply() error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	skipStashWarning := gui.c.UserConfig.Gui.SkipStashWarning | ||||
|  | ||||
| 	apply := func() error { | ||||
| 		gui.c.LogAction(gui.c.Tr.Actions.Stash) | ||||
| 		err := gui.git.Stash.Apply(stashEntry.Index) | ||||
| @@ -49,7 +47,7 @@ func (gui *Gui) handleStashApply() error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if skipStashWarning { | ||||
| 	if gui.c.UserConfig.Gui.SkipStashWarning { | ||||
| 		return apply() | ||||
| 	} | ||||
|  | ||||
| @@ -68,8 +66,6 @@ func (gui *Gui) handleStashPop() error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	skipStashWarning := gui.c.UserConfig.Gui.SkipStashWarning | ||||
|  | ||||
| 	pop := func() error { | ||||
| 		gui.c.LogAction(gui.c.Tr.Actions.Stash) | ||||
| 		err := gui.git.Stash.Pop(stashEntry.Index) | ||||
| @@ -80,7 +76,7 @@ func (gui *Gui) handleStashPop() error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if skipStashWarning { | ||||
| 	if gui.c.UserConfig.Gui.SkipStashWarning { | ||||
| 		return pop() | ||||
| 	} | ||||
|  | ||||
| @@ -125,10 +121,9 @@ func (gui *Gui) handleViewStashFiles() error { | ||||
| 	} | ||||
|  | ||||
| 	return gui.SwitchToCommitFilesContext(controllers.SwitchToCommitFilesContextOpts{ | ||||
| 		RefName:    stashEntry.RefName(), | ||||
| 		CanRebase:  false, | ||||
| 		Context:    gui.State.Contexts.Stash, | ||||
| 		WindowName: "stash", | ||||
| 		RefName:   stashEntry.RefName(), | ||||
| 		CanRebase: false, | ||||
| 		Context:   gui.State.Contexts.Stash, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -30,7 +30,7 @@ func (gui *Gui) handleCheckForUpdate() error { | ||||
|  | ||||
| func (gui *Gui) handleStatusClick() error { | ||||
| 	// TODO: move into some abstraction (status is currently not a listViewContext where a lot of this code lives) | ||||
| 	currentBranch := gui.getCheckedOutBranch() | ||||
| 	currentBranch := gui.helpers.Refs.GetCheckedOutRef() | ||||
| 	if currentBranch == nil { | ||||
| 		// need to wait for branches to refresh | ||||
| 		return nil | ||||
| @@ -48,7 +48,7 @@ func (gui *Gui) handleStatusClick() error { | ||||
| 	case enums.REBASE_MODE_REBASING, enums.REBASE_MODE_MERGING: | ||||
| 		workingTreeStatus := fmt.Sprintf("(%s)", formatWorkingTreeState(workingTreeState)) | ||||
| 		if cursorInSubstring(cx, upstreamStatus+" ", workingTreeStatus) { | ||||
| 			return gui.helpers.Rebase.CreateRebaseOptionsMenu() | ||||
| 			return gui.helpers.MergeAndRebase.CreateRebaseOptionsMenu() | ||||
| 		} | ||||
| 		if cursorInSubstring(cx, upstreamStatus+" "+workingTreeStatus+" ", repoName) { | ||||
| 			return gui.handleCreateRecentReposMenu() | ||||
| @@ -74,7 +74,6 @@ func formatWorkingTreeState(rebaseMode enums.RebaseMode) string { | ||||
| } | ||||
|  | ||||
| func (gui *Gui) statusRenderToMain() error { | ||||
| 	// TODO: move into some abstraction (status is currently not a listViewContext where a lot of this code lives) | ||||
| 	dashboardString := strings.Join( | ||||
| 		[]string{ | ||||
| 			lazygitTitle(), | ||||
| @@ -114,9 +113,8 @@ func (gui *Gui) askForConfigFile(action func(file string) error) error { | ||||
| 			} | ||||
| 		} | ||||
| 		return gui.c.Menu(types.CreateMenuOptions{ | ||||
| 			Title:      gui.c.Tr.SelectConfigFile, | ||||
| 			Items:      menuItems, | ||||
| 			HideCancel: true, | ||||
| 			Title: gui.c.Tr.SelectConfigFile, | ||||
| 			Items: menuItems, | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -63,10 +63,9 @@ func (gui *Gui) handleViewSubCommitFiles() error { | ||||
| 	} | ||||
|  | ||||
| 	return gui.SwitchToCommitFilesContext(controllers.SwitchToCommitFilesContextOpts{ | ||||
| 		RefName:    commit.Sha, | ||||
| 		CanRebase:  false, | ||||
| 		Context:    gui.State.Contexts.SubCommits, | ||||
| 		WindowName: "branches", | ||||
| 		RefName:   commit.Sha, | ||||
| 		CanRebase: false, | ||||
| 		Context:   gui.State.Contexts.SubCommits, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import ( | ||||
| 	"gopkg.in/ozeidan/fuzzy-patricia.v3/patricia" | ||||
| ) | ||||
|  | ||||
| type ControllerCommon struct { | ||||
| type HelperCommon struct { | ||||
| 	*common.Common | ||||
| 	IGuiCommon | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user