diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2020-08-27 20:50:30 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2020-08-27 21:51:07 +1000 |
commit | 40bec49de8428be4e771f2ded1e8ffecbd0c4fd5 (patch) | |
tree | f97d7d748bb2441d867e5b81c3a9a9323dde0aa6 | |
parent | f99d5f74d49109c19f7701005e636a38c9a70fdb (diff) |
more efficient refreshing of rebase commits
-rw-r--r-- | pkg/commands/commit_list_builder.go | 71 | ||||
-rw-r--r-- | pkg/commands/commit_list_builder_test.go | 9 | ||||
-rw-r--r-- | pkg/gui/commits_panel.go | 25 | ||||
-rw-r--r-- | pkg/gui/gui.go | 1 | ||||
-rw-r--r-- | pkg/gui/sub_commits_panel.go | 2 |
5 files changed, 74 insertions, 34 deletions
diff --git a/pkg/commands/commit_list_builder.go b/pkg/commands/commit_list_builder.go index 46c59d38b..bebc78253 100644 --- a/pkg/commands/commit_list_builder.go +++ b/pkg/commands/commit_list_builder.go @@ -28,21 +28,19 @@ const SEPARATION_CHAR = "|" // CommitListBuilder returns a list of Branch objects for the current repo type CommitListBuilder struct { - Log *logrus.Entry - GitCommand *GitCommand - OSCommand *OSCommand - Tr *i18n.Localizer - CherryPickedCommits []*Commit + Log *logrus.Entry + GitCommand *GitCommand + OSCommand *OSCommand + Tr *i18n.Localizer } // NewCommitListBuilder builds a new commit list builder -func NewCommitListBuilder(log *logrus.Entry, gitCommand *GitCommand, osCommand *OSCommand, tr *i18n.Localizer, cherryPickedCommits []*Commit) *CommitListBuilder { +func NewCommitListBuilder(log *logrus.Entry, gitCommand *GitCommand, osCommand *OSCommand, tr *i18n.Localizer) *CommitListBuilder { return &CommitListBuilder{ - Log: log, - GitCommand: gitCommand, - OSCommand: osCommand, - Tr: tr, - CherryPickedCommits: cherryPickedCommits, + Log: log, + GitCommand: gitCommand, + OSCommand: osCommand, + Tr: tr, } } @@ -94,28 +92,53 @@ type GetCommitsOptions struct { RefName string // e.g. "HEAD" or "my_branch" } +func (c *CommitListBuilder) MergeRebasingCommits(commits []*Commit) ([]*Commit, error) { + // chances are we have as many commits as last time so we'll set the capacity to be the old length + result := make([]*Commit, 0, len(commits)) + for i, commit := range commits { + if commit.Status != "rebasing" { // removing the existing rebase commits so we can add the refreshed ones + result = append(result, commits[i:]...) + break + } + } + + rebaseMode, err := c.GitCommand.RebaseMode() + if err != nil { + return nil, err + } + + if rebaseMode == "" { + // not in rebase mode so return original commits + return result, nil + } + + rebasingCommits, err := c.getRebasingCommits(rebaseMode) + if err != nil { + return nil, err + } + if len(rebasingCommits) > 0 { + result = append(rebasingCommits, result...) + } + + return result, nil +} + // GetCommits obtains the commits of the current branch func (c *CommitListBuilder) GetCommits(opts GetCommitsOptions) ([]*Commit, error) { commits := []*Commit{} var rebasingCommits []*Commit - rebaseMode := "" + rebaseMode, err := c.GitCommand.RebaseMode() + if err != nil { + return nil, err + } - if opts.IncludeRebaseCommits { + if opts.IncludeRebaseCommits && opts.FilterPath == "" { var err error - rebaseMode, err = c.GitCommand.RebaseMode() + rebasingCommits, err = c.MergeRebasingCommits(commits) if err != nil { return nil, err } - if rebaseMode != "" && opts.FilterPath == "" { - // here we want to also prepend the commits that we're in the process of rebasing - rebasingCommits, err = c.getRebasingCommits(rebaseMode) - if err != nil { - return nil, err - } - if len(rebasingCommits) > 0 { - commits = append(commits, rebasingCommits...) - } - } + commits = append(commits, rebasingCommits...) } passedFirstPushedCommit := false diff --git a/pkg/commands/commit_list_builder_test.go b/pkg/commands/commit_list_builder_test.go index 590ee6f4a..08114f7a5 100644 --- a/pkg/commands/commit_list_builder_test.go +++ b/pkg/commands/commit_list_builder_test.go @@ -13,11 +13,10 @@ func NewDummyCommitListBuilder() *CommitListBuilder { osCommand := NewDummyOSCommand() return &CommitListBuilder{ - Log: NewDummyLog(), - GitCommand: NewDummyGitCommandWithOSCommand(osCommand), - OSCommand: osCommand, - Tr: i18n.NewLocalizer(NewDummyLog()), - CherryPickedCommits: []*Commit{}, + Log: NewDummyLog(), + GitCommand: NewDummyGitCommandWithOSCommand(osCommand), + OSCommand: osCommand, + Tr: i18n.NewLocalizer(NewDummyLog()), } } diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index 200fea7af..950149c6e 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -97,7 +97,10 @@ func (gui *Gui) refreshCommits() error { } func (gui *Gui) refreshCommitsWithLimit() error { - builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.Modes.CherryPicking.CherryPickedCommits) + gui.State.BranchCommitsMutex.Lock() + defer gui.State.BranchCommitsMutex.Unlock() + + builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr) commits, err := builder.GetCommits( commands.GetCommitsOptions{ @@ -115,6 +118,21 @@ func (gui *Gui) refreshCommitsWithLimit() error { return gui.postRefreshUpdate(gui.Contexts.BranchCommits.Context) } +func (gui *Gui) refreshRebaseCommits() error { + gui.State.BranchCommitsMutex.Lock() + defer gui.State.BranchCommitsMutex.Unlock() + + builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr) + + updatedCommits, err := builder.MergeRebasingCommits(gui.State.Commits) + if err != nil { + return err + } + gui.State.Commits = updatedCommits + + return gui.postRefreshUpdate(gui.Contexts.BranchCommits.Context) +} + // specific functions func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error { @@ -256,9 +274,8 @@ func (gui *Gui) handleMidRebaseCommand(action string) (bool, error) { if err := gui.GitCommand.EditRebaseTodo(gui.State.Panels.Commits.SelectedLineIdx, action); err != nil { return false, gui.surfaceError(err) } - // TODO: consider doing this in a way that is less expensive. We don't actually - // need to reload all the commits, just the TODO commits. - return true, gui.refreshSidePanels(refreshOptions{scope: []int{COMMITS}}) + + return true, gui.refreshRebaseCommits() } func (gui *Gui) handleCommitDelete(g *gocui.Gui, v *gocui.View) error { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index e95ef1e99..858bbef5f 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -297,6 +297,7 @@ type guiState struct { RefreshingFilesMutex sync.Mutex RefreshingStatusMutex sync.Mutex FetchMutex sync.Mutex + BranchCommitsMutex sync.Mutex Searching searchingState ScreenMode int SideView *gocui.View diff --git a/pkg/gui/sub_commits_panel.go b/pkg/gui/sub_commits_panel.go index 571df1820..06793680f 100644 --- a/pkg/gui/sub_commits_panel.go +++ b/pkg/gui/sub_commits_panel.go @@ -77,7 +77,7 @@ func (gui *Gui) handleViewSubCommitFiles() error { func (gui *Gui) switchToSubCommitsContext(refName string) error { // need to populate my sub commits - builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr, gui.State.Modes.CherryPicking.CherryPickedCommits) + builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr) commits, err := builder.GetCommits( commands.GetCommitsOptions{ |