summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/commands/git.go15
-rw-r--r--pkg/commands/git_test.go41
-rw-r--r--pkg/commands/os.go6
-rw-r--r--pkg/gui/files_panel.go91
-rw-r--r--pkg/gui/keybindings.go4
-rw-r--r--pkg/i18n/dutch.go15
-rw-r--r--pkg/i18n/english.go15
-rw-r--r--pkg/i18n/polish.go15
8 files changed, 151 insertions, 51 deletions
diff --git a/pkg/commands/git.go b/pkg/commands/git.go
index af39ab2d2..e674dc720 100644
--- a/pkg/commands/git.go
+++ b/pkg/commands/git.go
@@ -438,8 +438,8 @@ func (c *GitCommand) RebaseMode() (string, error) {
}
}
-// RemoveFile directly
-func (c *GitCommand) RemoveFile(file *File) error {
+// DiscardAllFileChanges directly
+func (c *GitCommand) DiscardAllFileChanges(file *File) error {
// if the file isn't tracked, we assume you want to delete it
quotedFileName := c.OSCommand.Quote(file.Name)
if file.HasStagedChanges {
@@ -450,7 +450,12 @@ func (c *GitCommand) RemoveFile(file *File) error {
if !file.Tracked {
return c.removeFile(file.Name)
}
- // if the file is tracked, we assume you want to just check it out
+ return c.DiscardUnstagedFileChanges(file)
+}
+
+// DiscardUnstagedFileChanges directly
+func (c *GitCommand) DiscardUnstagedFileChanges(file *File) error {
+ quotedFileName := c.OSCommand.Quote(file.Name)
return c.OSCommand.RunCommand(fmt.Sprintf("git checkout -- %s", quotedFileName))
}
@@ -575,7 +580,7 @@ func (c *GitCommand) ApplyPatch(patch string) (string, error) {
return "", err
}
- defer func() { _ = c.OSCommand.RemoveFile(filename) }()
+ defer func() { _ = c.OSCommand.Remove(filename) }()
return c.OSCommand.RunCommandWithOutput(fmt.Sprintf("git apply --cached %s", c.OSCommand.Quote(filename)))
}
@@ -861,7 +866,7 @@ func (c *GitCommand) DiscardOldFileChanges(commits []*Commit, commitIndex int, f
// check if file exists in previous commit (this command returns an error if the file doesn't exist)
if err := c.OSCommand.RunCommand(fmt.Sprintf("git cat-file -e HEAD^:%s", fileName)); err != nil {
- if err := c.OSCommand.RemoveFile(fileName); err != nil {
+ if err := c.OSCommand.Remove(fileName); err != nil {
return err
}
if err := c.StageFile(fileName); err != nil {
diff --git a/pkg/commands/git_test.go b/pkg/commands/git_test.go
index 8fbdc1642..614ad527b 100644
--- a/pkg/commands/git_test.go
+++ b/pkg/commands/git_test.go
@@ -1140,8 +1140,8 @@ func TestGitCommandIsInMergeState(t *testing.T) {
}
}
-// TestGitCommandRemoveFile is a function.
-func TestGitCommandRemoveFile(t *testing.T) {
+// TestGitCommandDiscardAllFileChanges is a function.
+func TestGitCommandDiscardAllFileChanges(t *testing.T) {
type scenario struct {
testName string
command func() (func(string, ...string) *exec.Cmd, *[][]string)
@@ -1337,7 +1337,7 @@ func TestGitCommandRemoveFile(t *testing.T) {
gitCmd := NewDummyGitCommand()
gitCmd.OSCommand.command, cmdsCalled = s.command()
gitCmd.removeFile = s.removeFile
- s.test(cmdsCalled, gitCmd.RemoveFile(s.file))
+ s.test(cmdsCalled, gitCmd.DiscardAllFileChanges(s.file))
})
}
}
@@ -1932,3 +1932,38 @@ func TestGitCommandGetCommitFiles(t *testing.T) {
})
}
}
+
+// TestGitCommandDiscardUnstagedChanges is a function.
+func TestGitCommandDiscardUnstagedChanges(t *testing.T) {
+ type scenario struct {
+ testName string
+ file *File
+ command func(string, ...string) *exec.Cmd
+ test func(error)
+ }
+
+ scenarios := []scenario{
+ {
+ "valid case",
+ &File{Name: "test.txt"},
+ test.CreateMockCommand(t, []*test.CommandSwapper{
+ {
+ Expect: `git checkout -- "test.txt"`,
+ 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.DiscardUnstagedFileChanges(s.file))
+ })
+ }
+}
diff --git a/pkg/commands/os.go b/pkg/commands/os.go
index 9e0967cba..1fb8e8da6 100644
--- a/pkg/commands/os.go
+++ b/pkg/commands/os.go
@@ -255,9 +255,9 @@ func (c *OSCommand) CreateTempFile(filename, content string) (string, error) {
return tmpfile.Name(), nil
}
-// RemoveFile removes a file at the specified path
-func (c *OSCommand) RemoveFile(filename string) error {
- err := os.Remove(filename)
+// Remove removes a file or directory at the specified path
+func (c *OSCommand) Remove(filename string) error {
+ err := os.RemoveAll(filename)
return WrapError(err)
}
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 843286e9e..deaffb83b 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -259,35 +259,6 @@ func (gui *Gui) handleAddPatch(g *gocui.Gui, v *gocui.View) error {
return gui.Errors.ErrSubProcess
}
-func (gui *Gui) handleFileRemove(g *gocui.Gui, v *gocui.View) error {
- file, err := gui.getSelectedFile(g)
- if err != nil {
- if err == gui.Errors.ErrNoFiles {
- return nil
- }
- return err
- }
- var deleteVerb string
- if file.Tracked {
- deleteVerb = gui.Tr.SLocalize("checkout")
- } else {
- deleteVerb = gui.Tr.SLocalize("delete")
- }
- message := gui.Tr.TemplateLocalize(
- "SureTo",
- Teml{
- "deleteVerb": deleteVerb,
- "fileName": file.Name,
- },
- )
- return gui.createConfirmationPanel(g, v, strings.Title(deleteVerb)+" file", message, func(g *gocui.Gui, v *gocui.View) error {
- if err := gui.GitCommand.RemoveFile(file); err != nil {
- return gui.createErrorPanel(gui.g, err.Error())
- }
- return gui.refreshFiles()
- }, nil)
-}
-
func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error {
file, err := gui.getSelectedFile(g)
if err != nil {
@@ -521,3 +492,65 @@ func (gui *Gui) handleSoftReset(g *gocui.Gui, v *gocui.View) error {
return gui.refreshFiles()
}, nil)
}
+
+type discardOption struct {
+ handler func(fileName *commands.File) error
+ description string
+}
+
+type discardOptionValue int
+
+// GetDisplayStrings is a function.
+func (r *discardOption) GetDisplayStrings(isFocused bool) []string {
+ return []string{r.description}
+}
+
+func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error {
+ file, err := gui.getSelectedFile(g)
+ if err != nil {
+ if err != gui.Errors.ErrNoFiles {
+ return err
+ }
+ return nil
+ }
+
+ options := []*discardOption{
+ {
+ description: gui.Tr.SLocalize("discardAllChanges"),
+ handler: func(file *commands.File) error {
+ if err := gui.GitCommand.DiscardAllFileChanges(file); err != nil {
+ return err
+ }
+
+ return gui.refreshFiles()
+ },
+ },
+ {
+ description: gui.Tr.SLocalize("cancel"),
+ handler: func(file *commands.File) error {
+ return nil
+ },
+ },
+ }
+
+ if file.HasStagedChanges && file.HasUnstagedChanges {
+ 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()
+ },
+ }
+
+ options = append(options[:1], append([]*discardOption{discardUnstagedChanges}, options[1:]...)...)
+ }
+
+ handleMenuPress := func(index int) error {
+ return options[index].handler(file)
+ }
+
+ return gui.createMenu(file.Name, options, handleMenuPress)
+}
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index ae8858124..172e76896 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -176,8 +176,8 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "files",
Key: 'd',
Modifier: gocui.ModNone,
- Handler: gui.handleFileRemove,
- Description: gui.Tr.SLocalize("removeFile"),
+ Handler: gui.handleCreateDiscardMenu,
+ Description: gui.Tr.SLocalize("viewDiscardOptions"),
}, {
ViewName: "files",
Key: 'e',
diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go
index 77b3052d9..add38dd59 100644
--- a/pkg/i18n/dutch.go
+++ b/pkg/i18n/dutch.go
@@ -383,9 +383,6 @@ func addDutch(i18nObject *i18n.Bundle) error {
ID: "GitconfigParseErr",
Other: `Gogit kon je gitconfig bestand niet goed parsen door de aanwezigheid van losstaande '\' tekens. Het weghalen van deze tekens zou het probleem moeten oplossen. `,
}, &i18n.Message{
- ID: "removeFile",
- Other: `Verwijder als untracked / uitchecken wordt gevolgd (ga weg)`,
- }, &i18n.Message{
ID: "editFile",
Other: `verander bestand`,
}, &i18n.Message{
@@ -685,6 +682,18 @@ func addDutch(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "StashPrefix",
Other: "Auto-stashing changes for ",
+ }, &i18n.Message{
+ ID: "viewDiscardOptions",
+ Other: "view 'discard changes' options",
+ }, &i18n.Message{
+ ID: "cancel",
+ Other: "cancel",
+ }, &i18n.Message{
+ ID: "discardAllChanges",
+ Other: "discard all changes",
+ }, &i18n.Message{
+ ID: "discardUnstagedChanges",
+ Other: "discard unstaged changes",
},
)
}
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index 09805540a..7f22e82bd 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -448,9 +448,6 @@ func addEnglish(i18nObject *i18n.Bundle) error {
ID: "GitconfigParseErr",
Other: `Gogit failed to parse your gitconfig file due to the presence of unquoted '\' characters. Removing these should fix the issue.`,
}, &i18n.Message{
- ID: "removeFile",
- Other: `delete if untracked / checkout if tracked`,
- }, &i18n.Message{
ID: "editFile",
Other: `edit file`,
}, &i18n.Message{
@@ -708,6 +705,18 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "StashPrefix",
Other: "Auto-stashing changes for ",
+ }, &i18n.Message{
+ ID: "viewDiscardOptions",
+ Other: "view 'discard changes' options",
+ }, &i18n.Message{
+ ID: "cancel",
+ Other: "cancel",
+ }, &i18n.Message{
+ ID: "discardAllChanges",
+ Other: "discard all changes",
+ }, &i18n.Message{
+ ID: "discardUnstagedChanges",
+ Other: "discard unstaged changes",
},
)
}
diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go
index 951bc3728..b8e43059f 100644
--- a/pkg/i18n/polish.go
+++ b/pkg/i18n/polish.go
@@ -372,9 +372,6 @@ func addPolish(i18nObject *i18n.Bundle) error {
ID: "AnonymousReportingPrompt",
Other: "Włączyć anonimowe raportowanie błędów w celu pomocy w usprawnianiu lazygita (enter/esc)?",
}, &i18n.Message{
- ID: "removeFile",
- Other: `usuń jeśli nie śledzony / przełącz jeśli śledzony`,
- }, &i18n.Message{
ID: "editFile",
Other: `edytuj plik`,
}, &i18n.Message{
@@ -668,6 +665,18 @@ func addPolish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{
ID: "StashPrefix",
Other: "Auto-stashing changes for ",
+ }, &i18n.Message{
+ ID: "viewDiscardOptions",
+ Other: "view 'discard changes' options",
+ }, &i18n.Message{
+ ID: "cancel",
+ Other: "cancel",
+ }, &i18n.Message{
+ ID: "discardAllChanges",
+ Other: "discard all changes",
+ }, &i18n.Message{
+ ID: "discardUnstagedChanges",
+ Other: "discard unstaged changes",
},
)
}