1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-31 14:24:25 +03:00

wip: commit logic in helper and reported in files/staging controllers

This commit is contained in:
Arnaud PERALTA
2022-11-27 01:00:51 +01:00
committed by Jesse Duffield
parent f7449ed53a
commit 8b894d7bf5
3 changed files with 154 additions and 122 deletions

View File

@ -1,18 +1,14 @@
package controllers package controllers
import ( import (
"fmt"
"regexp"
"strings" "strings"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models" "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/context"
"github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
) )
type FilesController struct { type FilesController struct {
@ -54,12 +50,12 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
}, },
{ {
Key: opts.GetKey(opts.Config.Files.CommitChanges), Key: opts.GetKey(opts.Config.Files.CommitChanges),
Handler: self.HandleCommitPress, Handler: self.helpers.WorkingTree.HandleCommitPress,
Description: self.c.Tr.CommitChanges, Description: self.c.Tr.CommitChanges,
}, },
{ {
Key: opts.GetKey(opts.Config.Files.CommitChangesWithoutHook), Key: opts.GetKey(opts.Config.Files.CommitChangesWithoutHook),
Handler: self.HandleWIPCommitPress, Handler: self.helpers.WorkingTree.HandleWIPCommitPress,
Description: self.c.Tr.LcCommitChangesWithoutHook, Description: self.c.Tr.LcCommitChangesWithoutHook,
}, },
{ {
@ -69,7 +65,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
}, },
{ {
Key: opts.GetKey(opts.Config.Files.CommitChangesWithEditor), Key: opts.GetKey(opts.Config.Files.CommitChangesWithEditor),
Handler: self.HandleCommitEditorPress, Handler: self.helpers.WorkingTree.HandleCommitEditorPress,
Description: self.c.Tr.CommitChangesWithEditor, 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 { func (self *FilesController) refresh() error {
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}}) 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 { func (self *FilesController) handleAmendCommitPress() error {
if len(self.model.Files) == 0 { if len(self.model.Files) == 0 {
return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle) return self.c.ErrorMsg(self.c.Tr.NoFilesStagedTitle)
} }
if !self.helpers.WorkingTree.AnyStagedFiles() { if !self.helpers.WorkingTree.AnyStagedFiles() {
return self.promptToStageAllAndRetry(self.handleAmendCommitPress) return self.helpers.WorkingTree.PromptToStageAllAndRetry(self.handleAmendCommitPress)
} }
if len(self.model.Commits) == 0 { 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 { func (self *FilesController) handleStatusFilterPressed() error {
return self.c.Menu(types.CreateMenuOptions{ return self.c.Menu(types.CreateMenuOptions{
Title: self.c.Tr.FilteringMenuTitle, Title: self.c.Tr.FilteringMenuTitle,

View File

@ -1,9 +1,14 @@
package helpers package helpers
import ( import (
"fmt"
"regexp"
"github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/types" "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 { type IWorkingTreeHelper interface {
@ -16,15 +21,30 @@ type IWorkingTreeHelper interface {
type WorkingTreeHelper struct { type WorkingTreeHelper struct {
c *types.HelperCommon c *types.HelperCommon
git *commands.GitCommand git *commands.GitCommand
contexts *context.ContextTree
refHelper *RefsHelper
model *types.Model 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{ return &WorkingTreeHelper{
c: c, c: c,
git: git, git: git,
contexts: contexts,
refHelper: refHelper,
model: model, 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
}

View File

@ -73,6 +73,21 @@ func (self *StagingController) GetKeybindings(opts types.KeybindingsOpts) []*typ
Handler: self.EditHunkAndRefresh, Handler: self.EditHunkAndRefresh,
Description: self.c.Tr.EditHunk, 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,
},
} }
} }