mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-17 01:42:45 +02:00
Allow pasting commits multiple times (#3983)
- **PR Description** After pasting commits, hide the cherry-pick status (i.e. remove the "x commits copied" status in the lower right corner, and hide the blue selection of the copied commits). However, keep the copied commits around so that it's possible to paste them again. This can be useful e.g. to backport a bugfix to multiple major version release branches. Discussed in #3198. - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [x] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see [here](https://github.com/jesseduffield/lazygit/blob/master/docs/dev/Codebase_Guide.md#using-userconfig)) * [ ] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc
This commit is contained in:
@ -303,7 +303,8 @@ func (self *CommitFilesController) toggleForPatch(selectedNodes []*filetree.Comm
|
|||||||
self.c.Git().Patch.PatchBuilder.Reset()
|
self.c.Git().Patch.PatchBuilder.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.c.PostRefreshUpdate(self.context())
|
self.c.PostRefreshUpdate(self.context())
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,9 +388,7 @@ func (self *CommitFilesController) enterCommitFile(node *filetree.CommitFileNode
|
|||||||
func (self *CommitFilesController) handleToggleCommitFileDirCollapsed(node *filetree.CommitFileNode) error {
|
func (self *CommitFilesController) handleToggleCommitFileDirCollapsed(node *filetree.CommitFileNode) error {
|
||||||
self.context().CommitFileTreeViewModel.ToggleCollapsed(node.GetPath())
|
self.context().CommitFileTreeViewModel.ToggleCollapsed(node.GetPath())
|
||||||
|
|
||||||
if err := self.c.PostRefreshUpdate(self.context()); err != nil {
|
self.c.PostRefreshUpdate(self.context())
|
||||||
self.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -398,7 +397,8 @@ func (self *CommitFilesController) handleToggleCommitFileDirCollapsed(node *file
|
|||||||
func (self *CommitFilesController) toggleTreeView() error {
|
func (self *CommitFilesController) toggleTreeView() error {
|
||||||
self.context().CommitFileTreeViewModel.ToggleShowTree()
|
self.context().CommitFileTreeViewModel.ToggleShowTree()
|
||||||
|
|
||||||
return self.c.PostRefreshUpdate(self.context())
|
self.c.PostRefreshUpdate(self.context())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: these functions are identical to those in files_controller.go (except for types) and
|
// NOTE: these functions are identical to those in files_controller.go (except for types) and
|
||||||
|
@ -373,9 +373,7 @@ func (self *FilesController) optimisticChange(nodes []*filetree.FileNode, optimi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rerender {
|
if rerender {
|
||||||
if err := self.c.PostRefreshUpdate(self.c.Contexts().Files); err != nil {
|
self.c.PostRefreshUpdate(self.c.Contexts().Files)
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -710,7 +708,8 @@ func (self *FilesController) handleStatusFilterPressed() error {
|
|||||||
|
|
||||||
func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error {
|
func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error {
|
||||||
self.context().FileTreeViewModel.SetStatusFilter(filter)
|
self.context().FileTreeViewModel.SetStatusFilter(filter)
|
||||||
return self.c.PostRefreshUpdate(self.context())
|
self.c.PostRefreshUpdate(self.context())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesController) edit(nodes []*filetree.FileNode) error {
|
func (self *FilesController) edit(nodes []*filetree.FileNode) error {
|
||||||
@ -949,9 +948,7 @@ func (self *FilesController) handleToggleDirCollapsed() error {
|
|||||||
|
|
||||||
self.context().FileTreeViewModel.ToggleCollapsed(node.GetPath())
|
self.context().FileTreeViewModel.ToggleCollapsed(node.GetPath())
|
||||||
|
|
||||||
if err := self.c.PostRefreshUpdate(self.c.Contexts().Files); err != nil {
|
self.c.PostRefreshUpdate(self.c.Contexts().Files)
|
||||||
self.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -959,7 +956,8 @@ func (self *FilesController) handleToggleDirCollapsed() error {
|
|||||||
func (self *FilesController) toggleTreeView() error {
|
func (self *FilesController) toggleTreeView() error {
|
||||||
self.context().FileTreeViewModel.ToggleShowTree()
|
self.context().FileTreeViewModel.ToggleShowTree()
|
||||||
|
|
||||||
return self.c.PostRefreshUpdate(self.context())
|
self.c.PostRefreshUpdate(self.context())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *FilesController) handleStashSave(stashFunc func(message string) error, action string) error {
|
func (self *FilesController) handleStashSave(stashFunc func(message string) error, action string) error {
|
||||||
|
@ -57,7 +57,10 @@ func (self *CherryPickHelper) CopyRange(commitsList []*models.Commit, context ty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.rerender()
|
self.getData().DidPaste = false
|
||||||
|
|
||||||
|
self.rerender()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandlePasteCommits begins a cherry-pick rebase with the commits the user has copied.
|
// HandlePasteCommits begins a cherry-pick rebase with the commits the user has copied.
|
||||||
@ -102,7 +105,8 @@ func (self *CherryPickHelper) Paste() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !isInRebase {
|
if !isInRebase {
|
||||||
return self.Reset()
|
self.getData().DidPaste = true
|
||||||
|
self.rerender()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -113,14 +117,15 @@ func (self *CherryPickHelper) Paste() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CherryPickHelper) CanPaste() bool {
|
func (self *CherryPickHelper) CanPaste() bool {
|
||||||
return self.getData().Active()
|
return self.getData().CanPaste()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CherryPickHelper) Reset() error {
|
func (self *CherryPickHelper) Reset() error {
|
||||||
self.getData().ContextKey = ""
|
self.getData().ContextKey = ""
|
||||||
self.getData().CherryPickedCommits = nil
|
self.getData().CherryPickedCommits = nil
|
||||||
|
|
||||||
return self.rerender()
|
self.rerender()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// you can only copy from one context at a time, because the order and position of commits matter
|
// you can only copy from one context at a time, because the order and position of commits matter
|
||||||
@ -136,16 +141,12 @@ func (self *CherryPickHelper) resetIfNecessary(context types.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CherryPickHelper) rerender() error {
|
func (self *CherryPickHelper) rerender() {
|
||||||
for _, context := range []types.Context{
|
for _, context := range []types.Context{
|
||||||
self.c.Contexts().LocalCommits,
|
self.c.Contexts().LocalCommits,
|
||||||
self.c.Contexts().ReflogCommits,
|
self.c.Contexts().ReflogCommits,
|
||||||
self.c.Contexts().SubCommits,
|
self.c.Contexts().SubCommits,
|
||||||
} {
|
} {
|
||||||
if err := self.c.PostRefreshUpdate(context); err != nil {
|
self.c.PostRefreshUpdate(context)
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -487,5 +487,6 @@ func (self *MergeAndRebaseHelper) SquashMergeCommitted(refName, checkedOutBranch
|
|||||||
|
|
||||||
func (self *MergeAndRebaseHelper) ResetMarkedBaseCommit() error {
|
func (self *MergeAndRebaseHelper) ResetMarkedBaseCommit() error {
|
||||||
self.c.Modes().MarkedBaseCommit.Reset()
|
self.c.Modes().MarkedBaseCommit.Reset()
|
||||||
return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,8 @@ func (self *PatchBuildingHelper) Reset() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// refreshing the current context so that the secondary panel is hidden if necessary.
|
// refreshing the current context so that the secondary panel is hidden if necessary.
|
||||||
return self.c.PostRefreshUpdate(self.c.Context().Current())
|
self.c.PostRefreshUpdate(self.c.Context().Current())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpts) {
|
func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpts) {
|
||||||
|
@ -157,7 +157,7 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if scopeSet.Includes(types.STASH) {
|
if scopeSet.Includes(types.STASH) {
|
||||||
refresh("stash", func() { _ = self.refreshStashEntries() })
|
refresh("stash", func() { self.refreshStashEntries() })
|
||||||
}
|
}
|
||||||
|
|
||||||
if scopeSet.Includes(types.TAGS) {
|
if scopeSet.Includes(types.TAGS) {
|
||||||
@ -169,7 +169,7 @@ func (self *RefreshHelper) Refresh(options types.RefreshOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if scopeSet.Includes(types.WORKTREES) && !includeWorktreesWithBranches {
|
if scopeSet.Includes(types.WORKTREES) && !includeWorktreesWithBranches {
|
||||||
refresh("worktrees", func() { _ = self.refreshWorktrees() })
|
refresh("worktrees", func() { self.refreshWorktrees() })
|
||||||
}
|
}
|
||||||
|
|
||||||
if scopeSet.Includes(types.STAGING) {
|
if scopeSet.Includes(types.STAGING) {
|
||||||
@ -343,7 +343,8 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
|||||||
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
||||||
self.c.Model().CheckedOutBranch = checkedOutBranchName
|
self.c.Model().CheckedOutBranch = checkedOutBranchName
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().LocalCommits)
|
self.refreshView(self.c.Contexts().LocalCommits)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
|
func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
|
||||||
@ -368,7 +369,8 @@ func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
|
|||||||
self.c.Model().SubCommits = commits
|
self.c.Model().SubCommits = commits
|
||||||
self.RefreshAuthors(commits)
|
self.RefreshAuthors(commits)
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().SubCommits)
|
self.refreshView(self.c.Contexts().SubCommits)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) RefreshAuthors(commits []*models.Commit) {
|
func (self *RefreshHelper) RefreshAuthors(commits []*models.Commit) {
|
||||||
@ -397,7 +399,8 @@ func (self *RefreshHelper) refreshCommitFilesContext() error {
|
|||||||
self.c.Model().CommitFiles = files
|
self.c.Model().CommitFiles = files
|
||||||
self.c.Contexts().CommitFiles.CommitFileTreeViewModel.SetTree()
|
self.c.Contexts().CommitFiles.CommitFileTreeViewModel.SetTree()
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().CommitFiles)
|
self.refreshView(self.c.Contexts().CommitFiles)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshRebaseCommits() error {
|
func (self *RefreshHelper) refreshRebaseCommits() error {
|
||||||
@ -411,7 +414,8 @@ func (self *RefreshHelper) refreshRebaseCommits() error {
|
|||||||
self.c.Model().Commits = updatedCommits
|
self.c.Model().Commits = updatedCommits
|
||||||
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().LocalCommits)
|
self.refreshView(self.c.Contexts().LocalCommits)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshTags() error {
|
func (self *RefreshHelper) refreshTags() error {
|
||||||
@ -422,7 +426,8 @@ func (self *RefreshHelper) refreshTags() error {
|
|||||||
|
|
||||||
self.c.Model().Tags = tags
|
self.c.Model().Tags = tags
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().Tags)
|
self.refreshView(self.c.Contexts().Tags)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshStateSubmoduleConfigs() error {
|
func (self *RefreshHelper) refreshStateSubmoduleConfigs() error {
|
||||||
@ -482,9 +487,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele
|
|||||||
|
|
||||||
if refreshWorktrees {
|
if refreshWorktrees {
|
||||||
self.loadWorktrees()
|
self.loadWorktrees()
|
||||||
if err := self.refreshView(self.c.Contexts().Worktrees); err != nil {
|
self.refreshView(self.c.Contexts().Worktrees)
|
||||||
self.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !keepBranchSelectionIndex && prevSelectedBranch != nil {
|
if !keepBranchSelectionIndex && prevSelectedBranch != nil {
|
||||||
@ -495,9 +498,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := self.refreshView(self.c.Contexts().Branches); err != nil {
|
self.refreshView(self.c.Contexts().Branches)
|
||||||
self.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to re-render the commits view because the visualization of local
|
// Need to re-render the commits view because the visualization of local
|
||||||
// branch heads might have changed
|
// branch heads might have changed
|
||||||
@ -525,14 +526,8 @@ func (self *RefreshHelper) refreshFilesAndSubmodules() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.c.OnUIThread(func() error {
|
self.c.OnUIThread(func() error {
|
||||||
if err := self.refreshView(self.c.Contexts().Submodules); err != nil {
|
self.refreshView(self.c.Contexts().Submodules)
|
||||||
self.c.Log.Error(err)
|
self.refreshView(self.c.Contexts().Files)
|
||||||
}
|
|
||||||
|
|
||||||
if err := self.refreshView(self.c.Contexts().Files); err != nil {
|
|
||||||
self.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -653,7 +648,8 @@ func (self *RefreshHelper) refreshReflogCommits() error {
|
|||||||
model.FilteredReflogCommits = model.ReflogCommits
|
model.FilteredReflogCommits = model.ReflogCommits
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().ReflogCommits)
|
self.refreshView(self.c.Contexts().ReflogCommits)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshRemotes() error {
|
func (self *RefreshHelper) refreshRemotes() error {
|
||||||
@ -677,14 +673,8 @@ func (self *RefreshHelper) refreshRemotes() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := self.refreshView(self.c.Contexts().Remotes); err != nil {
|
self.refreshView(self.c.Contexts().Remotes)
|
||||||
return err
|
self.refreshView(self.c.Contexts().RemoteBranches)
|
||||||
}
|
|
||||||
|
|
||||||
if err := self.refreshView(self.c.Contexts().RemoteBranches); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,23 +688,20 @@ func (self *RefreshHelper) loadWorktrees() {
|
|||||||
self.c.Model().Worktrees = worktrees
|
self.c.Model().Worktrees = worktrees
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshWorktrees() error {
|
func (self *RefreshHelper) refreshWorktrees() {
|
||||||
self.loadWorktrees()
|
self.loadWorktrees()
|
||||||
|
|
||||||
// need to refresh branches because the branches view shows worktrees against
|
// need to refresh branches because the branches view shows worktrees against
|
||||||
// branches
|
// branches
|
||||||
if err := self.refreshView(self.c.Contexts().Branches); err != nil {
|
self.refreshView(self.c.Contexts().Branches)
|
||||||
return err
|
self.refreshView(self.c.Contexts().Worktrees)
|
||||||
}
|
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().Worktrees)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshStashEntries() error {
|
func (self *RefreshHelper) refreshStashEntries() {
|
||||||
self.c.Model().StashEntries = self.c.Git().Loaders.StashLoader.
|
self.c.Model().StashEntries = self.c.Git().Loaders.StashLoader.
|
||||||
GetStashEntries(self.c.Modes().Filtering.GetPath())
|
GetStashEntries(self.c.Modes().Filtering.GetPath())
|
||||||
|
|
||||||
return self.refreshView(self.c.Contexts().Stash)
|
self.refreshView(self.c.Contexts().Stash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// never call this on its own, it should only be called from within refreshCommits()
|
// never call this on its own, it should only be called from within refreshCommits()
|
||||||
@ -754,12 +741,12 @@ func (self *RefreshHelper) refForLog() string {
|
|||||||
return bisectInfo.GetStartHash()
|
return bisectInfo.GetStartHash()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshView(context types.Context) error {
|
func (self *RefreshHelper) refreshView(context types.Context) {
|
||||||
// Re-applying the filter must be done before re-rendering the view, so that
|
// Re-applying the filter must be done before re-rendering the view, so that
|
||||||
// the filtered list model is up to date for rendering.
|
// the filtered list model is up to date for rendering.
|
||||||
self.searchHelper.ReApplyFilter(context)
|
self.searchHelper.ReApplyFilter(context)
|
||||||
|
|
||||||
err := self.c.PostRefreshUpdate(context)
|
self.c.PostRefreshUpdate(context)
|
||||||
|
|
||||||
self.c.AfterLayout(func() error {
|
self.c.AfterLayout(func() error {
|
||||||
// Re-applying the search must be done after re-rendering the view though,
|
// Re-applying the search must be done after re-rendering the view though,
|
||||||
@ -773,6 +760,4 @@ func (self *RefreshHelper) refreshView(context types.Context) error {
|
|||||||
self.searchHelper.ReApplySearch(context)
|
self.searchHelper.ReApplySearch(context)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ func (self *SearchHelper) Cancel() {
|
|||||||
switch context := state.Context.(type) {
|
switch context := state.Context.(type) {
|
||||||
case types.IFilterableContext:
|
case types.IFilterableContext:
|
||||||
context.ClearFilter()
|
context.ClearFilter()
|
||||||
_ = self.c.PostRefreshUpdate(context)
|
self.c.PostRefreshUpdate(context)
|
||||||
case types.ISearchableContext:
|
case types.ISearchableContext:
|
||||||
context.ClearSearchString()
|
context.ClearSearchString()
|
||||||
context.GetView().ClearSearch()
|
context.GetView().ClearSearch()
|
||||||
@ -231,7 +231,7 @@ func (self *SearchHelper) OnPromptContentChanged(searchString string) {
|
|||||||
context.SetSelection(0)
|
context.SetSelection(0)
|
||||||
context.GetView().SetOriginY(0)
|
context.GetView().SetOriginY(0)
|
||||||
context.SetFilter(searchString, self.c.UserConfig().Gui.UseFuzzySearch())
|
context.SetFilter(searchString, self.c.UserConfig().Gui.UseFuzzySearch())
|
||||||
_ = self.c.PostRefreshUpdate(context)
|
self.c.PostRefreshUpdate(context)
|
||||||
case types.ISearchableContext:
|
case types.ISearchableContext:
|
||||||
// do nothing
|
// do nothing
|
||||||
default:
|
default:
|
||||||
|
@ -67,10 +67,7 @@ func (self *SubCommitsHelper) ViewSubCommits(opts ViewSubCommitsOpts) error {
|
|||||||
subCommitsContext.GetView().ClearSearch()
|
subCommitsContext.GetView().ClearSearch()
|
||||||
subCommitsContext.GetView().TitlePrefix = opts.Context.GetView().TitlePrefix
|
subCommitsContext.GetView().TitlePrefix = opts.Context.GetView().TitlePrefix
|
||||||
|
|
||||||
err = self.c.PostRefreshUpdate(self.c.Contexts().SubCommits)
|
self.c.PostRefreshUpdate(self.c.Contexts().SubCommits)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
self.c.Context().Push(self.c.Contexts().SubCommits)
|
self.c.Context().Push(self.c.Contexts().SubCommits)
|
||||||
return nil
|
return nil
|
||||||
|
@ -1177,10 +1177,9 @@ func (self *LocalCommitsController) handleOpenLogMenu() error {
|
|||||||
return func() error {
|
return func() error {
|
||||||
self.c.GetAppState().GitLogShowGraph = value
|
self.c.GetAppState().GitLogShowGraph = value
|
||||||
self.c.SaveAppStateAndLogError()
|
self.c.SaveAppStateAndLogError()
|
||||||
if err := self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits); err != nil {
|
self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
||||||
return err
|
self.c.PostRefreshUpdate(self.c.Contexts().SubCommits)
|
||||||
}
|
return nil
|
||||||
return self.c.PostRefreshUpdate(self.c.Contexts().SubCommits)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.c.Menu(types.CreateMenuOptions{
|
return self.c.Menu(types.CreateMenuOptions{
|
||||||
@ -1286,7 +1285,8 @@ func (self *LocalCommitsController) markAsBaseCommit(commit *models.Commit) erro
|
|||||||
} else {
|
} else {
|
||||||
self.c.Modes().MarkedBaseCommit.SetHash(commit.Hash)
|
self.c.Modes().MarkedBaseCommit.SetHash(commit.Hash)
|
||||||
}
|
}
|
||||||
return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsController) isHeadCommit(idx int) bool {
|
func (self *LocalCommitsController) isHeadCommit(idx int) bool {
|
||||||
|
@ -160,7 +160,8 @@ func (self *PatchBuildingController) Escape() error {
|
|||||||
|
|
||||||
if state.SelectingRange() || state.SelectingHunk() {
|
if state.SelectingRange() || state.SelectingHunk() {
|
||||||
state.SetLineSelectMode()
|
state.SetLineSelectMode()
|
||||||
return self.c.PostRefreshUpdate(context)
|
self.c.PostRefreshUpdate(context)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.c.Helpers().PatchBuilding.Escape()
|
self.c.Helpers().PatchBuilding.Escape()
|
||||||
|
@ -58,7 +58,8 @@ func (self *QuitActions) Escape() error {
|
|||||||
if listContext, ok := currentContext.(types.IListContext); ok {
|
if listContext, ok := currentContext.(types.IListContext); ok {
|
||||||
if listContext.GetList().IsSelectingRange() {
|
if listContext.GetList().IsSelectingRange() {
|
||||||
listContext.GetList().CancelRangeSelect()
|
listContext.GetList().CancelRangeSelect()
|
||||||
return self.c.PostRefreshUpdate(listContext)
|
self.c.PostRefreshUpdate(listContext)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,9 +127,7 @@ func (self *RemotesController) enter(remote *models.Remote) error {
|
|||||||
remoteBranchesContext.SetParentContext(self.Context())
|
remoteBranchesContext.SetParentContext(self.Context())
|
||||||
remoteBranchesContext.GetView().TitlePrefix = self.Context().GetView().TitlePrefix
|
remoteBranchesContext.GetView().TitlePrefix = self.Context().GetView().TitlePrefix
|
||||||
|
|
||||||
if err := self.c.PostRefreshUpdate(remoteBranchesContext); err != nil {
|
self.c.PostRefreshUpdate(remoteBranchesContext)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
self.c.Context().Push(remoteBranchesContext)
|
self.c.Context().Push(remoteBranchesContext)
|
||||||
return nil
|
return nil
|
||||||
|
@ -168,7 +168,8 @@ func (self *StagingController) EditFile() error {
|
|||||||
func (self *StagingController) Escape() error {
|
func (self *StagingController) Escape() error {
|
||||||
if self.context.GetState().SelectingRange() || self.context.GetState().SelectingHunk() {
|
if self.context.GetState().SelectingRange() || self.context.GetState().SelectingHunk() {
|
||||||
self.context.GetState().SetLineSelectMode()
|
self.context.GetState().SetLineSelectMode()
|
||||||
return self.c.PostRefreshUpdate(self.context)
|
self.c.PostRefreshUpdate(self.context)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.c.Context().Pop()
|
self.c.Context().Pop()
|
||||||
|
@ -162,10 +162,7 @@ func (self *FilesController) createResetMenu() error {
|
|||||||
|
|
||||||
func (self *FilesController) animateExplosion() {
|
func (self *FilesController) animateExplosion() {
|
||||||
self.Explode(self.c.Views().Files, func() {
|
self.Explode(self.c.Views().Files, func() {
|
||||||
err := self.c.PostRefreshUpdate(self.c.Contexts().Files)
|
self.c.PostRefreshUpdate(self.c.Contexts().Files)
|
||||||
if err != nil {
|
|
||||||
self.c.Log.Error(err)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ func (self *guiCommon) Refresh(opts types.RefreshOptions) error {
|
|||||||
return self.gui.helpers.Refresh.Refresh(opts)
|
return self.gui.helpers.Refresh.Refresh(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *guiCommon) PostRefreshUpdate(context types.Context) error {
|
func (self *guiCommon) PostRefreshUpdate(context types.Context) {
|
||||||
return self.gui.postRefreshUpdate(context)
|
self.gui.postRefreshUpdate(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *guiCommon) RunSubprocessAndRefresh(cmdObj oscommands.ICmdObj) error {
|
func (self *guiCommon) RunSubprocessAndRefresh(cmdObj oscommands.ICmdObj) error {
|
||||||
|
@ -57,7 +57,7 @@ func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = gui.c.PostRefreshUpdate(gui.State.Contexts.Menu)
|
gui.c.PostRefreshUpdate(gui.State.Contexts.Menu)
|
||||||
|
|
||||||
// TODO: ensure that if we're opened a menu from within a menu that it renders correctly
|
// TODO: ensure that if we're opened a menu from within a menu that it renders correctly
|
||||||
gui.c.Context().Push(gui.State.Contexts.Menu)
|
gui.c.Context().Push(gui.State.Contexts.Menu)
|
||||||
|
@ -9,8 +9,13 @@ import (
|
|||||||
type CherryPicking struct {
|
type CherryPicking struct {
|
||||||
CherryPickedCommits []*models.Commit
|
CherryPickedCommits []*models.Commit
|
||||||
|
|
||||||
// we only allow cherry picking from one context at a time, so you can't copy a commit from the local commits context and then also copy a commit in the reflog context
|
// we only allow cherry picking from one context at a time, so you can't copy a commit from
|
||||||
|
// the local commits context and then also copy a commit in the reflog context
|
||||||
ContextKey string
|
ContextKey string
|
||||||
|
|
||||||
|
// keep track of whether the currently copied commits have been pasted already. If so, we hide
|
||||||
|
// the mode and the blue display of the commits, but we still allow pasting them again.
|
||||||
|
DidPaste bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *CherryPicking {
|
func New() *CherryPicking {
|
||||||
@ -21,10 +26,18 @@ func New() *CherryPicking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *CherryPicking) Active() bool {
|
func (self *CherryPicking) Active() bool {
|
||||||
|
return self.CanPaste() && !self.DidPaste
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CherryPicking) CanPaste() bool {
|
||||||
return len(self.CherryPickedCommits) > 0
|
return len(self.CherryPickedCommits) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CherryPicking) SelectedHashSet() *set.Set[string] {
|
func (self *CherryPicking) SelectedHashSet() *set.Set[string] {
|
||||||
|
if self.DidPaste {
|
||||||
|
return set.New[string]()
|
||||||
|
}
|
||||||
|
|
||||||
hashes := lo.Map(self.CherryPickedCommits, func(commit *models.Commit, _ int) string {
|
hashes := lo.Map(self.CherryPickedCommits, func(commit *models.Commit, _ int) string {
|
||||||
return commit.Hash
|
return commit.Hash
|
||||||
})
|
})
|
||||||
|
@ -33,7 +33,7 @@ type IGuiCommon interface {
|
|||||||
// we call this when we've changed something in the view model but not the actual model,
|
// we call this when we've changed something in the view model but not the actual model,
|
||||||
// e.g. expanding or collapsing a folder in a file view. Calling 'Refresh' in this
|
// e.g. expanding or collapsing a folder in a file view. Calling 'Refresh' in this
|
||||||
// case would be overkill, although refresh will internally call 'PostRefreshUpdate'
|
// case would be overkill, although refresh will internally call 'PostRefreshUpdate'
|
||||||
PostRefreshUpdate(Context) error
|
PostRefreshUpdate(Context)
|
||||||
|
|
||||||
// renders string to a view without resetting its origin
|
// renders string to a view without resetting its origin
|
||||||
SetViewContent(view *gocui.View, content string)
|
SetViewContent(view *gocui.View, content string)
|
||||||
|
@ -126,7 +126,7 @@ func (gui *Gui) render() {
|
|||||||
// postRefreshUpdate is to be called on a context after the state that it depends on has been refreshed
|
// postRefreshUpdate is to be called on a context after the state that it depends on has been refreshed
|
||||||
// if the context's view is set to another context we do nothing.
|
// if the context's view is set to another context we do nothing.
|
||||||
// if the context's view is the current view we trigger a focus; re-selecting the current item.
|
// if the context's view is the current view we trigger a focus; re-selecting the current item.
|
||||||
func (gui *Gui) postRefreshUpdate(c types.Context) error {
|
func (gui *Gui) postRefreshUpdate(c types.Context) {
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
gui.Log.Infof("postRefreshUpdate for %s took %s", c.GetKey(), time.Since(t))
|
gui.Log.Infof("postRefreshUpdate for %s took %s", c.GetKey(), time.Since(t))
|
||||||
@ -137,6 +137,4 @@ func (gui *Gui) postRefreshUpdate(c types.Context) error {
|
|||||||
if gui.currentViewName() == c.GetViewName() {
|
if gui.currentViewName() == c.GetViewName() {
|
||||||
c.HandleFocus(types.OnFocusOpts{})
|
c.HandleFocus(types.OnFocusOpts{})
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -79,5 +79,32 @@ var CherryPick = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
Contains("one"),
|
Contains("one"),
|
||||||
Contains("base"),
|
Contains("base"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Even though the cherry-picking mode has been reset, it's still possible to paste the copied commits again:
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
NavigateToLine(Contains("master")).
|
||||||
|
PressPrimaryAction()
|
||||||
|
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("base").IsSelected(),
|
||||||
|
).
|
||||||
|
Press(keys.Commits.PasteCommits).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Alert().
|
||||||
|
Title(Equals("Cherry-pick")).
|
||||||
|
Content(Contains("Are you sure you want to cherry-pick the copied commits onto this branch?")).
|
||||||
|
Confirm()
|
||||||
|
}).
|
||||||
|
Tap(func() {
|
||||||
|
t.Views().Information().Content(DoesNotContain("commits copied"))
|
||||||
|
}).
|
||||||
|
Lines(
|
||||||
|
Contains("four"),
|
||||||
|
Contains("three"),
|
||||||
|
Contains("base"),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user