From e09aac645035146805a3af0389e1f27fe13599b9 Mon Sep 17 00:00:00 2001 From: Suhas Karanth Date: Fri, 3 May 2019 12:32:57 +0530 Subject: [PATCH 1/3] Improve directory check for .git Return error if the .git exists but is not a directory. This provides a slightly better failure message for git repo with submodules in case the '.git' is a file which provides the reference to the parent's .git folder with the submodule inside. --- pkg/commands/git.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 265d6553e..64f3cd4b1 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -27,8 +27,11 @@ func navigateToRepoRootDirectory(stat func(string) (os.FileInfo, error), chdir f for { f, err := stat(".git") - if err == nil && f.IsDir() { - return nil + if err == nil { + if f.IsDir() { + return nil + } + return errors.New("expected .git to be a directory") } if !os.IsNotExist(err) { From 2746b1bd38fa2668490a8db2369dec5146fbaec6 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 6 May 2019 22:29:35 +1000 Subject: [PATCH 2/3] Prevent crash when opening in small window We were crashing when opening lazygit in a small window because the limit view was the only view that got created, and there were two functions that referenced either the 'current' view or the files view, neither of which existed. Now those functions just return nil if the view does not exist --- pkg/gui/context.go | 6 +++++- pkg/gui/files_panel.go | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/gui/context.go b/pkg/gui/context.go index b741132ea..2cdc5c8c6 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -21,7 +21,11 @@ func (gui *Gui) contextTitleMap() map[string]map[string]string { } func (gui *Gui) setMainTitle() error { - currentViewName := gui.g.CurrentView().Name() + currentView := gui.g.CurrentView() + if currentView == nil { + return nil + } + currentViewName := currentView.Name() var newTitle string if context, ok := gui.State.Contexts[currentViewName]; ok { newTitle = gui.contextTitleMap()[currentViewName][context] diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index caab1bede..3d2001ac1 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -86,6 +86,10 @@ func (gui *Gui) refreshFiles() error { selectedFile, _ := gui.getSelectedFile(gui.g) filesView := gui.getFilesView() + if filesView == nil { + // if the filesView hasn't been instantiated yet we just return + return nil + } if err := gui.refreshStateFiles(); err != nil { return err } From 5a0d0bb299eb2e4d693d3ecab506cc154e97678a Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Tue, 2 Apr 2019 19:53:16 +1100 Subject: [PATCH 3/3] support resetting to a commit in either soft, hard, or mixed mode --- pkg/commands/git.go | 4 ++-- pkg/commands/git_test.go | 4 ++-- pkg/gui/commits_panel.go | 51 +++++++++++++++++++++++++++++++++++++++- pkg/gui/keybindings.go | 2 +- pkg/i18n/dutch.go | 3 +++ pkg/i18n/english.go | 3 +++ pkg/i18n/polish.go | 3 +++ 7 files changed, 64 insertions(+), 6 deletions(-) diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 64f3cd4b1..159c88cca 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -277,8 +277,8 @@ func (c *GitCommand) Fetch(unamePassQuestion func(string) string, canAskForCrede } // ResetToCommit reset to commit -func (c *GitCommand) ResetToCommit(sha string) error { - return c.OSCommand.RunCommand(fmt.Sprintf("git reset %s", sha)) +func (c *GitCommand) ResetToCommit(sha string, strength string) error { + return c.OSCommand.RunCommand(fmt.Sprintf("git reset --%s %s", strength, sha)) } // NewBranch create new branch diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 3358be054..0d59c30b7 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -616,12 +616,12 @@ func TestGitCommandResetToCommit(t *testing.T) { gitCmd := NewDummyGitCommand() gitCmd.OSCommand.command = func(cmd string, args ...string) *exec.Cmd { assert.EqualValues(t, "git", cmd) - assert.EqualValues(t, []string{"reset", "78976bc"}, args) + assert.EqualValues(t, []string{"reset", "--hard", "78976bc"}, args) return exec.Command("echo") } - assert.NoError(t, gitCmd.ResetToCommit("78976bc")) + assert.NoError(t, gitCmd.ResetToCommit("78976bc", "hard")) } // TestGitCommandNewBranch is a function. diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index 98817bf59..c35b4adee 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -4,6 +4,7 @@ import ( "fmt" "strconv" + "github.com/fatih/color" "github.com/go-errors/errors" "github.com/jesseduffield/gocui" @@ -124,7 +125,8 @@ func (gui *Gui) handleResetToCommit(g *gocui.Gui, commitView *gocui.View) error if commit == nil { panic(errors.New(gui.Tr.SLocalize("NoCommitsThisBranch"))) } - if err := gui.GitCommand.ResetToCommit(commit.Sha); err != nil { + + if err := gui.GitCommand.ResetToCommit(commit.Sha, "mixed"); err != nil { return gui.createErrorPanel(g, err.Error()) } if err := gui.refreshCommits(g); err != nil { @@ -554,3 +556,50 @@ func (gui *Gui) handleSquashAllAboveFixupCommits(g *gocui.Gui, v *gocui.View) er }) }, nil) } + +type resetOption struct { + description string + command string +} + +// GetDisplayStrings is a function. +func (r *resetOption) GetDisplayStrings(isFocused bool) []string { + return []string{r.description, color.New(color.FgRed).Sprint(r.command)} +} + +func (gui *Gui) handleCreateCommitResetMenu(g *gocui.Gui, v *gocui.View) error { + commit := gui.getSelectedCommit(g) + if commit == nil { + return gui.createErrorPanel(gui.g, gui.Tr.SLocalize("NoCommitsThisBranch")) + } + + strengths := []string{"soft", "mixed", "hard"} + options := make([]*resetOption, len(strengths)) + for i, strength := range strengths { + options[i] = &resetOption{ + description: fmt.Sprintf("%s reset", strength), + command: fmt.Sprintf("reset --%s %s", strength, commit.Sha), + } + } + + handleMenuPress := func(index int) error { + if err := gui.GitCommand.ResetToCommit(commit.Sha, strengths[index]); err != nil { + return err + } + + if err := gui.refreshCommits(g); err != nil { + return err + } + if err := gui.refreshFiles(); err != nil { + return err + } + if err := gui.resetOrigin(gui.getCommitsView()); err != nil { + return err + } + + gui.State.Panels.Commits.SelectedLine = 0 + return gui.handleCommitSelect(g, gui.getCommitsView()) + } + + return gui.createMenu(fmt.Sprintf("%s %s", gui.Tr.SLocalize("resetTo"), commit.Sha), options, len(options), handleMenuPress) +} diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 6bb32ea59..fd4ed7625 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -327,7 +327,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { ViewName: "commits", Key: 'g', Modifier: gocui.ModNone, - Handler: gui.handleResetToCommit, + Handler: gui.handleCreateCommitResetMenu, Description: gui.Tr.SLocalize("resetToThisCommit"), }, { ViewName: "commits", diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go index 489a5d955..97b49e76d 100644 --- a/pkg/i18n/dutch.go +++ b/pkg/i18n/dutch.go @@ -733,6 +733,9 @@ func addDutch(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "SkipHookPrefixNotConfigured", Other: "Je hebt nog niet een commit bericht voorvoegsel ingesteld voor het overslaan van hooks. Set `git.skipHookPrefix = 'WIP'` in je config", + }, &i18n.Message{ + ID: "resetTo", + Other: `reset to`, }, ) } diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index b6c8215d8..291f114e8 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -756,6 +756,9 @@ func addEnglish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "SkipHookPrefixNotConfigured", Other: "You have not configured a commit message prefix for skipping hooks. Set `git.skipHookPrefix = 'WIP'` in your config", + }, &i18n.Message{ + ID: "resetTo", + Other: `reset to`, }, ) } diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go index 09ad7624f..8229dc5df 100644 --- a/pkg/i18n/polish.go +++ b/pkg/i18n/polish.go @@ -716,6 +716,9 @@ func addPolish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "SkipHookPrefixNotConfigured", Other: "You have not configured a commit message prefix for skipping hooks. Set `git.skipHookPrefix = 'WIP'` in your config", + }, &i18n.Message{ + ID: "resetTo", + Other: `reset to`, }, ) }