1package gui 2 3import ( 4 "fmt" 5 6 "github.com/jesseduffield/lazygit/pkg/commands" 7) 8 9func (gui *Gui) handleCreatePatchOptionsMenu() error { 10 if !gui.GitCommand.PatchManager.Active() { 11 return gui.createErrorPanel(gui.Tr.NoPatchError) 12 } 13 14 menuItems := []*menuItem{ 15 { 16 displayString: "reset patch", 17 onPress: gui.handleResetPatch, 18 }, 19 { 20 displayString: "apply patch", 21 onPress: func() error { return gui.handleApplyPatch(false) }, 22 }, 23 { 24 displayString: "apply patch in reverse", 25 onPress: func() error { return gui.handleApplyPatch(true) }, 26 }, 27 } 28 29 if gui.GitCommand.PatchManager.CanRebase && gui.workingTreeState() == commands.REBASE_MODE_NORMAL { 30 menuItems = append(menuItems, []*menuItem{ 31 { 32 displayString: fmt.Sprintf("remove patch from original commit (%s)", gui.GitCommand.PatchManager.To), 33 onPress: gui.handleDeletePatchFromCommit, 34 }, 35 { 36 displayString: "move patch out into index", 37 onPress: gui.handleMovePatchIntoWorkingTree, 38 }, 39 { 40 displayString: "move patch into new commit", 41 onPress: gui.handlePullPatchIntoNewCommit, 42 }, 43 }...) 44 45 if gui.currentContext().GetKey() == gui.State.Contexts.BranchCommits.GetKey() { 46 selectedCommit := gui.getSelectedLocalCommit() 47 if selectedCommit != nil && gui.GitCommand.PatchManager.To != selectedCommit.Sha { 48 // adding this option to index 1 49 menuItems = append( 50 menuItems[:1], 51 append( 52 []*menuItem{ 53 { 54 displayString: fmt.Sprintf("move patch to selected commit (%s)", selectedCommit.Sha), 55 onPress: gui.handleMovePatchToSelectedCommit, 56 }, 57 }, menuItems[1:]..., 58 )..., 59 ) 60 } 61 } 62 } 63 64 return gui.createMenu(gui.Tr.PatchOptionsTitle, menuItems, createMenuOptions{showCancel: true}) 65} 66 67func (gui *Gui) getPatchCommitIndex() int { 68 for index, commit := range gui.State.Commits { 69 if commit.Sha == gui.GitCommand.PatchManager.To { 70 return index 71 } 72 } 73 return -1 74} 75 76func (gui *Gui) validateNormalWorkingTreeState() (bool, error) { 77 if gui.GitCommand.WorkingTreeState() != commands.REBASE_MODE_NORMAL { 78 return false, gui.createErrorPanel(gui.Tr.CantPatchWhileRebasingError) 79 } 80 return true, nil 81} 82 83func (gui *Gui) returnFocusFromLineByLinePanelIfNecessary() error { 84 if gui.State.MainContext == MAIN_PATCH_BUILDING_CONTEXT_KEY { 85 return gui.handleEscapePatchBuildingPanel() 86 } 87 return nil 88} 89 90func (gui *Gui) handleDeletePatchFromCommit() error { 91 if ok, err := gui.validateNormalWorkingTreeState(); !ok { 92 return err 93 } 94 95 if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil { 96 return err 97 } 98 99 return gui.WithWaitingStatus(gui.Tr.RebasingStatus, func() error { 100 commitIndex := gui.getPatchCommitIndex() 101 err := gui.GitCommand.WithSpan(gui.Tr.Spans.RemovePatchFromCommit).DeletePatchesFromCommit(gui.State.Commits, commitIndex, gui.GitCommand.PatchManager) 102 return gui.handleGenericMergeCommandResult(err) 103 }) 104} 105 106func (gui *Gui) handleMovePatchToSelectedCommit() error { 107 if ok, err := gui.validateNormalWorkingTreeState(); !ok { 108 return err 109 } 110 111 if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil { 112 return err 113 } 114 115 return gui.WithWaitingStatus(gui.Tr.RebasingStatus, func() error { 116 commitIndex := gui.getPatchCommitIndex() 117 err := gui.GitCommand.WithSpan(gui.Tr.Spans.MovePatchToSelectedCommit).MovePatchToSelectedCommit(gui.State.Commits, commitIndex, gui.State.Panels.Commits.SelectedLineIdx, gui.GitCommand.PatchManager) 118 return gui.handleGenericMergeCommandResult(err) 119 }) 120} 121 122func (gui *Gui) handleMovePatchIntoWorkingTree() error { 123 if ok, err := gui.validateNormalWorkingTreeState(); !ok { 124 return err 125 } 126 127 if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil { 128 return err 129 } 130 131 pull := func(stash bool) error { 132 return gui.WithWaitingStatus(gui.Tr.RebasingStatus, func() error { 133 commitIndex := gui.getPatchCommitIndex() 134 err := gui.GitCommand.WithSpan(gui.Tr.Spans.MovePatchIntoIndex).MovePatchIntoIndex(gui.State.Commits, commitIndex, gui.GitCommand.PatchManager, stash) 135 return gui.handleGenericMergeCommandResult(err) 136 }) 137 } 138 139 if len(gui.trackedFiles()) > 0 { 140 return gui.ask(askOpts{ 141 title: gui.Tr.MustStashTitle, 142 prompt: gui.Tr.MustStashWarning, 143 handleConfirm: func() error { 144 return pull(true) 145 }, 146 }) 147 } else { 148 return pull(false) 149 } 150} 151 152func (gui *Gui) handlePullPatchIntoNewCommit() error { 153 if ok, err := gui.validateNormalWorkingTreeState(); !ok { 154 return err 155 } 156 157 if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil { 158 return err 159 } 160 161 return gui.WithWaitingStatus(gui.Tr.RebasingStatus, func() error { 162 commitIndex := gui.getPatchCommitIndex() 163 err := gui.GitCommand.WithSpan(gui.Tr.Spans.MovePatchIntoNewCommit).PullPatchIntoNewCommit(gui.State.Commits, commitIndex, gui.GitCommand.PatchManager) 164 return gui.handleGenericMergeCommandResult(err) 165 }) 166} 167 168func (gui *Gui) handleApplyPatch(reverse bool) error { 169 if err := gui.returnFocusFromLineByLinePanelIfNecessary(); err != nil { 170 return err 171 } 172 173 span := gui.Tr.Spans.ApplyPatch 174 if reverse { 175 span = "Apply patch in reverse" 176 } 177 if err := gui.GitCommand.WithSpan(span).PatchManager.ApplyPatches(reverse); err != nil { 178 return gui.surfaceError(err) 179 } 180 return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) 181} 182 183func (gui *Gui) handleResetPatch() error { 184 gui.GitCommand.PatchManager.Reset() 185 if gui.currentContextKeyIgnoringPopups() == MAIN_PATCH_BUILDING_CONTEXT_KEY { 186 if err := gui.pushContext(gui.State.Contexts.CommitFiles); err != nil { 187 return err 188 } 189 } 190 return gui.refreshCommitFilesView() 191} 192