mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-10-22 06:52:19 +03:00
Avoid auto-stashing when only submodules are out of date
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.
This commit is contained in:
@@ -173,7 +173,7 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error
|
|||||||
|
|
||||||
self.returnFocusFromPatchExplorerIfNecessary()
|
self.returnFocusFromPatchExplorerIfNecessary()
|
||||||
|
|
||||||
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirty()
|
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules()
|
||||||
return self.c.ConfirmIf(mustStash, types.ConfirmOpts{
|
return self.c.ConfirmIf(mustStash, types.ConfirmOpts{
|
||||||
Title: self.c.Tr.MustStashTitle,
|
Title: self.c.Tr.MustStashTitle,
|
||||||
Prompt: self.c.Tr.MustStashWarning,
|
Prompt: self.c.Tr.MustStashWarning,
|
||||||
|
@@ -973,7 +973,7 @@ func (self *FilesController) createStashMenu() error {
|
|||||||
{
|
{
|
||||||
Label: self.c.Tr.StashAllChanges,
|
Label: self.c.Tr.StashAllChanges,
|
||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
|
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
|
||||||
return errors.New(self.c.Tr.NoFilesToStash)
|
return errors.New(self.c.Tr.NoFilesToStash)
|
||||||
}
|
}
|
||||||
return self.handleStashSave(self.c.Git().Stash.Push, self.c.Tr.Actions.StashAllChanges)
|
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,
|
Label: self.c.Tr.StashAllChangesKeepIndex,
|
||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
|
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
|
||||||
return errors.New(self.c.Tr.NoFilesToStash)
|
return errors.New(self.c.Tr.NoFilesToStash)
|
||||||
}
|
}
|
||||||
// if there are no staged files it behaves the same as Stash.Save
|
// 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,
|
Label: self.c.Tr.StashStagedChanges,
|
||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
// there must be something in staging otherwise the current implementation mucks the stash up
|
// 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 errors.New(self.c.Tr.NoTrackedStagedFilesStash)
|
||||||
}
|
}
|
||||||
return self.handleStashSave(self.c.Git().Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges)
|
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,
|
Label: self.c.Tr.StashUnstagedChanges,
|
||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
|
if !self.c.Helpers().WorkingTree.IsWorkingTreeDirtyExceptSubmodules() {
|
||||||
return errors.New(self.c.Tr.NoFilesToStash)
|
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)
|
return self.handleStashSave(self.c.Git().Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges)
|
||||||
}
|
}
|
||||||
// ordinary stash
|
// ordinary stash
|
||||||
|
@@ -77,7 +77,7 @@ func (self *CherryPickHelper) Paste() error {
|
|||||||
}),
|
}),
|
||||||
HandleConfirm: func() error {
|
HandleConfirm: func() error {
|
||||||
return self.c.WithWaitingStatusSync(self.c.Tr.CherryPickingStatus, 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)
|
self.c.LogAction(self.c.Tr.Actions.CherryPick)
|
||||||
|
|
||||||
|
@@ -258,7 +258,7 @@ func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
|
|||||||
style.FgRed.Sprintf("reset --%s %s", row.strength, name),
|
style.FgRed.Sprintf("reset --%s %s", row.strength, name),
|
||||||
},
|
},
|
||||||
OnPress: func() error {
|
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{
|
types.ConfirmOpts{
|
||||||
Title: self.c.Tr.Actions.HardReset,
|
Title: self.c.Tr.Actions.HardReset,
|
||||||
Prompt: self.c.Tr.ResetHardConfirmation,
|
Prompt: self.c.Tr.ResetHardConfirmation,
|
||||||
@@ -484,7 +484,7 @@ func (self *RefsHelper) moveCommitsToNewBranchStackedOnCurrentBranch(newBranchNa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mustStash := IsWorkingTreeDirty(self.c.Model().Files)
|
mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
|
||||||
if mustStash {
|
if mustStash {
|
||||||
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil {
|
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -517,7 +517,7 @@ func (self *RefsHelper) moveCommitsToNewBranchOffOfMainBranch(newBranchName stri
|
|||||||
return commit.Status == models.StatusUnpushed
|
return commit.Status == models.StatusUnpushed
|
||||||
})
|
})
|
||||||
|
|
||||||
mustStash := IsWorkingTreeDirty(self.c.Model().Files)
|
mustStash := IsWorkingTreeDirtyExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
|
||||||
if mustStash {
|
if mustStash {
|
||||||
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil {
|
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForNewBranch, newBranchName)); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -47,6 +47,14 @@ func AnyStagedFiles(files []*models.File) bool {
|
|||||||
return lo.SomeBy(files, func(f *models.File) bool { return f.HasStagedChanges })
|
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 {
|
func (self *WorkingTreeHelper) AnyTrackedFiles() bool {
|
||||||
return AnyTrackedFiles(self.c.Model().Files)
|
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 })
|
return lo.SomeBy(files, func(f *models.File) bool { return f.Tracked })
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeHelper) IsWorkingTreeDirty() bool {
|
func (self *WorkingTreeHelper) AnyTrackedFilesExceptSubmodules() bool {
|
||||||
return IsWorkingTreeDirty(self.c.Model().Files)
|
return AnyTrackedFilesExceptSubmodules(self.c.Model().Files, self.c.Model().Submodules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsWorkingTreeDirty(files []*models.File) bool {
|
func AnyTrackedFilesExceptSubmodules(files []*models.File, submoduleConfigs []*models.SubmoduleConfig) bool {
|
||||||
return AnyStagedFiles(files) || AnyTrackedFiles(files)
|
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 {
|
func (self *WorkingTreeHelper) FileForSubmodule(submodule *models.SubmoduleConfig) *models.File {
|
||||||
|
@@ -856,7 +856,7 @@ func (self *LocalCommitsController) revert(commits []*models.Commit, start, end
|
|||||||
HandleConfirm: func() error {
|
HandleConfirm: func() error {
|
||||||
self.c.LogAction(self.c.Tr.Actions.RevertCommit)
|
self.c.LogAction(self.c.Tr.Actions.RevertCommit)
|
||||||
return self.c.WithWaitingStatusSync(self.c.Tr.RevertingStatus, func() error {
|
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 mustStash {
|
||||||
if err := self.c.Git().Stash.Push(self.c.Tr.AutoStashForReverting); err != nil {
|
if err := self.c.Git().Stash.Push(self.c.Tr.AutoStashForReverting); err != nil {
|
||||||
|
@@ -257,7 +257,7 @@ func (self *UndoController) hardResetWithAutoStash(commitHash string, options ha
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if we have any modified tracked files we need to auto-stash
|
// 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 {
|
if dirtyWorkingTree {
|
||||||
return self.c.WithWaitingStatus(options.WaitingStatus, func(gocui.Task) error {
|
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 {
|
if err := self.c.Git().Stash.Push(fmt.Sprintf(self.c.Tr.AutoStashForUndo, utils.ShortHash(commitHash))); err != nil {
|
||||||
|
@@ -100,7 +100,7 @@ func (self *FilesController) createResetMenu() error {
|
|||||||
Tooltip: self.c.Tr.DiscardStagedChangesDescription,
|
Tooltip: self.c.Tr.DiscardStagedChangesDescription,
|
||||||
OnPress: func() error {
|
OnPress: func() error {
|
||||||
self.c.LogAction(self.c.Tr.Actions.RemoveStagedFiles)
|
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)
|
return errors.New(self.c.Tr.NoTrackedStagedFilesStash)
|
||||||
}
|
}
|
||||||
if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil {
|
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"),
|
red.Sprint("git reset --hard HEAD"),
|
||||||
},
|
},
|
||||||
OnPress: func() error {
|
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{
|
types.ConfirmOpts{
|
||||||
Title: self.c.Tr.Actions.HardReset,
|
Title: self.c.Tr.Actions.HardReset,
|
||||||
Prompt: self.c.Tr.ResetHardConfirmation,
|
Prompt: self.c.Tr.ResetHardConfirmation,
|
||||||
|
Reference in New Issue
Block a user