Skip to content

Commit 0a1ddba

Browse files
authored
Add confirmation for hard reset (#4704)
- **PR Description** Doing a hard reset is really destructive because it loses all uncommitted changes, so add a confirmation in case there are any. Fixes #3085 Fixes #3709 Fixes #4688
2 parents 1ca5f09 + 7153305 commit 0a1ddba

17 files changed

+191
-244
lines changed

pkg/gui/controllers/branches_controller.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -724,17 +724,11 @@ func (self *BranchesController) rename(branch *models.Branch) error {
724724
// I could do an explicit check here for whether the branch is tracking a remote branch
725725
// but if we've selected it we'll already know that via Pullables and Pullables.
726726
// Bit of a hack but I'm lazy.
727-
if !branch.IsTrackingRemote() {
728-
return promptForNewName()
729-
}
730-
731-
self.c.Confirm(types.ConfirmOpts{
727+
return self.c.ConfirmIf(branch.IsTrackingRemote(), types.ConfirmOpts{
732728
Title: self.c.Tr.RenameBranch,
733729
Prompt: self.c.Tr.RenameBranchWarning,
734730
HandleConfirm: promptForNewName,
735731
})
736-
737-
return nil
738732
}
739733

740734
func (self *BranchesController) newBranch(selectedBranch *models.Branch) error {

pkg/gui/controllers/commits_files_controller.go

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -426,20 +426,18 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
426426
}
427427

428428
from, to, reverse := self.currentFromToReverseForPatchBuilding()
429-
if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse) {
430-
self.c.Confirm(types.ConfirmOpts{
431-
Title: self.c.Tr.DiscardPatch,
432-
Prompt: self.c.Tr.DiscardPatchConfirm,
433-
HandleConfirm: func() error {
429+
mustDiscardPatch := self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse)
430+
return self.c.ConfirmIf(mustDiscardPatch, types.ConfirmOpts{
431+
Title: self.c.Tr.DiscardPatch,
432+
Prompt: self.c.Tr.DiscardPatchConfirm,
433+
HandleConfirm: func() error {
434+
if mustDiscardPatch {
434435
self.c.Git().Patch.PatchBuilder.Reset()
435-
return toggle()
436-
},
437-
})
438-
439-
return nil
440-
}
436+
}
441437

442-
return toggle()
438+
return toggle()
439+
},
440+
})
443441
}
444442

445443
func (self *CommitFilesController) toggleAllForPatch(_ *filetree.CommitFileNode) error {
@@ -479,32 +477,26 @@ func (self *CommitFilesController) enterCommitFile(node *filetree.CommitFileNode
479477
keybindings.Label(self.c.UserConfig().Keybinding.Universal.IncreaseContextInDiffView))
480478
}
481479

482-
enterTheFile := func() error {
483-
if !self.c.Git().Patch.PatchBuilder.Active() {
484-
if err := self.startPatchBuilder(); err != nil {
485-
return err
486-
}
487-
}
488-
489-
self.c.Context().Push(self.c.Contexts().CustomPatchBuilder, opts)
490-
return nil
491-
}
492-
493480
from, to, reverse := self.currentFromToReverseForPatchBuilding()
494-
if self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse) {
495-
self.c.Confirm(types.ConfirmOpts{
496-
Title: self.c.Tr.DiscardPatch,
497-
Prompt: self.c.Tr.DiscardPatchConfirm,
498-
HandleConfirm: func() error {
481+
mustDiscardPatch := self.c.Git().Patch.PatchBuilder.Active() && self.c.Git().Patch.PatchBuilder.NewPatchRequired(from, to, reverse)
482+
return self.c.ConfirmIf(mustDiscardPatch, types.ConfirmOpts{
483+
Title: self.c.Tr.DiscardPatch,
484+
Prompt: self.c.Tr.DiscardPatchConfirm,
485+
HandleConfirm: func() error {
486+
if mustDiscardPatch {
499487
self.c.Git().Patch.PatchBuilder.Reset()
500-
return enterTheFile()
501-
},
502-
})
488+
}
503489

504-
return nil
505-
}
490+
if !self.c.Git().Patch.PatchBuilder.Active() {
491+
if err := self.startPatchBuilder(); err != nil {
492+
return err
493+
}
494+
}
506495

507-
return enterTheFile()
496+
self.c.Context().Push(self.c.Contexts().CustomPatchBuilder, opts)
497+
return nil
498+
},
499+
})
508500
}
509501

