mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-01-04 03:48:07 +02:00
Make it easier to run sync/async commands, switch to interactive rebase when rebasing on branches
This commit is contained in:
parent
6c1d2d45ef
commit
95d451e59a
@ -252,13 +252,14 @@ func (c *GitCommand) RenameCommit(name string) error {
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git commit --allow-empty --amend -m %s", c.OSCommand.Quote(name)))
|
||||
}
|
||||
|
||||
func (c *GitCommand) RebaseBranch(onto string) error {
|
||||
curBranch, err := c.CurrentBranchName()
|
||||
// RebaseBranch interactive rebases onto a branch
|
||||
func (c *GitCommand) RebaseBranch(branchName string) error {
|
||||
cmd, err := c.PrepareInteractiveRebaseCommand(branchName, "", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.OSCommand.RunCommand(fmt.Sprintf("git rebase --autostash %s %s ", onto, curBranch))
|
||||
return c.OSCommand.RunPreparedCommand(cmd)
|
||||
}
|
||||
|
||||
// Fetch fetch git repo
|
||||
@ -332,12 +333,18 @@ func (c *GitCommand) usingGpg() bool {
|
||||
}
|
||||
|
||||
// Commit commits to git
|
||||
func (c *GitCommand) Commit(message string, amend bool) (*exec.Cmd, error) {
|
||||
amendParam := ""
|
||||
if amend {
|
||||
amendParam = " --amend"
|
||||
func (c *GitCommand) Commit(message string) (*exec.Cmd, error) {
|
||||
command := fmt.Sprintf("git commit -m %s", c.OSCommand.Quote(message))
|
||||
if c.usingGpg() {
|
||||
return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command), nil
|
||||
}
|
||||
command := fmt.Sprintf("git commit%s -m %s", amendParam, c.OSCommand.Quote(message))
|
||||
|
||||
return nil, c.OSCommand.RunCommand(command)
|
||||
}
|
||||
|
||||
// AmendHead amends HEAD with whatever is staged in your working tree
|
||||
func (c *GitCommand) AmendHead() (*exec.Cmd, error) {
|
||||
command := "git commit --amend --no-edit"
|
||||
if c.usingGpg() {
|
||||
return c.OSCommand.PrepareSubProcess(c.OSCommand.Platform.shell, c.OSCommand.Platform.shellArg, command), nil
|
||||
}
|
||||
@ -644,6 +651,11 @@ func (c *GitCommand) PrepareInteractiveRebaseCommand(baseSha string, todo string
|
||||
|
||||
cmd := exec.Command(splitCmd[0], splitCmd[1:]...)
|
||||
|
||||
gitSequenceEditor := ex
|
||||
if todo == "" {
|
||||
gitSequenceEditor = "true"
|
||||
}
|
||||
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(
|
||||
cmd.Env,
|
||||
@ -652,7 +664,7 @@ func (c *GitCommand) PrepareInteractiveRebaseCommand(baseSha string, todo string
|
||||
"DEBUG="+debug,
|
||||
"LANG=en_US.UTF-8", // Force using EN as language
|
||||
"LC_ALL=en_US.UTF-8", // Force using EN as language
|
||||
"GIT_SEQUENCE_EDITOR="+ex,
|
||||
"GIT_SEQUENCE_EDITOR="+gitSequenceEditor,
|
||||
)
|
||||
|
||||
if overrideEditor {
|
||||
@ -706,7 +718,17 @@ func (c *GitCommand) EditRebaseTodo(index int, action string) error {
|
||||
|
||||
content := strings.Split(string(bytes), "\n")
|
||||
|
||||
contentIndex := len(content) - 2 - index
|
||||
// count lines that are not blank and are not comments
|
||||
commitCount := 0
|
||||
for _, line := range content {
|
||||
if line != "" && !strings.HasPrefix(line, "#") {
|
||||
commitCount++
|
||||
}
|
||||
}
|
||||
|
||||
// we have the most recent commit at the bottom whereas the todo file has
|
||||
// it at the bottom, so we need to subtract our index from the commit count
|
||||
contentIndex := commitCount - 1 - index
|
||||
splitLine := strings.Split(content[contentIndex], " ")
|
||||
content[contentIndex] = action + " " + strings.Join(splitLine[1:], " ")
|
||||
result := strings.Join(content, "\n")
|
||||
|
@ -1,28 +1,38 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
)
|
||||
|
||||
func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error {
|
||||
message := gui.trimmedContent(v)
|
||||
if message == "" {
|
||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("CommitWithoutMessageErr"))
|
||||
}
|
||||
sub, err := gui.GitCommand.Commit(message, false)
|
||||
// runSyncOrAsyncCommand takes the output of a command that may have returned
|
||||
// either no error, an error, or a subprocess to execute, and if a subprocess
|
||||
// needs to be set on the gui object, it does so, and then returns the error
|
||||
func (gui *Gui) runSyncOrAsyncCommand(sub *exec.Cmd, err error) error {
|
||||
if err != nil {
|
||||
// TODO need to find a way to send through this error
|
||||
if err != gui.Errors.ErrSubProcess {
|
||||
return gui.createErrorPanel(g, err.Error())
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
}
|
||||
if sub != nil {
|
||||
gui.SubProcess = sub
|
||||
return gui.Errors.ErrSubProcess
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) handleCommitConfirm(g *gocui.Gui, v *gocui.View) error {
|
||||
message := gui.trimmedContent(v)
|
||||
if message == "" {
|
||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("CommitWithoutMessageErr"))
|
||||
}
|
||||
if err := gui.runSyncOrAsyncCommand(gui.GitCommand.Commit(message)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.Clear()
|
||||
_ = v.SetCursor(0, 0)
|
||||
_ = v.SetOrigin(0, 0)
|
||||
|
@ -212,6 +212,11 @@ func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error {
|
||||
// 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 (gui *Gui) handleMidRebaseCommand(action string) (bool, error) {
|
||||
selectedCommit := gui.State.Commits[gui.State.Panels.Commits.SelectedLine]
|
||||
if selectedCommit.Status != "rebasing" {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// for now we do not support setting 'reword' because it requires an editor
|
||||
// and that means we either unconditionally wait around for the subprocess to ask for
|
||||
// our input or we set a lazygit client as the EDITOR env variable and have it
|
||||
@ -220,10 +225,6 @@ func (gui *Gui) handleMidRebaseCommand(action string) (bool, error) {
|
||||
return true, gui.createErrorPanel(gui.g, gui.Tr.SLocalize("rewordNotSupported"))
|
||||
}
|
||||
|
||||
selectedCommit := gui.State.Commits[gui.State.Panels.Commits.SelectedLine]
|
||||
if selectedCommit.Status != "rebasing" {
|
||||
return false, nil
|
||||
}
|
||||
if err := gui.GitCommand.EditRebaseTodo(gui.State.Panels.Commits.SelectedLine, action); err != nil {
|
||||
return false, gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
@ -318,6 +319,7 @@ func (gui *Gui) handleCommitEdit(g *gocui.Gui, v *gocui.View) error {
|
||||
}
|
||||
|
||||
func (gui *Gui) handleCommitAmendTo(g *gocui.Gui, v *gocui.View) error {
|
||||
// TODO: i18n
|
||||
return gui.createConfirmationPanel(gui.g, v, "Amend Commit", "Are you sure you want to amend this commit with your staged files?", func(*gocui.Gui, *gocui.View) error {
|
||||
err := gui.GitCommand.AmendTo(gui.State.Commits[gui.State.Panels.Commits.SelectedLine].Sha)
|
||||
return gui.handleGenericMergeCommandResult(err)
|
||||
|
@ -287,18 +287,16 @@ func (gui *Gui) handleAmendCommitPress(g *gocui.Gui, filesView *gocui.View) erro
|
||||
if len(gui.stagedFiles()) == 0 && gui.State.WorkingTreeState == "normal" {
|
||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoStagedFilesToCommit"))
|
||||
}
|
||||
title := strings.Title(gui.Tr.SLocalize("AmendLastCommit"))
|
||||
question := gui.Tr.SLocalize("SureToAmend")
|
||||
|
||||
if len(gui.State.Commits) == 0 {
|
||||
return gui.createErrorPanel(g, gui.Tr.SLocalize("NoCommitToAmend"))
|
||||
}
|
||||
|
||||
title := strings.Title(gui.Tr.SLocalize("AmendLastCommit"))
|
||||
question := gui.Tr.SLocalize("SureToAmend")
|
||||
|
||||
return gui.createConfirmationPanel(g, filesView, title, question, func(g *gocui.Gui, v *gocui.View) error {
|
||||
lastCommitMsg := gui.State.Commits[0].Name
|
||||
_, err := gui.GitCommand.Commit(lastCommitMsg, true)
|
||||
if err != nil {
|
||||
return gui.createErrorPanel(g, err.Error())
|
||||
if err := gui.runSyncOrAsyncCommand(gui.GitCommand.AmendHead()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gui.refreshSidePanels(g)
|
||||
@ -324,15 +322,7 @@ func (gui *Gui) PrepareSubProcess(g *gocui.Gui, commands ...string) {
|
||||
}
|
||||
|
||||
func (gui *Gui) editFile(filename string) error {
|
||||
sub, err := gui.OSCommand.EditFile(filename)
|
||||
if err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
if sub != nil {
|
||||
gui.SubProcess = sub
|
||||
return gui.Errors.ErrSubProcess
|
||||
}
|
||||
return nil
|
||||
return gui.runSyncOrAsyncCommand(gui.OSCommand.EditFile(filename))
|
||||
}
|
||||
|
||||
func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error {
|
||||
|
@ -65,7 +65,7 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
||||
Other: "amend last commit",
|
||||
}, &i18n.Message{
|
||||
ID: "SureToAmend",
|
||||
Other: "Are you sure you want to amend last commit? You can change commit message from commits panel.",
|
||||
Other: "Are you sure you want to amend last commit? Afterwards, you can change commit message from the commits panel.",
|
||||
}, &i18n.Message{
|
||||
ID: "NoCommitToAmend",
|
||||
Other: "There's no commit to amend.",
|
||||
@ -284,7 +284,7 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
||||
Other: "Fixup",
|
||||
}, &i18n.Message{
|
||||
ID: "SureFixupThisCommit",
|
||||
Other: "Are you sure you want to fixup this commit? The commit beneath will be squashed up into this one",
|
||||
Other: "Are you sure you want to 'fixup' this commit? It will be merged into the commit below",
|
||||
}, &i18n.Message{
|
||||
ID: "SureSquashThisCommit",
|
||||
Other: "Are you sure you want to squash this commit into the commit below?", // TODO: i18n
|
||||
@ -568,11 +568,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
||||
}, &i18n.Message{
|
||||
ID: "YouAreHere",
|
||||
Other: "YOU ARE HERE",
|
||||
}, &i18n.Message{
|
||||
ID: "rewordNotSupported",
|
||||
Other: "rewording commits while interactively rebasing is not currently supported",
|
||||
},
|
||||
|
||||
|
||||
}, &i18n.Message{
|
||||
ID: "rewordNotSupported",
|
||||
Other: "rewording commits while interactively rebasing is not currently supported",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user