From cd0532b4d6e9dcb846c6ce5ad88be7e0cf671a40 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Tue, 16 Mar 2021 09:07:00 +1100 Subject: [PATCH] allow ignoring directories --- pkg/commands/files.go | 2 +- pkg/commands/models/status_line_node.go | 26 +++++++++++++++-- pkg/gui/files_panel.go | 39 ++++++++++++++++++++----- pkg/gui/keybindings.go | 2 +- 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/pkg/commands/files.go b/pkg/commands/files.go index 740928759..e7332dbbe 100644 --- a/pkg/commands/files.go +++ b/pkg/commands/files.go @@ -31,7 +31,7 @@ func (c *GitCommand) StageAll() error { return c.OSCommand.RunCommand("git add -A") } -// UnstageAll stages all files +// UnstageAll unstages all files func (c *GitCommand) UnstageAll() error { return c.OSCommand.RunCommand("git reset") } diff --git a/pkg/commands/models/status_line_node.go b/pkg/commands/models/status_line_node.go index e0a9051e2..ce85cfec8 100644 --- a/pkg/commands/models/status_line_node.go +++ b/pkg/commands/models/status_line_node.go @@ -144,13 +144,19 @@ func (s *StatusLineNode) sortChildren() { s.Children = sortedChildren } +// returns true if any descendant file is tracked func (s *StatusLineNode) GetIsTracked() bool { if s.File != nil { return s.File.GetIsTracked() } - // pretty sure I'm allowed to do this - return true + for _, child := range s.Children { + if child.GetIsTracked() { + return true + } + } + + return false } func (s *StatusLineNode) GetPath() string { @@ -211,3 +217,19 @@ func (s *StatusLineNode) ID() string { func (s *StatusLineNode) Description() string { return s.GetPath() } + +func (s *StatusLineNode) ForEachFile(cb func(*File) error) error { + if s.File != nil { + if err := cb(s.File); err != nil { + return err + } + } + + for _, child := range s.Children { + if err := child.ForEachFile(cb); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 772b05cf3..30ce0a51f 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -294,24 +294,43 @@ func (gui *Gui) handleStageAll(g *gocui.Gui, v *gocui.View) error { return gui.selectFile(false) } -func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { - file := gui.getSelectedFile() - if file == nil { +func (gui *Gui) handleIgnoreFile() error { + node := gui.getSelectedStatusNode() + if node == nil { return nil } - if file.Name == ".gitignore" { + + if node.GetPath() == ".gitignore" { return gui.createErrorPanel("Cannot ignore .gitignore") } - if file.Tracked { + unstageFiles := func() error { + return node.ForEachFile(func(file *models.File) error { + if file.HasStagedChanges { + if err := gui.GitCommand.UnStageFile(file.Name, file.Tracked); err != nil { + return err + } + } + + return nil + }) + } + + if node.GetIsTracked() { return gui.ask(askOpts{ title: gui.Tr.IgnoreTracked, prompt: gui.Tr.IgnoreTrackedPrompt, handleConfirm: func() error { - if err := gui.GitCommand.Ignore(file.Name); err != nil { + // not 100% sure if this is necessary but I'll assume it is + if err := unstageFiles(); err != nil { return err } - if err := gui.GitCommand.RemoveTrackedFiles(file.Name); err != nil { + + if err := gui.GitCommand.RemoveTrackedFiles(node.GetPath()); err != nil { + return err + } + + if err := gui.GitCommand.Ignore(node.GetPath()); err != nil { return err } return gui.refreshSidePanels(refreshOptions{scope: []int{FILES}}) @@ -319,7 +338,11 @@ func (gui *Gui) handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { }) } - if err := gui.GitCommand.Ignore(file.Name); err != nil { + if err := unstageFiles(); err != nil { + return err + } + + if err := gui.GitCommand.Ignore(node.GetPath()); err != nil { return gui.surfaceError(err) } diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index ea6e13e99..fc6107a96 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -430,7 +430,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { ViewName: "files", Contexts: []string{FILES_CONTEXT_KEY}, Key: gui.getKey(config.Files.IgnoreFile), - Handler: gui.handleIgnoreFile, + Handler: gui.wrappedHandler(gui.handleIgnoreFile), Description: gui.Tr.LcIgnoreFile, }, {