510502
func (self *CommitFilesController) handleToggleCommitFileDirCollapsed(node *filetree.CommitFileNode) error {

pkg/gui/controllers/custom_patch_options_menu_action.go

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -173,28 +173,19 @@ func (self *CustomPatchOptionsMenuAction) handleMovePatchIntoWorkingTree() error
173173

174174
self.returnFocusFromPatchExplorerIfNecessary()
175175

176-
pull := func(stash bool) error {
177-
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
178-
commitIndex := self.getPatchCommitIndex()
179-
self.c.LogAction(self.c.Tr.Actions.MovePatchIntoIndex)
180-
err := self.c.Git().Patch.MovePatchIntoIndex(self.c.Model().Commits, commitIndex, stash)
181-
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
182-
})
183-
}
184-
185-
if self.c.Helpers().WorkingTree.IsWorkingTreeDirty() {
186-
self.c.Confirm(types.ConfirmOpts{
187-
Title: self.c.Tr.MustStashTitle,
188-
Prompt: self.c.Tr.MustStashWarning,
189-
HandleConfirm: func() error {
190-
return pull(true)
191-
},
192-
})
193-
194-
return nil
195-
}
196-
197-
return pull(false)
176+
mustStash := self.c.Helpers().WorkingTree.IsWorkingTreeDirty()
177+
return self.c.ConfirmIf(mustStash, types.ConfirmOpts{
178+
Title: self.c.Tr.MustStashTitle,
179+
Prompt: self.c.Tr.MustStashWarning,
180+
HandleConfirm: func() error {
181+
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
182+
commitIndex := self.getPatchCommitIndex()
183+
self.c.LogAction(self.c.Tr.Actions.MovePatchIntoIndex)
184+
err := self.c.Git().Patch.MovePatchIntoIndex(self.c.Model().Commits, commitIndex, mustStash)
185+
return self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err)
186+
})
187+
},
188+
})
198189
}
199190

200191
func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error {
@@ -272,40 +263,31 @@ func (self *CustomPatchOptionsMenuAction) handleApplyPatch(reverse bool) error {
272263

273264
affectedUnstagedFiles := self.getAffectedUnstagedFiles()
274265

275-
apply := func() error {
276-
action := self.c.Tr.Actions.ApplyPatch
277-
if reverse {
278-
action = "Apply patch in reverse"
279-
}
280-
self.c.LogAction(action)
281-
282-
if len(affectedUnstagedFiles) > 0 {
283-
if err := self.c.Git().WorkingTree.StageFiles(affectedUnstagedFiles, nil); err != nil {
284-
return err
266+
mustStageFiles := len(affectedUnstagedFiles) > 0
267+
return self.c.ConfirmIf(mustStageFiles, types.ConfirmOpts{
268+
Title: self.c.Tr.MustStageFilesAffectedByPatchTitle,
269+
Prompt: self.c.Tr.MustStageFilesAffectedByPatchWarning,
270+
HandleConfirm: func() error {
271+
action := self.c.Tr.Actions.ApplyPatch
272+
if reverse {
273+
action = "Apply patch in reverse"
285274
}
286-
}
275+
self.c.LogAction(action)
287276

288-
if err := self.c.Git().Patch.ApplyCustomPatch(reverse, true); err != nil {
289-
return err
290-
}
291-
292-
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
293-
return nil
294-
}
295-
296-
if len(affectedUnstagedFiles) > 0 {
297-
self.c.Confirm(types.ConfirmOpts{
298-
Title: self.c.Tr.MustStageFilesAffectedByPatchTitle,
299-
Prompt: self.c.Tr.MustStageFilesAffectedByPatchWarning,
300-
HandleConfirm: func() error {
301-
return apply()
302-
},
303-
})
277+
if mustStageFiles {
278+
if err := self.c.Git().WorkingTree.StageFiles(affectedUnstagedFiles, nil); err != nil {
279+
return err
280+
}
281+
}
304282

305-
return nil
306-
}
283+
if err := self.c.Git().Patch.ApplyCustomPatch(reverse, true); err != nil {
284+
return err
285+
}
307286

308-
return apply()
287+
self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC})
288+
return nil
289+
},
290+
})
309291
}
310292

