Skip to content

Commit a22aced

Browse files
authored
Avoid auto-stashing when only submodules are out of date (#4969)
Stashing doesn't affect submodules, so if you have a working copy that has out-of-date submodules but no other changes, and then you revert or paste a commit (or invoke one of the many other lazygit commands that auto-stash, e.g. undo), lazygit would previously try to stash changes (which did nothing, but also didn't return an error), perform the operation, and then pop the stash again. If no stashes existed before, then this would only cause a confusing error popup ("error: refs/stash@{0} is not a valid reference"), but if there were stashes, this would try to pop the newest one of these, which is very undesirable and confusing.
2 parents 7282159 + 40cc008 commit a22aced

File tree

8 files changed

+34
-18
lines changed

8 files changed

+34
-18
lines changed

pkg/gui/controllers/custom_patch_options_menu_action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error
173173

174174
self.returnFocusFromPatchExplorerIfNecessary()
175175

176-
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirty()
176+
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules()
177177
return self.c.ConfirmIf(mustStash, types.ConfirmOpts{
178178
Title: self.c.Tr.MustStashTitle,
179179
Prompt: self.c.Tr.MustStashWarning,

pkg/gui/controllers/files_controller.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ func (self *FilesController) createStashMenu() error {
973973
{
974974
Label: self.c.Tr.StashAllChanges,
975975
OnPress: func() error {
976-
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
976+
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
977977
return errors.New(self.c.Tr.NoFilesToStash)
978978
}
979979
return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashAllChanges)
@@ -983,7 +983,7 @@ func (self *FilesController) createStashMenu() error {
983983
{
984984
Label: self.c.Tr.StashAllChangesKeepIndex,
985985
OnPress: func() error {
986-
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
986+
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
987987
return errors.New(self.c.Tr.NoFilesToStash)
988988
}
989989
// if there are no staged files it behaves the same as Stash.Save
@@ -1002,7 +1002,7 @@ func (self *FilesController) createStashMenu() error {
10021002
Label: self.c.Tr.StashStagedChanges,
10031003
OnPress: func() error {
10041004
// there must be something in staging otherwise the current implementation mucks the stash up
1005-
if !self.c.Helpers().WorkingTree.AnyStagedFiles() {
1005+
if !self.c.Helpers().WorkingTree.AnyStagedFilesExceptSubmodules() {
10061006
return errors.New(self.c.Tr.NoTrackedStagedFilesStash)
10071007
}
10081008
return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges)
@@ -1012,10 +1012,10 @@ func (self *FilesController) createStashMenu() error {
10121012
{
10131013
Label: self.c.Tr.StashUnstagedChanges,
10141014
OnPress: func() error {
1015-
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
1015+
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
10161016
return errors.New(self.c.Tr.NoFilesToStash)
10171017
}
1018-
if self.c.Helpers().WorkingTree.AnyStagedFiles() {
1018+
if self.c.Helpers().WorkingTree.AnyStagedFilesExceptSubmodules() {
10191019
return self.handleStashSave(self.c.Git().Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges)
10201020
}
10211021
// ordinary stash

pkg/gui/controllers/helpers/cherry_pick_helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (self *CherryPickHelper) Paste() error {
7777
}),
7878
HandleConfirm: func() error {
7979
return self.c.WithWaitingStatusSync(self.c.Tr.CherryPickingStatus, func() error {
80-
mustStash := IsWorkingTreeDirty(self.c.Model().Files)
80+
mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
8181

8282
self.c.LogAction(self.c.Tr.Actions.CherryPick)
8383

pkg/gui/controllers/helpers/refs_helper.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
258258
style.FgRed.Sprintf("reset --%s %s", row.strength, name),
259259
},
260260
OnPress: func() error {
261-
return self.c.ConfirmIf(row.strength == "hard" && IsWorkingTreeDirty(self.c.Model().Files),
261+
return self.c.ConfirmIf(row.strength == "hard" && IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules),
262262
types.ConfirmOpts{
263263
Title: self.c.Tr.Actions.HardReset,
264264
Prompt: self.c.Tr.ResetHardConfirmation,
@@ -484,7 +484,7 @@ func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchNa
484484
return err
485485
}
486486

487-
mustStash := IsWorkingTreeDirty(self.c.Model().Files)
487+
mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
488488
if mustStash {
489489
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil {
490490
return err
@@ -517,7 +517,7 @@ func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName stri
517517
return commit.Status == models.StatusUnpushed
518518
})
519519

520-
mustStash := IsWorkingTreeDirty(self.c.Model().Files)
520+
mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
521521
if mustStash {
522522
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil {
523523
return err

pkg/gui/controllers/helpers/working_tree_helper.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ func AnyStagedFiles(files []*models.File) bool {
4747
return lo.SomeBy(files, func(f *models.File) bool { return f.HasStagedChanges })
4848
}
4949

50+
func (self *WorkingTreeHelper) AnyStagedFilesExceptSubmodules() bool {
51+
return AnyStagedFilesExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
52+
}
53+
54+
func AnyStagedFilesExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool {
55+
return lo.SomeBy(files, func(f *models.File) bool { return f.HasStagedChanges && !f.IsSubmodule(submoduleConfigs) })
56+
}
57+
5058
func (self *WorkingTreeHelper) AnyTrackedFiles() bool {
5159
return AnyTrackedFiles(self.c.Model().Files)
5260
}
@@ -55,12 +63,20 @@ func AnyTrackedFiles(files []*models.File) bool {
5563
return lo.SomeBy(files, func(f *models.File) bool { return f.Tracked })
5664
}
5765

58-
func (self *WorkingTreeHelper) IsWorkingTreeDirty() bool {
59-
return IsWorkingTreeDirty(self.c.Model().Files)
66+
func (self *WorkingTreeHelper) AnyTrackedFilesExceptSubmodules() bool {
67+
return AnyTrackedFilesExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
68+
}
69+
70+
func AnyTrackedFilesExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool {
71+
return lo.SomeBy(files, func(f *models.File) bool { return f.Tracked && !f.IsSubmodule(submoduleConfigs) })
72+
}
73+
74+
func (self *WorkingTreeHelper) IsWorkingTreeDirtyExceptSubmodules() bool {
75+
return IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
6076
}
6177

62-
func IsWorkingTreeDirty(files []*models.File) bool {
63-
return AnyStagedFiles(files) || AnyTrackedFiles(files)
78+
func IsWorkingTreeDirtyExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool {
79+
return AnyStagedFilesExceptSubmodules(files, submoduleConfigs) || AnyTrackedFilesExceptSubmodules(files, submoduleConfigs)
6480
}
6581

6682
func (self *WorkingTreeHelper) FileForSubmodule(submodule *models.SubmoduleConfig) *models.File {

pkg/gui/controllers/local_commits_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ func (self *LocalCommitsController) revert(commits []*models.Commit, start, end
856856
HandleConfirm: func() error {
857857
self.c.LogAction(self.c.Tr.Actions.RevertCommit)
858858
return self.c.WithWaitingStatusSync(self.c.Tr.RevertingStatus, func() error {
859-
mustStash := helpers.IsWorkingTreeDirty(self.c.Model().Files)
859+
mustStash := helpers.IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
860860

861861
if mustStash {
862862
if err := self.c.Git().Stash.Push(self.c.Tr.AutoStashForReverting); err != nil {

pkg/gui/controllers/undo_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ func (self *UndoController) hardResetWithAutoStash(commitHash string, options ha
257257
}
258258

259259
// if we have any modified tracked files we need to auto-stash
260-
dirtyWorkingTree := self.c.Helpers().WorkingTree.IsWorkingTreeDirty()
260+
dirtyWorkingTree := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules()
261261
if dirtyWorkingTree {
262262
return self.c.WithWaitingStatus(options.WaitingStatus, func(gocui.Task) error {
263263
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForUndo, utils.ShortHash(commitHash))); err != nil {

pkg/gui/controllers/workspace_reset_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (self *FilesController) createResetMenu() error {
100100
Tooltip: self.c.Tr.DiscardStagedChangesDescription,
101101
OnPress: func() error {
102102
self.c.LogAction(self.c.Tr.Actions.RemoveStagedFiles)
103-
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
103+
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
104104
return errors.New(self.c.Tr.NoTrackedStagedFilesStash)
105105
}
106106
if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil {
@@ -159,7 +159,7 @@ func (self *FilesController) createResetMenu() error {
159159
red.Sprint("git reset --hard HEAD"),
160160
},
161161
OnPress: func() error {
162-
return self.c.ConfirmIf(helpers.IsWorkingTreeDirty(self.c.Model().Files),
162+
return self.c.ConfirmIf(helpers.IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules),
163163
types.ConfirmOpts{
164164
Title: self.c.Tr.Actions.HardReset,
165165
Prompt: self.c.Tr.ResetHardConfirmation,

0 commit comments

Comments
 (0)