mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-01-26 05:37:18 +02:00
1dd7307fde
more and more move rebase commit refreshing into existing abstraction and more and more WIP and more handling clicks properly fix merge conflicts update cheatsheet lots more preparation to start moving things into controllers WIP better typing expand on remotes controller moving more code into controllers
158 lines
4.4 KiB
Go
158 lines
4.4 KiB
Go
package gui
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/popup"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
)
|
|
|
|
type RebaseOption string
|
|
|
|
const (
|
|
REBASE_OPTION_CONTINUE = "continue"
|
|
REBASE_OPTION_ABORT = "abort"
|
|
REBASE_OPTION_SKIP = "skip"
|
|
)
|
|
|
|
func (gui *Gui) handleCreateRebaseOptionsMenu() error {
|
|
options := []string{REBASE_OPTION_CONTINUE, REBASE_OPTION_ABORT}
|
|
|
|
if gui.git.Status.WorkingTreeState() == enums.REBASE_MODE_REBASING {
|
|
options = append(options, REBASE_OPTION_SKIP)
|
|
}
|
|
|
|
menuItems := make([]*popup.MenuItem, len(options))
|
|
for i, option := range options {
|
|
// note to self. Never, EVER, close over loop variables in a function
|
|
option := option
|
|
menuItems[i] = &popup.MenuItem{
|
|
DisplayString: option,
|
|
OnPress: func() error {
|
|
return gui.genericMergeCommand(option)
|
|
},
|
|
}
|
|
}
|
|
|
|
var title string
|
|
if gui.git.Status.WorkingTreeState() == enums.REBASE_MODE_MERGING {
|
|
title = gui.c.Tr.MergeOptionsTitle
|
|
} else {
|
|
title = gui.c.Tr.RebaseOptionsTitle
|
|
}
|
|
|
|
return gui.c.Menu(popup.CreateMenuOptions{Title: title, Items: menuItems})
|
|
}
|
|
|
|
func (gui *Gui) genericMergeCommand(command string) error {
|
|
status := gui.git.Status.WorkingTreeState()
|
|
|
|
if status != enums.REBASE_MODE_MERGING && status != enums.REBASE_MODE_REBASING {
|
|
return gui.c.ErrorMsg(gui.c.Tr.NotMergingOrRebasing)
|
|
}
|
|
|
|
gui.c.LogAction(fmt.Sprintf("Merge/Rebase: %s", command))
|
|
|
|
commandType := ""
|
|
switch status {
|
|
case enums.REBASE_MODE_MERGING:
|
|
commandType = "merge"
|
|
case enums.REBASE_MODE_REBASING:
|
|
commandType = "rebase"
|
|
default:
|
|
// shouldn't be possible to land here
|
|
}
|
|
|
|
// we should end up with a command like 'git merge --continue'
|
|
|
|
// it's impossible for a rebase to require a commit so we'll use a subprocess only if it's a merge
|
|
if status == enums.REBASE_MODE_MERGING && command != REBASE_OPTION_ABORT && gui.c.UserConfig.Git.Merging.ManualCommit {
|
|
// TODO: see if we should be calling more of the code from gui.Git.Rebase.GenericMergeOrRebaseAction
|
|
return gui.runSubprocessWithSuspenseAndRefresh(
|
|
gui.git.Rebase.GenericMergeOrRebaseActionCmdObj(commandType, command),
|
|
)
|
|
}
|
|
result := gui.git.Rebase.GenericMergeOrRebaseAction(commandType, command)
|
|
if err := gui.checkMergeOrRebase(result); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var conflictStrings = []string{
|
|
"Failed to merge in the changes",
|
|
"When you have resolved this problem",
|
|
"fix conflicts",
|
|
"Resolve all conflicts manually",
|
|
}
|
|
|
|
func isMergeConflictErr(errStr string) bool {
|
|
for _, str := range conflictStrings {
|
|
if strings.Contains(errStr, str) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (gui *Gui) checkMergeOrRebase(result error) error {
|
|
if err := gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}); err != nil {
|
|
return err
|
|
}
|
|
if result == nil {
|
|
return nil
|
|
} else if strings.Contains(result.Error(), "No changes - did you forget to use") {
|
|
return gui.genericMergeCommand(REBASE_OPTION_SKIP)
|
|
} else if strings.Contains(result.Error(), "The previous cherry-pick is now empty") {
|
|
return gui.genericMergeCommand(REBASE_OPTION_CONTINUE)
|
|
} else if strings.Contains(result.Error(), "No rebase in progress?") {
|
|
// assume in this case that we're already done
|
|
return nil
|
|
} else if isMergeConflictErr(result.Error()) {
|
|
return gui.c.Ask(popup.AskOpts{
|
|
Title: gui.c.Tr.FoundConflictsTitle,
|
|
Prompt: gui.c.Tr.FoundConflicts,
|
|
HandlersManageFocus: true,
|
|
HandleConfirm: func() error {
|
|
return gui.c.PushContext(gui.State.Contexts.Files)
|
|
},
|
|
HandleClose: func() error {
|
|
if err := gui.returnFromContext(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return gui.genericMergeCommand(REBASE_OPTION_ABORT)
|
|
},
|
|
})
|
|
} else {
|
|
return gui.c.ErrorMsg(result.Error())
|
|
}
|
|
}
|
|
|
|
func (gui *Gui) abortMergeOrRebaseWithConfirm() error {
|
|
// prompt user to confirm that they want to abort, then do it
|
|
mode := gui.workingTreeStateNoun()
|
|
return gui.c.Ask(popup.AskOpts{
|
|
Title: fmt.Sprintf(gui.c.Tr.AbortTitle, mode),
|
|
Prompt: fmt.Sprintf(gui.c.Tr.AbortPrompt, mode),
|
|
HandleConfirm: func() error {
|
|
return gui.genericMergeCommand(REBASE_OPTION_ABORT)
|
|
},
|
|
})
|
|
}
|
|
|
|
func (gui *Gui) workingTreeStateNoun() string {
|
|
workingTreeState := gui.git.Status.WorkingTreeState()
|
|
switch workingTreeState {
|
|
case enums.REBASE_MODE_NONE:
|
|
return ""
|
|
case enums.REBASE_MODE_MERGING:
|
|
return "merge"
|
|
default:
|
|
return "rebase"
|
|
}
|
|
}
|