diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 222d53af0..4efb4c2cd 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -322,8 +322,8 @@ func (c *GitCommand) Fetch(unamePassQuestion func(string) string, canAskForCrede } // ResetToCommit reset to commit -func (c *GitCommand) ResetToCommit(sha string, strength string) error { - return c.OSCommand.RunCommand("git reset --%s %s", strength, sha) +func (c *GitCommand) ResetToCommit(sha string, strength string, options RunCommandOptions) error { + return c.OSCommand.RunCommandWithOptions(fmt.Sprintf("git reset --%s %s", strength, sha), options) } // NewBranch create new branch @@ -522,12 +522,17 @@ func (c *GitCommand) DiscardUnstagedFileChanges(file *File) error { } // Checkout checks out a branch (or commit), with --force if you set the force arg to true -func (c *GitCommand) Checkout(branch string, force bool) error { +type CheckoutOptions struct { + Force bool + EnvVars []string +} + +func (c *GitCommand) Checkout(branch string, options CheckoutOptions) error { forceArg := "" - if force { + if options.Force { forceArg = "--force " } - return c.OSCommand.RunCommand("git checkout %s %s", forceArg, branch) + return c.OSCommand.RunCommandWithOptions(fmt.Sprintf("git checkout %s %s", forceArg, branch), RunCommandOptions{EnvVars: options.EnvVars}) } // PrepareCommitSubProcess prepares a subprocess for `git commit` diff --git a/pkg/commands/os.go b/pkg/commands/os.go index 9cf266f58..7b96b99c4 100644 --- a/pkg/commands/os.go +++ b/pkg/commands/os.go @@ -64,6 +64,22 @@ func (c *OSCommand) SetBeforeExecuteCmd(cmd func(*exec.Cmd)) { c.beforeExecuteCmd = cmd } +type RunCommandOptions struct { + EnvVars []string +} + +func (c *OSCommand) RunCommandWithOutputWithOptions(command string, options RunCommandOptions) (string, error) { + c.Log.WithField("command", command).Info("RunCommand") + cmd := c.ExecutableFromString(command) + cmd.Env = append(cmd.Env, options.EnvVars...) + return sanitisedCommandOutput(cmd.CombinedOutput()) +} + +func (c *OSCommand) RunCommandWithOptions(command string, options RunCommandOptions) error { + _, err := c.RunCommandWithOutputWithOptions(command, options) + return err +} + // RunCommandWithOutput wrapper around commands returning their output and error // NOTE: If you don't pass any formatArgs we'll just use the command directly, // however there's a bizarre compiler error/warning when you pass in a formatString diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 227392a45..72c09252c 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -136,7 +136,7 @@ func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error { message := gui.Tr.SLocalize("SureForceCheckout") title := gui.Tr.SLocalize("ForceCheckoutBranch") return gui.createConfirmationPanel(g, v, true, title, message, func(g *gocui.Gui, v *gocui.View) error { - if err := gui.GitCommand.Checkout(branch.Name, true); err != nil { + if err := gui.GitCommand.Checkout(branch.Name, commands.CheckoutOptions{Force: true}); err != nil { _ = gui.createErrorPanel(g, err.Error()) } return gui.refreshSidePanels(g) @@ -144,19 +144,22 @@ func (gui *Gui) handleForceCheckout(g *gocui.Gui, v *gocui.View) error { } type handleCheckoutRefOptions struct { - onDone func() - waitingStatus string + OnDone func() + WaitingStatus string + EnvVars []string } func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions) error { - onDone := options.onDone - waitingStatus := options.waitingStatus + onDone := options.OnDone + waitingStatus := options.WaitingStatus if waitingStatus == "" { waitingStatus = gui.Tr.SLocalize("CheckingOutStatus") } + cmdOptions := commands.CheckoutOptions{Force: false, EnvVars: options.EnvVars} + return gui.WithWaitingStatus(waitingStatus, func() error { - if err := gui.GitCommand.Checkout(ref, false); err != nil { + if err := gui.GitCommand.Checkout(ref, cmdOptions); err != nil { // note, this will only work for english-language git commands. If we force git to use english, and the error isn't this one, then the user will receive an english command they may not understand. I'm not sure what the best solution to this is. Running the command once in english and a second time in the native language is one option if strings.Contains(err.Error(), "Please commit your changes or stash them before you switch branch") { @@ -166,7 +169,7 @@ func (gui *Gui) handleCheckoutRef(ref string, options handleCheckoutRefOptions) if err := gui.GitCommand.StashSave(gui.Tr.SLocalize("StashPrefix") + ref); err != nil { return gui.createErrorPanel(g, err.Error()) } - if err := gui.GitCommand.Checkout(ref, false); err != nil { + if err := gui.GitCommand.Checkout(ref, cmdOptions); err != nil { return gui.createErrorPanel(g, err.Error()) } if onDone != nil { @@ -477,7 +480,7 @@ func (gui *Gui) handleRenameBranch(g *gocui.Gui, v *gocui.View) error { } // need to checkout so that the branch shows up in our reflog and therefore // doesn't get lost among all the other branches when we switch to something else - if err := gui.GitCommand.Checkout(newName, false); err != nil { + if err := gui.GitCommand.Checkout(newName, commands.CheckoutOptions{Force: false}); err != nil { return gui.createErrorPanel(gui.g, err.Error()) } diff --git a/pkg/gui/reflog_panel.go b/pkg/gui/reflog_panel.go index f0172d7f2..20cba609d 100644 --- a/pkg/gui/reflog_panel.go +++ b/pkg/gui/reflog_panel.go @@ -144,7 +144,12 @@ func (gui *Gui) reflogUndo(g *gocui.Gui, v *gocui.View) error { if len(match) <= 1 { return false, nil } - return true, gui.handleCheckoutRef(match[1], handleCheckoutRefOptions{onDone: onDone, waitingStatus: gui.Tr.SLocalize("UndoingStatus")}) + return true, gui.handleCheckoutRef(match[1], handleCheckoutRefOptions{ + OnDone: onDone, + WaitingStatus: gui.Tr.SLocalize("UndoingStatus"), + EnvVars: []string{"GIT_REFLOG_ACTION=[lazygit]"}, + }, + ) }, }, { @@ -202,7 +207,12 @@ func (gui *Gui) reflogRedo(g *gocui.Gui, v *gocui.View) error { if len(match) <= 1 { return false, nil } - return true, gui.handleCheckoutRef(match[1], handleCheckoutRefOptions{onDone: onDone, waitingStatus: gui.Tr.SLocalize("RedoingStatus")}) + return true, gui.handleCheckoutRef(match[1], handleCheckoutRefOptions{ + OnDone: onDone, + WaitingStatus: gui.Tr.SLocalize("RedoingStatus"), + EnvVars: []string{"GIT_REFLOG_ACTION=[lazygit]"}, + }, + ) }, }, { @@ -252,6 +262,14 @@ func (gui *Gui) handleHardResetWithAutoStash(commitSha string, onDone func()) er } } + reset := func() error { + if err := gui.resetToRef(commitSha, "hard", commands.RunCommandOptions{EnvVars: []string{"GIT_REFLOG_ACTION=[lazygit]"}}); err != nil { + return gui.createErrorPanel(gui.g, err.Error()) + } + onDone() + return nil + } + if dirtyWorkingTree { // offer to autostash changes return gui.createConfirmationPanel(gui.g, gui.getBranchesView(), true, gui.Tr.SLocalize("AutoStashTitle"), gui.Tr.SLocalize("AutoStashPrompt"), func(g *gocui.Gui, v *gocui.View) error { @@ -259,10 +277,9 @@ func (gui *Gui) handleHardResetWithAutoStash(commitSha string, onDone func()) er if err := gui.GitCommand.StashSave(gui.Tr.SLocalize("StashPrefix") + commitSha); err != nil { return gui.createErrorPanel(g, err.Error()) } - if err := gui.resetToRef(commitSha, "hard"); err != nil { - return gui.createErrorPanel(g, err.Error()) + if err := reset(); err != nil { + return err } - onDone() if err := gui.GitCommand.StashDo(0, "pop"); err != nil { if err := gui.refreshSidePanels(g); err != nil { @@ -276,10 +293,9 @@ func (gui *Gui) handleHardResetWithAutoStash(commitSha string, onDone func()) er } return gui.WithWaitingStatus(gui.Tr.SLocalize("UndoingStatus"), func() error { - if err := gui.resetToRef(commitSha, "hard"); err != nil { - return gui.createErrorPanel(gui.g, err.Error()) + if err := reset(); err != nil { + return err } - onDone() return gui.refreshSidePanels(gui.g) }) } diff --git a/pkg/gui/reset_menu_panel.go b/pkg/gui/reset_menu_panel.go index 49dd95c3c..5103044a2 100644 --- a/pkg/gui/reset_menu_panel.go +++ b/pkg/gui/reset_menu_panel.go @@ -4,10 +4,11 @@ import ( "fmt" "github.com/fatih/color" + "github.com/jesseduffield/lazygit/pkg/commands" ) -func (gui *Gui) resetToRef(ref string, strength string) error { - if err := gui.GitCommand.ResetToCommit(ref, strength); err != nil { +func (gui *Gui) resetToRef(ref string, strength string, options commands.RunCommandOptions) error { + if err := gui.GitCommand.ResetToCommit(ref, strength, options); err != nil { return gui.createErrorPanel(gui.g, err.Error()) } @@ -47,7 +48,7 @@ func (gui *Gui) createResetMenu(ref string) error { ), }, onPress: func() error { - return gui.resetToRef(ref, strength) + return gui.resetToRef(ref, strength, commands.RunCommandOptions{}) }, } }