diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2019-03-18 21:19:07 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2019-03-23 13:26:17 +1100 |
commit | f502f75e1f56bf8f34d3fdf42e934919cd045d85 (patch) | |
tree | 27236dda4b1bd011d43e0bc1efb2e642371c6c6d | |
parent | ff97ef7b94b5ccfda1d8b98b0a7e21a779309fcc (diff) |
add more options for resetting files in the working tree
-rw-r--r-- | pkg/commands/git.go | 19 | ||||
-rw-r--r-- | pkg/commands/git_test.go | 103 | ||||
-rw-r--r-- | pkg/gui/files_panel.go | 88 | ||||
-rw-r--r-- | pkg/i18n/dutch.go | 18 | ||||
-rw-r--r-- | pkg/i18n/english.go | 18 | ||||
-rw-r--r-- | pkg/i18n/polish.go | 18 |
6 files changed, 221 insertions, 43 deletions
diff --git a/pkg/commands/git.go b/pkg/commands/git.go index e674dc720..dbd9087c2 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -217,11 +217,11 @@ func includesInt(list []int, a int) bool { // ResetAndClean removes all unstaged changes and removes all untracked files func (c *GitCommand) ResetAndClean() error { - if err := c.OSCommand.RunCommand("git reset --hard HEAD"); err != nil { + if err := c.ResetHardHead(); err != nil { return err } - return c.OSCommand.RunCommand("git clean -fd") + return c.RemoveUntrackedFiles() } func (c *GitCommand) GetCurrentBranchUpstreamDifferenceCount() (string, string) { @@ -890,3 +890,18 @@ func (c *GitCommand) DiscardOldFileChanges(commits []*Commit, commitIndex int, f // continue return c.GenericMerge("rebase", "continue") } + +// DiscardAnyUnstagedFileChanges discards any unstages file changes via `git checkout -- .` +func (c *GitCommand) DiscardAnyUnstagedFileChanges() error { + return c.OSCommand.RunCommand("git checkout -- .") +} + +// RemoveUntrackedFiles runs `git clean -fd` +func (c *GitCommand) RemoveUntrackedFiles() error { + return c.OSCommand.RunCommand("git clean -fd") +} + +// ResetHardHead runs `git reset --hard HEAD` +func (c *GitCommand) ResetHardHead() error { + return c.OSCommand.RunCommand("git reset --hard HEAD") +} diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go index 614ad527b..aa1785af8 100644 --- a/pkg/commands/git_test.go +++ b/pkg/commands/git_test.go @@ -1933,8 +1933,8 @@ func TestGitCommandGetCommitFiles(t *testing.T) { } } -// TestGitCommandDiscardUnstagedChanges is a function. -func TestGitCommandDiscardUnstagedChanges(t *testing.T) { +// TestGitCommandDiscardUnstagedFileChanges is a function. +func TestGitCommandDiscardUnstagedFileChanges(t *testing.T) { type scenario struct { testName string file *File @@ -1967,3 +1967,102 @@ func TestGitCommandDiscardUnstagedChanges(t *testing.T) { }) } } + +// TestGitCommandDiscardAnyUnstagedFileChanges is a function. +func TestGitCommandDiscardAnyUnstagedFileChanges(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(error) + } + + scenarios := []scenario{ + { + "valid case", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: `git checkout -- .`, + Replace: "echo", + }, + }), + func(err error) { + assert.NoError(t, err) + }, + }, + } + + gitCmd := NewDummyGitCommand() + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd.OSCommand.command = s.command + s.test(gitCmd.DiscardAnyUnstagedFileChanges()) + }) + } +} + +// TestGitCommandRemoveUntrackedFiles is a function. +func TestGitCommandRemoveUntrackedFiles(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(error) + } + + scenarios := []scenario{ + { + "valid case", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: `git clean -fd`, + Replace: "echo", + }, + }), + func(err error) { + assert.NoError(t, err) + }, + }, + } + + gitCmd := NewDummyGitCommand() + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd.OSCommand.command = s.command + s.test(gitCmd.RemoveUntrackedFiles()) + }) + } +} + +// TestGitCommandResetHardHead is a function. +func TestGitCommandResetHardHead(t *testing.T) { + type scenario struct { + testName string + command func(string, ...string) *exec.Cmd + test func(error) + } + + scenarios := []scenario{ + { + "valid case", + test.CreateMockCommand(t, []*test.CommandSwapper{ + { + Expect: `git reset --hard HEAD`, + Replace: "echo", + }, + }), + func(err error) { + assert.NoError(t, err) + }, + }, + } + + gitCmd := NewDummyGitCommand() + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + gitCmd.OSCommand.command = s.command + s.test(gitCmd.ResetHardHead()) + }) + } +} diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index deaffb83b..2f91df519 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -10,6 +10,7 @@ import ( "fmt" "strings" + "github.com/fatih/color" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/utils" @@ -455,15 +456,6 @@ func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error { return gui.refreshFiles() } -func (gui *Gui) handleResetAndClean(g *gocui.Gui, v *gocui.View) error { - return gui.createConfirmationPanel(g, v, gui.Tr.SLocalize("ClearFilePanel"), gui.Tr.SLocalize("SureResetHardHead"), func(g *gocui.Gui, v *gocui.View) error { - if err := gui.GitCommand.ResetAndClean(); err != nil { - gui.createErrorPanel(g, err.Error()) - } - return gui.refreshFiles() - }, nil) -} - func (gui *Gui) openFile(filename string) error { if err := gui.OSCommand.OpenFile(filename); err != nil { return gui.createErrorPanel(gui.g, err.Error()) @@ -498,13 +490,22 @@ type discardOption struct { description string } -type discardOptionValue int +type discardAllOption struct { + handler func() error + description string + command string +} // GetDisplayStrings is a function. func (r *discardOption) GetDisplayStrings(isFocused bool) []string { return []string{r.description} } +// GetDisplayStrings is a function. +func (r *discardAllOption) GetDisplayStrings(isFocused bool) []string { + return []string{r.description, color.New(color.FgRed).Sprint(r.command)} +} + func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error { file, err := gui.getSelectedFile(g) if err != nil { @@ -518,11 +519,7 @@ func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error { { description: gui.Tr.SLocalize("discardAllChanges"), handler: func(file *commands.File) error { - if err := gui.GitCommand.DiscardAllFileChanges(file); err != nil { - return err - } - - return gui.refreshFiles() + return gui.GitCommand.DiscardAllFileChanges(file) }, }, { @@ -537,11 +534,7 @@ func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error { discardUnstagedChanges := &discardOption{ description: gui.Tr.SLocalize("discardUnstagedChanges"), handler: func(file *commands.File) error { - if err := gui.GitCommand.DiscardUnstagedFileChanges(file); err != nil { - return err - } - - return gui.refreshFiles() + return gui.GitCommand.DiscardUnstagedFileChanges(file) }, } @@ -549,8 +542,61 @@ func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error { } handleMenuPress := func(index int) error { - return options[index].handler(file) + if err := options[index].handler(file); err != nil { + return err + } + + return gui.refreshFiles() } return gui.createMenu(file.Name, options, handleMenuPress) } + +func (gui *Gui) handleResetAndClean(g *gocui.Gui, v *gocui.View) error { + options := []*discardAllOption{ + { + description: gui.Tr.SLocalize("discardAllChangesToAllFiles"), + command: "reset --hard HEAD && git clean -fd", + handler: func() error { + return gui.GitCommand.ResetAndClean() + }, + }, + { + description: gui.Tr.SLocalize("discardAnyUnstagedChanges"), + command: "git checkout -- .", + handler: func() error { + return gui.GitCommand.DiscardAnyUnstagedFileChanges() + }, + }, + { + description: gui.Tr.SLocalize("discardUntrackedFiles"), + command: "git clean -fd", + handler: func() error { + return gui.GitCommand.RemoveUntrackedFiles() + }, + }, + { + description: gui.Tr.SLocalize("hardReset"), + command: "git reset --hard HEAD", + handler: func() error { + return gui.GitCommand.ResetHardHead() + }, + }, + { + description: gui.Tr.SLocalize("cancel"), + handler: func() error { + return nil + }, + }, + } + + handleMenuPress := func(index int) error { + if err := options[index].handler(); err != nil { + return err + } + + return gui.refreshFiles() + } + + return gui.createMenu("", options, handleMenuPress) +} diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go index add38dd59..662c7cce6 100644 --- a/pkg/i18n/dutch.go +++ b/pkg/i18n/dutch.go @@ -158,9 +158,6 @@ func addDutch(i18nObject *i18n.Bundle) error { ID: "FileNoMergeCons", Other: "Dit bestand heeft geen merge conflicten", }, &i18n.Message{ - ID: "SureResetHardHead", - Other: "Weet je het zeker dat je `reset --hard HEAD` en `clean -fd` wil uitvoeren? Het kan dat je hierdoor bestanden verliest", - }, &i18n.Message{ ID: "SureTo", Other: "Weet je het zeker dat je {{.fileName}} wilt {{.deleteVerb}} (je veranderingen zullen worden verwijderd)", }, &i18n.Message{ @@ -341,9 +338,6 @@ func addDutch(i18nObject *i18n.Bundle) error { ID: "CantCloseConfirmationPrompt", Other: "Kon de bevestiging prompt niet sluiten: {{.error}}", }, &i18n.Message{ - ID: "ClearFilePanel", - Other: "maak bestandsvenster leeg", - }, &i18n.Message{ ID: "MergeAborted", Other: "Merge afgebroken", }, &i18n.Message{ @@ -694,6 +688,18 @@ func addDutch(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "discardUnstagedChanges", Other: "discard unstaged changes", + }, &i18n.Message{ + ID: "discardAllChangesToAllFiles", + Other: "nuke working tree", + }, &i18n.Message{ + ID: "discardAnyUnstagedChanges", + Other: "discard unstaged changes", + }, &i18n.Message{ + ID: "discardUntrackedFiles", + Other: "discard untracked files", + }, &i18n.Message{ + ID: "hardReset", + Other: "hard reset", }, ) } diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 7f22e82bd..4e2a6a094 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -181,9 +181,6 @@ func addEnglish(i18nObject *i18n.Bundle) error { ID: "FileNoMergeCons", Other: "This file has no inline merge conflicts", }, &i18n.Message{ - ID: "SureResetHardHead", - Other: "Are you sure you want to `reset --hard HEAD` and `clean -fd`? You may lose changes", - }, &i18n.Message{ ID: "SoftReset", Other: "Soft reset", }, &i18n.Message{ @@ -406,9 +403,6 @@ func addEnglish(i18nObject *i18n.Bundle) error { ID: "NoChangedFiles", Other: "No changed files", }, &i18n.Message{ - ID: "ClearFilePanel", - Other: "Clear file panel", - }, &i18n.Message{ ID: "MergeAborted", Other: "Merge aborted", }, &i18n.Message{ @@ -717,6 +711,18 @@ func addEnglish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "discardUnstagedChanges", Other: "discard unstaged changes", + }, &i18n.Message{ + ID: "discardAllChangesToAllFiles", + Other: "nuke working tree", + }, &i18n.Message{ + ID: "discardAnyUnstagedChanges", + Other: "discard unstaged changes", + }, &i18n.Message{ + ID: "discardUntrackedFiles", + Other: "discard untracked files", + }, &i18n.Message{ + ID: "hardReset", + Other: "hard reset", }, ) } diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go index b8e43059f..049c7cefa 100644 --- a/pkg/i18n/polish.go +++ b/pkg/i18n/polish.go @@ -147,9 +147,6 @@ func addPolish(i18nObject *i18n.Bundle) error { ID: "FileNoMergeCons", Other: "Ten plik nie powoduje konfliktów scalania", }, &i18n.Message{ - ID: "SureResetHardHead", - Other: "Jesteś pewny, że chcesz wykonać `reset --hard HEAD` i `clean -fd`? Możesz stracić wprowadzone zmiany", - }, &i18n.Message{ ID: "SureTo", Other: "Jesteś pewny, że chcesz {{.deleteVerb}} {{.fileName}} (stracisz swoje wprowadzone zmiany)?", }, &i18n.Message{ @@ -333,9 +330,6 @@ func addPolish(i18nObject *i18n.Bundle) error { ID: "CantCloseConfirmationPrompt", Other: "Nie można zamknąć monitu potwierdzenia: {{.error}}", }, &i18n.Message{ - ID: "ClearFilePanel", - Other: "Wyczyść panel plików", - }, &i18n.Message{ ID: "MergeAborted", Other: "Scalanie anulowane", }, &i18n.Message{ @@ -677,6 +671,18 @@ func addPolish(i18nObject *i18n.Bundle) error { }, &i18n.Message{ ID: "discardUnstagedChanges", Other: "discard unstaged changes", + }, &i18n.Message{ + ID: "discardAllChangesToAllFiles", + Other: "nuke working tree", + }, &i18n.Message{ + ID: "discardAnyUnstagedChanges", + Other: "discard unstaged changes", + }, &i18n.Message{ + ID: "discardUntrackedFiles", + Other: "discard untracked files", + }, &i18n.Message{ + ID: "hardReset", + Other: "hard reset", }, ) } |