Skip to content

Commit

Permalink
WIP: Support discarding a range of files
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseduffield committed Jan 10, 2024
1 parent 0d19776 commit 9c3c2ab
Showing 1 changed file with 72 additions and 1 deletion.
73 changes: 72 additions & 1 deletion pkg/gui/controllers/files_remove_controller.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package controllers

import (
"strings"

"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)

// splitting this action out into its own file because it's self-contained
Expand Down Expand Up @@ -40,9 +43,77 @@ func (self *FilesRemoveController) GetKeybindings(opts types.KeybindingsOpts) []
return bindings
}

// for discarding I would need to order by depth and skip any paths whose ancestors have already been discarded. I could even use a helper for getting all the nodes, minus the ones that are descendents of other selected nodes. Then I just need to loop through each node and discard it.

// Couldn't think of a better term than 'normalised'. Alas.
// The idea is that when you select a range of nodes, you will often have both
// a node and its parent node selected. If we are trying to discard changes to the
// selected nodes, we'll get an error if we try to discard the child after the parent.
// So we just need to filter out any nodes from the selection that are descendants
// of other nodes
func (self *FilesRemoveController) NormalisedSelectedNodes() []*filetree.FileNode {
selectedNodes := self.SelectedNodes()

return lo.Filter(selectedNodes, func(node *filetree.FileNode, _ int) bool {
return !self.isDescendentOfSelectedNodes(node, selectedNodes)
})
}

func (self *FilesRemoveController) SelectedNodes() []*filetree.FileNode {
startIdx, endIdx := self.context().GetSelectionRange()

nodes := []*filetree.FileNode{}
for i := startIdx; i <= endIdx; i++ {
nodes = append(nodes, self.context().Get(i))
}

return nodes
}

func (self *FilesRemoveController) isDescendentOfSelectedNodes(node *filetree.FileNode, selectedNodes []*filetree.FileNode) bool {
for _, selectedNode := range selectedNodes {
selectedNodePath := selectedNode.GetPath()
nodePath := node.GetPath()

if strings.HasPrefix(nodePath, selectedNodePath) && nodePath != selectedNodePath {
return true
}
}
return false
}

func (self *FilesRemoveController) remove(node *filetree.FileNode) error {
var menuItems []*types.MenuItem
if node.File == nil {
if self.context().IsSelectingRange() {
menuItems = []*types.MenuItem{
{
Label: self.c.Tr.DiscardAllChanges,
OnPress: func() error {
self.c.LogAction(self.c.Tr.Actions.DiscardAllChangesInDirectory)

if self.context().IsSelectingRange() {
defer self.context().CancelRangeSelect()
}

selectedNodes := self.NormalisedSelectedNodes()
for _, node := range selectedNodes {
if err := self.c.Git().WorkingTree.DiscardAllDirChanges(node); err != nil {
return self.c.Error(err)
}
}

return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.WORKTREES}})
},
Key: self.c.KeybindingsOpts().GetKey(self.c.UserConfig.Keybinding.Files.ConfirmDiscard),
Tooltip: utils.ResolvePlaceholderString(
self.c.Tr.DiscardAllTooltip,
map[string]string{
"path": node.GetPath(),
},
),
},
}
} else if node.File == nil {
menuItems = []*types.MenuItem{
{
Label: self.c.Tr.DiscardAllChanges,
Expand Down

0 comments on commit 9c3c2ab

Please sign in to comment.