diff --git a/pkg/gui/controllers/workspace_reset_controller.go b/pkg/gui/controllers/workspace_reset_controller.go index 82357922f4a..c66f08b262b 100644 --- a/pkg/gui/controllers/workspace_reset_controller.go +++ b/pkg/gui/controllers/workspace_reset_controller.go @@ -62,14 +62,21 @@ func (self *FilesController) createResetMenu() error { red.Sprint("git checkout -- ."), }, OnPress: func() error { - self.c.LogAction(self.c.Tr.Actions.DiscardUnstagedFileChanges) - if err := self.c.Git().WorkingTree.DiscardAnyUnstagedFileChanges(); err != nil { - return err - } + self.c.Confirm(types.ConfirmOpts{ + Title: self.c.Tr.DiscardAnyUnstagedChanges, + Prompt: self.c.Tr.DiscardAnyUnstagedChangesConfirmation, + HandleConfirm: func() error { + self.c.LogAction(self.c.Tr.Actions.DiscardUnstagedFileChanges) + if err := self.c.Git().WorkingTree.DiscardAnyUnstagedFileChanges(); err != nil { + return err + } - self.c.Refresh( - types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}}, - ) + self.c.Refresh( + types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}}, + ) + return nil + }, + }) return nil }, Key: 'u', @@ -80,14 +87,21 @@ func (self *FilesController) createResetMenu() error { red.Sprint("git clean -fd"), }, OnPress: func() error { - self.c.LogAction(self.c.Tr.Actions.RemoveUntrackedFiles) - if err := self.c.Git().WorkingTree.RemoveUntrackedFiles(); err != nil { - return err - } + self.c.Confirm(types.ConfirmOpts{ + Title: self.c.Tr.DiscardUntrackedFiles, + Prompt: self.c.Tr.DiscardUntrackedFilesConfirmation, + HandleConfirm: func() error { + self.c.LogAction(self.c.Tr.Actions.RemoveUntrackedFiles) + if err := self.c.Git().WorkingTree.RemoveUntrackedFiles(); err != nil { + return err + } - self.c.Refresh( - types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}}, - ) + self.c.Refresh( + types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}}, + ) + return nil + }, + }) return nil }, Key: 'c', @@ -99,20 +113,27 @@ 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.IsWorkingTreeDirtyExceptSubmodules() { return errors.New(self.c.Tr.NoTrackedStagedFilesStash) } - if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil { - return err - } - if err := self.c.Git().Stash.DropNewest(); err != nil { - return err - } + self.c.Confirm(types.ConfirmOpts{ + Title: self.c.Tr.DiscardStagedChanges, + Prompt: self.c.Tr.DiscardStagedChangesConfirmation, + HandleConfirm: func() error { + self.c.LogAction(self.c.Tr.Actions.RemoveStagedFiles) + if err := self.c.Git().Stash.SaveStagedChanges("[lazygit] tmp stash"); err != nil { + return err + } + if err := self.c.Git().Stash.DropNewest(); err != nil { + return err + } - self.c.Refresh( - types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}}, - ) + self.c.Refresh( + types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}}, + ) + return nil + }, + }) return nil }, Key: 'S', diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 002adb11410..229eed5847f 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -825,6 +825,9 @@ type TranslationSet struct { NukeDescription string NukeTreeConfirmation string DiscardStagedChangesDescription string + DiscardAnyUnstagedChangesConfirmation string + DiscardUntrackedFilesConfirmation string + DiscardStagedChangesConfirmation string EmptyOutput string Patch string CustomPatch string @@ -1947,6 +1950,9 @@ func EnglishTranslationSet() *TranslationSet { NukeDescription: "If you want to make all the changes in the worktree go away, this is the way to do it. If there are dirty submodule changes this will stash those changes in the submodule(s).", NukeTreeConfirmation: "Are you sure you want to nuke the working tree? This will discard all changes in the worktree (staged, unstaged and untracked), which is not undoable.", DiscardStagedChangesDescription: "This will create a new stash entry containing only staged files and then drop it, so that the working tree is left with only unstaged changes", + DiscardAnyUnstagedChangesConfirmation: "Are you sure you want to discard all unstaged changes? This is not undoable.", + DiscardUntrackedFilesConfirmation: "Are you sure you want to discard all untracked files? This is not undoable.", + DiscardStagedChangesConfirmation: "Are you sure you want to discard all staged changes? This is not undoable.", EmptyOutput: "", Patch: "Patch", CustomPatch: "Custom patch", diff --git a/pkg/integration/tests/file/discard_staged_changes.go b/pkg/integration/tests/file/discard_staged_changes.go index 06322567fb6..44601c624e9 100644 --- a/pkg/integration/tests/file/discard_staged_changes.go +++ b/pkg/integration/tests/file/discard_staged_changes.go @@ -41,6 +41,11 @@ var DiscardStagedChanges = NewIntegrationTest(NewIntegrationTestArgs{ t.ExpectPopup().Menu().Title(Equals("")).Select(Contains("Discard staged changes")).Confirm() + t.ExpectPopup().Confirmation(). + Title(Equals("Discard staged changes")). + Content(Equals("Are you sure you want to discard all staged changes? This is not undoable.")). + Confirm() + // staged file has been removed t.Views().Files(). Lines(