mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 12:25:47 +02:00
wip: commit logic in helper and reported in files/staging controllers
This commit is contained in:
parent
f7449ed53a
commit
8b894d7bf5
3 changed files with 154 additions and 122 deletions
|
@ -1,18 +1,14 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
type FilesController struct {
|
||||
|
@ -54,12 +50,12 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
|||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.CommitChanges),
|
||||
Handler: self.HandleCommitPress,
|
||||
Handler: self.helpers.WorkingTree.HandleCommitPress,
|
||||
Description: self.c.Tr.CommitChanges,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.CommitChangesWithoutHook),
|
||||
Handler: self.HandleWIPCommitPress,
|
||||
Handler: self.helpers.WorkingTree.HandleWIPCommitPress,
|
||||
Description: self.c.Tr.LcCommitChangesWithoutHook,
|
||||
},
|
||||
{
|
||||
|
@ -69,7 +65,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
|||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.CommitChangesWithEditor),
|
||||
Handler: self.HandleCommitEditorPress,
|
||||
Handler: self.helpers.WorkingTree.HandleCommitEditorPress,
|
||||
Description: self.c.Tr.CommitChangesWithEditor,
|
||||
},
|
||||
{
|
||||
|
@ -554,112 +550,17 @@ func (self *FilesController) ignoreOrExcludeMenu(node *filetree.FileNode) error
|
|||
})
|
||||
}
|
||||
|
||||
func (self *FilesController) HandleWIPCommitPress() error {
|
||||
skipHookPrefix := self.c.UserConfig.Git.SkipHookPrefix
|
||||
if skipHookPrefix == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.SkipHookPrefixNotConfigured)
|
||||
}
|
||||
|
||||
self.setCommitMessage(skipHookPrefix)
|
||||
|
||||
return self.HandleCommitPress()
|
||||
}
|
||||
|
||||
func (self *FilesController) commitPrefixConfigForRepo() *config.CommitPrefixConfig {
|
||||
cfg, ok := self.c.UserConfig.Git.CommitPrefixes[utils.GetCurrentRepoName()]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &cfg
|
||||
}
|
||||
|
||||
func (self *FilesController) prepareFilesForCommit() error {
|
||||
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()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.syncRefresh()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// for when you need to refetch files before continuing an action. Runs synchronously.
|
||||
func (self *FilesController) syncRefresh() error {
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
|
||||
}
|
||||
|
||||
func (self *FilesController) refresh() error {
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}})
|
||||
}
|
||||
|
||||
func (self *FilesController) HandleCommitPress() error {
|
||||
if err := self.prepareFilesForCommit(); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
|
||||
if len(self.model.Files) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
|
||||
}
|
||||
|
||||
if !self.helpers.WorkingTree.AnyStagedFiles() {
|
||||
return self.promptToStageAllAndRetry(self.HandleCommitPress)
|
||||
}
|
||||
|
||||
savedCommitMessage := self.getSavedCommitMessage()
|
||||
if len(savedCommitMessage) > 0 {
|
||||
self.setCommitMessage(savedCommitMessage)
|
||||
} else {
|
||||
commitPrefixConfig := self.commitPrefixConfigForRepo()
|
||||
if commitPrefixConfig != nil {
|
||||
prefixPattern := commitPrefixConfig.Pattern
|
||||
prefixReplace := commitPrefixConfig.Replace
|
||||
rgx, err := regexp.Compile(prefixPattern)
|
||||
if err != nil {
|
||||
return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.LcCommitPrefixPatternError, err.Error()))
|
||||
}
|
||||
prefix := rgx.ReplaceAllString(self.helpers.Refs.GetCheckedOutRef().Name, prefixReplace)
|
||||
self.setCommitMessage(prefix)
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.c.PushContext(self.contexts.CommitMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *FilesController) promptToStageAllAndRetry(retry func() error) error {
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
Title: self.c.Tr.NoFilesStagedTitle,
|
||||
Prompt: self.c.Tr.NoFilesStagedPrompt,
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
|
||||
if err := self.git.WorkingTree.StageAll(); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
if err := self.syncRefresh(); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
|
||||
return retry()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *FilesController) handleAmendCommitPress() error {
|
||||
if len(self.model.Files) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
|
||||
}
|
||||
|
||||
if !self.helpers.WorkingTree.AnyStagedFiles() {
|
||||
return self.promptToStageAllAndRetry(self.handleAmendCommitPress)
|
||||
return self.helpers.WorkingTree.PromptToStageAllAndRetry(self.handleAmendCommitPress)
|
||||
}
|
||||
|
||||
if len(self.model.Commits) == 0 {
|
||||
|
@ -677,23 +578,6 @@ func (self *FilesController) handleAmendCommitPress() error {
|
|||
})
|
||||
}
|
||||
|
||||
// HandleCommitEditorPress - handle when the user wants to commit changes via
|
||||
// their editor rather than via the popup panel
|
||||
func (self *FilesController) HandleCommitEditorPress() error {
|
||||
if len(self.model.Files) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
|
||||
}
|
||||
|
||||
if !self.helpers.WorkingTree.AnyStagedFiles() {
|
||||
return self.promptToStageAllAndRetry(self.HandleCommitEditorPress)
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.Commit)
|
||||
return self.c.RunSubprocessAndRefresh(
|
||||
self.git.Commit.CommitEditorCmdObj(),
|
||||
)
|
||||
}
|
||||
|
||||
func (self *FilesController) handleStatusFilterPressed() error {
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
Title: self.c.Tr.FilteringMenuTitle,
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
)
|
||||
|
||||
type IWorkingTreeHelper interface {
|
||||
|
@ -16,15 +21,30 @@ type IWorkingTreeHelper interface {
|
|||
type WorkingTreeHelper struct {
|
||||
c *types.HelperCommon
|
||||
git *commands.GitCommand
|
||||
|
||||
contexts *context.ContextTree
|
||||
refHelper *RefsHelper
|
||||
model *types.Model
|
||||
setCommitMessage func(message string)
|
||||
getSavedCommitMessage func() string
|
||||
}
|
||||
|
||||
func NewWorkingTreeHelper(c *types.HelperCommon, git *commands.GitCommand, model *types.Model) *WorkingTreeHelper {
|
||||
func NewWorkingTreeHelper(
|
||||
c *types.HelperCommon,
|
||||
git *commands.GitCommand,
|
||||
contexts *context.ContextTree,
|
||||
refHelper *RefsHelper,
|
||||
model *types.Model,
|
||||
setCommitMessage func(message string),
|
||||
getSavedCommitMessage func() string,
|
||||
) *WorkingTreeHelper {
|
||||
return &WorkingTreeHelper{
|
||||
c: c,
|
||||
git: git,
|
||||
contexts: contexts,
|
||||
refHelper: refHelper,
|
||||
model: model,
|
||||
setCommitMessage: setCommitMessage,
|
||||
getSavedCommitMessage: getSavedCommitMessage,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,3 +92,116 @@ func (self *WorkingTreeHelper) OpenMergeTool() error {
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) HandleCommitPress() error {
|
||||
if err := self.prepareFilesForCommit(); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
|
||||
if len(self.model.Files) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
|
||||
}
|
||||
|
||||
if !self.AnyStagedFiles() {
|
||||
return self.PromptToStageAllAndRetry(self.HandleCommitPress)
|
||||
}
|
||||
|
||||
savedCommitMessage := self.getSavedCommitMessage()
|
||||
if len(savedCommitMessage) > 0 {
|
||||
self.setCommitMessage(savedCommitMessage)
|
||||
} else {
|
||||
commitPrefixConfig := self.commitPrefixConfigForRepo()
|
||||
if commitPrefixConfig != nil {
|
||||
prefixPattern := commitPrefixConfig.Pattern
|
||||
prefixReplace := commitPrefixConfig.Replace
|
||||
rgx, err := regexp.Compile(prefixPattern)
|
||||
if err != nil {
|
||||
return self.c.ErrorMsg(fmt.Sprintf("%s: %s", self.c.Tr.LcCommitPrefixPatternError, err.Error()))
|
||||
}
|
||||
prefix := rgx.ReplaceAllString(self.refHelper.GetCheckedOutRef().Name, prefixReplace)
|
||||
self.setCommitMessage(prefix)
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.c.PushContext(self.contexts.CommitMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleCommitEditorPress - handle when the user wants to commit changes via
|
||||
// their editor rather than via the popup panel
|
||||
func (self *WorkingTreeHelper) HandleCommitEditorPress() error {
|
||||
if len(self.model.Files) == 0 {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
|
||||
}
|
||||
|
||||
if !self.AnyStagedFiles() {
|
||||
return self.PromptToStageAllAndRetry(self.HandleCommitEditorPress)
|
||||
}
|
||||
|
||||
self.c.LogAction(self.c.Tr.Actions.Commit)
|
||||
return self.c.RunSubprocessAndRefresh(
|
||||
self.git.Commit.CommitEditorCmdObj(),
|
||||
)
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) HandleWIPCommitPress() error {
|
||||
skipHookPrefix := self.c.UserConfig.Git.SkipHookPrefix
|
||||
if skipHookPrefix == "" {
|
||||
return self.c.ErrorMsg(self.c.Tr.SkipHookPrefixNotConfigured)
|
||||
}
|
||||
|
||||
self.setCommitMessage(skipHookPrefix)
|
||||
|
||||
return self.HandleCommitPress()
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) PromptToStageAllAndRetry(retry func() error) error {
|
||||
return self.c.Confirm(types.ConfirmOpts{
|
||||
Title: self.c.Tr.NoFilesStagedTitle,
|
||||
Prompt: self.c.Tr.NoFilesStagedPrompt,
|
||||
HandleConfirm: func() error {
|
||||
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
|
||||
if err := self.git.WorkingTree.StageAll(); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
if err := self.syncRefresh(); err != nil {
|
||||
return self.c.Error(err)
|
||||
}
|
||||
|
||||
return retry()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// for when you need to refetch files before continuing an action. Runs synchronously.
|
||||
func (self *WorkingTreeHelper) syncRefresh() error {
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) prepareFilesForCommit() error {
|
||||
noStagedFiles := !self.AnyStagedFiles()
|
||||
if noStagedFiles && self.c.UserConfig.Gui.SkipNoStagedFilesWarning {
|
||||
self.c.LogAction(self.c.Tr.Actions.StageAllFiles)
|
||||
err := self.git.WorkingTree.StageAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.syncRefresh();
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *WorkingTreeHelper) commitPrefixConfigForRepo() *config.CommitPrefixConfig {
|
||||
cfg, ok := self.c.UserConfig.Git.CommitPrefixes[utils.GetCurrentRepoName()]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &cfg
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,21 @@ func (self *StagingController) GetKeybindings(opts types.KeybindingsOpts) []*typ
|
|||
Handler: self.EditHunkAndRefresh,
|
||||
Description: self.c.Tr.EditHunk,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.CommitChanges),
|
||||
Handler: self.helpers.WorkingTree.HandleCommitPress,
|
||||
Description: self.c.Tr.CommitChanges,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.CommitChangesWithoutHook),
|
||||
Handler: self.helpers.WorkingTree.HandleWIPCommitPress,
|
||||
Description: self.c.Tr.LcCommitChangesWithoutHook,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.CommitChangesWithEditor),
|
||||
Handler: self.helpers.WorkingTree.HandleCommitEditorPress,
|
||||
Description: self.c.Tr.CommitChangesWithEditor,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue