diff --git a/pkg/gui/controllers/custom_patch_options_menu_action.go b/pkg/gui/controllers/custom_patch_options_menu_action.go index d6a36c2e1..793048429 100644 --- a/pkg/gui/controllers/custom_patch_options_menu_action.go +++ b/pkg/gui/controllers/custom_patch_options_menu_action.go @@ -173,7 +173,7 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error self.returnFocusFromPatchExplorerIfNecessary() - mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirty() + mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() return self.c.ConfirmIf(mustStash, types.ConfirmOpts{ Title: self.c.Tr.MustStashTitle, Prompt: self.c.Tr.MustStashWarning, diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 4a3951c48..0289936de 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -973,7 +973,7 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.StashAllChanges, OnPress: func() error { - if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() { return errors.New(self.c.Tr.NoFilesToStash) } return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashAllChanges) @@ -983,7 +983,7 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.StashAllChangesKeepIndex, OnPress: func() error { - if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() { return errors.New(self.c.Tr.NoFilesToStash) } // if there are no staged files it behaves the same as Stash.Save @@ -1002,7 +1002,7 @@ func (self *FilesController) createStashMenu() error { Label: self.c.Tr.StashStagedChanges, OnPress: func() error { // there must be something in staging otherwise the current implementation mucks the stash up - if !self.c.Helpers().WorkingTree.AnyStagedFiles() { + if !self.c.Helpers().WorkingTree.AnyStagedFilesExceptSubmodules() { return errors.New(self.c.Tr.NoTrackedStagedFilesStash) } return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges) @@ -1012,10 +1012,10 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.StashUnstagedChanges, OnPress: func() error { - if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() { return errors.New(self.c.Tr.NoFilesToStash) } - if self.c.Helpers().WorkingTree.AnyStagedFiles() { + if self.c.Helpers().WorkingTree.AnyStagedFilesExceptSubmodules() { return self.handleStashSave(self.c.Git().Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges) } // ordinary stash diff --git a/pkg/gui/controllers/helpers/cherry_pick_helper.go b/pkg/gui/controllers/helpers/cherry_pick_helper.go index 8f5b37a66..c4be07ceb 100644 --- a/pkg/gui/controllers/helpers/cherry_pick_helper.go +++ b/pkg/gui/controllers/helpers/cherry_pick_helper.go @@ -77,7 +77,7 @@ func (self *CherryPickHelper) Paste() error { }), HandleConfirm: func() error { return self.c.WithWaitingStatusSync(self.c.Tr.CherryPickingStatus, func() error { - mustStash := IsWorkingTreeDirty(self.c.Model().Files) + mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) self.c.LogAction(self.c.Tr.Actions.CherryPick) diff --git a/pkg/gui/controllers/helpers/refs_helper.go b/pkg/gui/controllers/helpers/refs_helper.go index cfb9d3bab..39cda5bd4 100644 --- a/pkg/gui/controllers/helpers/refs_helper.go +++ b/pkg/gui/controllers/helpers/refs_helper.go @@ -258,7 +258,7 @@ func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error { style.FgRed.Sprintf("reset --%s %s", row.strength, name), }, OnPress: func() error { - return self.c.ConfirmIf(row.strength == "hard" && IsWorkingTreeDirty(self.c.Model().Files), + return self.c.ConfirmIf(row.strength == "hard" && IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules), types.ConfirmOpts{ Title: self.c.Tr.Actions.HardReset, Prompt: self.c.Tr.ResetHardConfirmation, @@ -484,7 +484,7 @@ func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchNa return err } - mustStash := IsWorkingTreeDirty(self.c.Model().Files) + mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) if mustStash { if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil { return err @@ -517,7 +517,7 @@ func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName stri return commit.Status == models.StatusUnpushed }) - mustStash := IsWorkingTreeDirty(self.c.Model().Files) + mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) if mustStash { if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil { return err diff --git a/pkg/gui/controllers/helpers/working_tree_helper.go b/pkg/gui/controllers/helpers/working_tree_helper.go index 9e6e36296..6437afa35 100644 --- a/pkg/gui/controllers/helpers/working_tree_helper.go +++ b/pkg/gui/controllers/helpers/working_tree_helper.go @@ -47,6 +47,14 @@ func AnyStagedFiles(files []*models.File) bool { return lo.SomeBy(files, func(f *models.File) bool { return f.HasStagedChanges }) } +func (self *WorkingTreeHelper) AnyStagedFilesExceptSubmodules() bool { + return AnyStagedFilesExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) +} + +func AnyStagedFilesExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool { + return lo.SomeBy(files, func(f *models.File) bool { return f.HasStagedChanges && !f.IsSubmodule(submoduleConfigs) }) +} + func (self *WorkingTreeHelper) AnyTrackedFiles() bool { return AnyTrackedFiles(self.c.Model().Files) } @@ -55,12 +63,20 @@ func AnyTrackedFiles(files []*models.File) bool { return lo.SomeBy(files, func(f *models.File) bool { return f.Tracked }) } -func (self *WorkingTreeHelper) IsWorkingTreeDirty() bool { - return IsWorkingTreeDirty(self.c.Model().Files) +func (self *WorkingTreeHelper) AnyTrackedFilesExceptSubmodules() bool { + return AnyTrackedFilesExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) } -func IsWorkingTreeDirty(files []*models.File) bool { - return AnyStagedFiles(files) || AnyTrackedFiles(files) +func AnyTrackedFilesExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool { + return lo.SomeBy(files, func(f *models.File) bool { return f.Tracked && !f.IsSubmodule(submoduleConfigs) }) +} + +func (self *WorkingTreeHelper) IsWorkingTreeDirtyExceptSubmodules() bool { + return IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) +} + +func IsWorkingTreeDirtyExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool { + return AnyStagedFilesExceptSubmodules(files, submoduleConfigs) || AnyTrackedFilesExceptSubmodules(files, submoduleConfigs) } func (self *WorkingTreeHelper) FileForSubmodule(submodule *models.SubmoduleConfig) *models.File { diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index b70a4ecb9..9badaf1ed 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -856,7 +856,7 @@ func (self *LocalCommitsController) revert(commits []*models.Commit, start, end HandleConfirm: func() error { self.c.LogAction(self.c.Tr.Actions.RevertCommit) return self.c.WithWaitingStatusSync(self.c.Tr.RevertingStatus, func() error { - mustStash := helpers.IsWorkingTreeDirty(self.c.Model().Files) + mustStash := helpers.IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules) if mustStash { if err := self.c.Git().Stash.Push(self.c.Tr.AutoStashForReverting); err != nil { diff --git a/pkg/gui/controllers/undo_controller.go b/pkg/gui/controllers/undo_controller.go index cd3b04e4f..cdc8a1280 100644 --- a/pkg/gui/controllers/undo_controller.go +++ b/pkg/gui/controllers/undo_controller.go @@ -257,7 +257,7 @@ func (self *UndoController) hardResetWithAutoStash(commitHash string, options ha } // if we have any modified tracked files we need to auto-stash - dirtyWorkingTree := self.c.Helpers().WorkingTree.IsWorkingTreeDirty() + dirtyWorkingTree := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() if dirtyWorkingTree { return self.c.WithWaitingStatus(options.WaitingStatus, func(gocui.Task) error { if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForUndo, utils.ShortHash(commitHash))); err != nil { diff --git a/pkg/gui/controllers/workspace_reset_controller.go b/pkg/gui/controllers/workspace_reset_controller.go index de6fc4577..82357922f 100644 --- a/pkg/gui/controllers/workspace_reset_controller.go +++ b/pkg/gui/controllers/workspace_reset_controller.go @@ -100,7 +100,7 @@ func (self *FilesController) createResetMenu() error { Tooltip: self.c.Tr.DiscardStagedChangesDescription, OnPress: func() error { self.c.LogAction(self.c.Tr.Actions.RemoveStagedFiles) - if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() { + if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() { return errors.New(self.c.Tr.NoTrackedStagedFilesStash) } if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil { @@ -159,7 +159,7 @@ func (self *FilesController) createResetMenu() error { red.Sprint("git reset --hard HEAD"), }, OnPress: func() error { - return self.c.ConfirmIf(helpers.IsWorkingTreeDirty(self.c.Model().Files), + return self.c.ConfirmIf(helpers.IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules), types.ConfirmOpts{ Title: self.c.Tr.Actions.HardReset, Prompt: self.c.Tr.ResetHardConfirmation,