Skip to content

Commit 1fa9ea7

Browse files
brandondongstefanhaller
authored andcommitted
Fix discarding submodule changes in nested folders
The current rules for discarding submodule changes is that no other changed item must be also selected. There are some bugs with the current implementation when submodules are in folders. For example, selecting and discarding a folder with only a nested submodule change will currently do nothing. The submodule changes should be discarded. The folder only contains submodule changes so it should be no different than pressing discard on the submodule entry itself. Also, I noticed range selecting both the folder and the submodule and then pressing discard would be incorrectly disallowed.
1 parent 106b701 commit 1fa9ea7

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

pkg/gui/controllers/files_controller.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77
"strings"
88

9+
"github.com/jesseduffield/generics/set"
910
"github.com/jesseduffield/gocui"
1011
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
1112
"github.com/jesseduffield/lazygit/pkg/commands/models"
@@ -1194,13 +1195,36 @@ func filterNodesHaveUnstagedChanges(nodes []*filetree.FileNode) []*filetree.File
11941195
})
11951196
}
11961197

1198+
func findSubmoduleNode(nodes []*filetree.FileNode, submodules []*models.SubmoduleConfig) *models.File {
1199+
for _, node := range nodes {
1200+
submoduleNode := node.FindFirstFileBy(func(f *models.File) bool {
1201+
return f.IsSubmodule(submodules)
1202+
})
1203+
if submoduleNode != nil {
1204+
return submoduleNode
1205+
}
1206+
}
1207+
return nil
1208+
}
1209+
11971210
func (self *FilesController) canRemove(selectedNodes []*filetree.FileNode) *types.DisabledReason {
1211+
// Return disabled if the selection contains multiple changed items and includes a submodule change.
11981212
submodules := self.c.Model().Submodules
1199-
submoduleCount := lo.CountBy(selectedNodes, func(node *filetree.FileNode) bool {
1200-
return node.File != nil && node.File.IsSubmodule(submodules)
1201-
})
1202-
if submoduleCount > 0 && len(selectedNodes) > 1 {
1203-
return &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupportedForSubmodules}
1213+
hasFiles := false
1214+
uniqueSelectedSubmodules := set.New[*models.SubmoduleConfig]()
1215+
1216+
for _, node := range selectedNodes {
1217+
_ = node.ForEachFile(func(f *models.File) error {
1218+
if submodule := f.SubmoduleConfig(submodules); submodule != nil {
1219+
uniqueSelectedSubmodules.Add(submodule)
1220+
} else {
1221+
hasFiles = true
1222+
}
1223+
return nil
1224+
})
1225+
if uniqueSelectedSubmodules.Len() > 0 && (hasFiles || uniqueSelectedSubmodules.Len() > 1) {
1226+
return &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupportedForSubmodules}
1227+
}
12041228
}
12051229

12061230
return nil
@@ -1209,11 +1233,13 @@ func (self *FilesController) canRemove(selectedNodes []*filetree.FileNode) *type
12091233
func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
12101234
submodules := self.c.Model().Submodules
12111235

1236+
selectedNodes = normalisedSelectedNodes(selectedNodes)
1237+
12121238
// If we have one submodule then we must only have one submodule or `canRemove` would have
12131239
// returned an error
1214-
firstNode := selectedNodes[0]
1215-
if firstNode.File != nil && firstNode.File.IsSubmodule(submodules) {
1216-
submodule := firstNode.File.SubmoduleConfig(submodules)
1240+
submoduleNode := findSubmoduleNode(selectedNodes, submodules)
1241+
if submoduleNode != nil {
1242+
submodule := submoduleNode.SubmoduleConfig(submodules)
12171243

12181244
menuItems := []*types.MenuItem{
12191245
{
@@ -1224,11 +1250,9 @@ func (self *FilesController) remove(selectedNodes []*filetree.FileNode) error {
12241250
},
12251251
}
12261252

1227-
return self.c.Menu(types.CreateMenuOptions{Title: firstNode.GetPath(), Items: menuItems})
1253+
return self.c.Menu(types.CreateMenuOptions{Title: submoduleNode.GetPath(), Items: menuItems})
12281254
}
12291255

1230-
selectedNodes = normalisedSelectedNodes(selectedNodes)
1231-
12321256
discardAllChangesItem := types.MenuItem{
12331257
Label: self.c.Tr.DiscardAllChanges,
12341258
OnPress: func() error {

pkg/gui/filetree/node.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,22 @@ func (self *Node[T]) EveryFile(predicate func(*T) bool) bool {
169169
return true
170170
}
171171

172+
func (self *Node[T]) FindFirstFileBy(predicate func(*T) bool) *T {
173+
if self.IsFile() {
174+
if predicate(self.File) {
175+
return self.File
176+
}
177+
} else {
178+
for _, child := range self.Children {
179+
if file := child.FindFirstFileBy(predicate); file != nil {
180+
return file
181+
}
182+
}
183+
}
184+
185+
return nil
186+
}
187+
172188
func (self *Node[T]) Flatten(collapsedPaths *CollapsedPaths) []*Node[T] {
173189
result := []*Node[T]{self}
174190

0 commit comments

Comments
 (0)