311293
func (self *CustomPatchOptionsMenuAction) copyPatchToClipboard() error {

pkg/gui/controllers/files_controller.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -794,19 +794,17 @@ func (self *FilesController) handleAmendCommitPress() error {
794794
},
795795
},
796796
})
797-
} else if !self.c.UserConfig().Gui.SkipAmendWarning {
798-
self.c.Confirm(types.ConfirmOpts{
797+
}
798+
799+
return self.c.ConfirmIf(!self.c.UserConfig().Gui.SkipAmendWarning,
800+
types.ConfirmOpts{
799801
Title: self.c.Tr.AmendLastCommitTitle,
800802
Prompt: self.c.Tr.SureToAmend,
801803
HandleConfirm: func() error {
802804
return doAmend()
803805
},
804-
})
805-
806-
return nil
807-
}
808-
809-
return doAmend()
806+
},
807+
)
810808
}
811809

812810
func (self *FilesController) isResolvingConflicts() bool {

pkg/gui/controllers/helpers/commits_helper.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -256,20 +256,13 @@ func (self *CommitsHelper) pasteCommitMessageFromClipboard() error {
256256
return nil
257257
}
258258

259-
if currentMessage := self.JoinCommitMessageAndUnwrappedDescription(); currentMessage == "" {
260-
self.SetMessageAndDescriptionInView(message)
261-
return nil
262-
}
263-
264-
// Confirm before overwriting the commit message
265-
self.c.Confirm(types.ConfirmOpts{
259+
currentMessage := self.JoinCommitMessageAndUnwrappedDescription()
260+
return self.c.ConfirmIf(currentMessage != "", types.ConfirmOpts{
266261
Title: self.c.Tr.PasteCommitMessageFromClipboard,
267262
Prompt: self.c.Tr.SurePasteCommitMessage,
268263
HandleConfirm: func() error {
269264
self.SetMessageAndDescriptionInView(message)
270265
return nil
271266
},
272267
})
273-
274-
return nil
275268
}

pkg/gui/controllers/helpers/fixup_helper.go

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,32 +128,22 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
128128
// and that's the one we want to select.
129129
_, index, _ := self.findCommit(commits, hashGroups[NOT_MERGED][0])
130130

131-
doIt := func() error {
132-
if !hasStagedChanges {
133-
if err := self.c.Git().WorkingTree.StageAll(); err != nil {
134-
return err
131+
return self.c.ConfirmIf(warnAboutAddedLines, types.ConfirmOpts{
132+
Title: self.c.Tr.FindBaseCommitForFixup,
133+
Prompt: self.c.Tr.HunksWithOnlyAddedLinesWarning,
134+
HandleConfirm: func() error {
135+
if !hasStagedChanges {
136+
if err := self.c.Git().WorkingTree.StageAll(); err != nil {
137+
return err
138+
}
139+
self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
135140
}
136-
self.c.Refresh(types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.FILES}})
137-
}
138-
139-
self.c.Contexts().LocalCommits.SetSelection(index)
140-
self.c.Context().Push(self.c.Contexts().LocalCommits, types.OnFocusOpts{})
141-
return nil
142-
}
143141

144-
if warnAboutAddedLines {
145-
self.c.Confirm(types.ConfirmOpts{
146-
Title: self.c.Tr.FindBaseCommitForFixup,
147-
Prompt: self.c.Tr.HunksWithOnlyAddedLinesWarning,
148-
HandleConfirm: func() error {
149-
return doIt()
150-
},
151-
})
152-
153-
return nil
154-
}
155-
156-
return doIt()
142+
self.c.Contexts().LocalCommits.SetSelection(index)
143+
self.c.Context().Push(self.c.Contexts().LocalCommits, types.OnFocusOpts{})
144+
return nil
145+
},
146+
})
157147
}
158148

159149
func (self *FixupHelper) getDiff() (string, bool, error) {

pkg/gui/controllers/helpers/refs_helper.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,15 @@ func (self *RefsHelper) CreateGitResetMenu(name string, ref string) error {
248248
style.FgRed.Sprintf("reset --%s %s", row.strength, name),
249249
},
250250
OnPress: func() error {
251-
self.c.LogAction("Reset")
252-
return self.ResetToRef(ref, row.strength, []string{})
251+
return self.c.ConfirmIf(row.strength == "hard" && IsWorkingTreeDirty(self.c.Model().Files),
252+
types.ConfirmOpts{
253+
Title: self.c.Tr.Actions.HardReset,
254+
Prompt: self.c.Tr.ResetHardConfirmation,
255+
HandleConfirm: func() error {
256+
self.c.LogAction("Reset")
257+
return self.ResetToRef(ref, row.strength, []string{})
258+
},
259+
})
253260
},
254261
Key: row.key,
255262
Tooltip: row.tooltip,

pkg/gui/controllers/helpers/tags_helper.go

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,43 +23,34 @@ func NewTagsHelper(c *HelperCommon, commitsHelper *CommitsHelper, gpg *GpgHelper
2323
}
2424

2525
func (self *TagsHelper) OpenCreateTagPrompt(ref string, onCreate func()) error {
26-
doCreateTag := func(tagName string, description string, force bool) error {
27-
var command *oscommands.CmdObj
28-
if description != "" || self.c.Git().Config.GetGpgTagSign() {
29-
self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag)
30-
command = self.c.Git().Tag.CreateAnnotatedObj(tagName, ref, description, force)
31-
} else {
32-
self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag)
33-
command = self.c.Git().Tag.CreateLightweightObj(tagName, ref, force)
34-
}
35-
36-
return self.gpg.WithGpgHandling(command, git_commands.TagGpgSign, self.c.Tr.CreatingTag, func() error {
37-
return nil
38-
}, []types.RefreshableView{types.COMMITS, types.TAGS})
39-
}
40-
4126
onConfirm := func(tagName string, description string) error {
42-
if self.c.Git().Tag.HasTag(tagName) {
43-
prompt := utils.ResolvePlaceholderString(
44-
self.c.Tr.ForceTagPrompt,
45-
map[string]string{
46-
"tagName": tagName,
47-
"cancelKey": self.c.UserConfig().Keybinding.Universal.Return,
48-
"confirmKey": self.c.UserConfig().Keybinding.Universal.Confirm,
49-
},
50-
)
51-
self.c.Confirm(types.ConfirmOpts{
52-
Title: self.c.Tr.ForceTag,
53-
Prompt: prompt,
54-
HandleConfirm: func() error {
55-
return doCreateTag(tagName, description, true)
56-
},
57-
})
58-
59-
return nil
60-
}
27+
prompt := utils.ResolvePlaceholderString(
28+
self.c.Tr.ForceTagPrompt,
29+
map[string]string{
30+
"tagName": tagName,
31+
"cancelKey": self.c.UserConfig().Keybinding.Universal.Return,
32+
"confirmKey": self.c.UserConfig().Keybinding.Universal.Confirm,
33+
},
34+
)
35+
force := self.c.Git().Tag.HasTag(tagName)
36+
return self.c.ConfirmIf(force, types.ConfirmOpts{
37+
Title: self.c.Tr.ForceTag,
38+
Prompt: prompt,
39+
HandleConfirm: func() error {
40+
var command *oscommands.CmdObj
41+
if description != "" || self.c.Git().Config.GetGpgTagSign() {
42+
self.c.LogAction(self.c.Tr.Actions.CreateAnnotatedTag)
43+
command = self.c.Git().Tag.CreateAnnotatedObj(tagName, ref, description, force)
44+
} else {
45+
self.c.LogAction(self.c.Tr.Actions.CreateLightweightTag)
46+
command = self.c.Git().Tag.CreateLightweightObj(tagName, ref, force)
47+
}
6148

62-
return doCreateTag(tagName, description, false)
49+
return self.gpg.WithGpgHandling(command, git_commands.TagGpgSign, self.c.Tr.CreatingTag, func() error {
50+
return nil
51+
}, []types.RefreshableView{types.COMMITS, types.TAGS})
52+
},
53+
})
6354
}
6455

6556
self.commitsHelper.OpenCommitMessagePanel(

0 commit comments

Comments
 (0)