diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2024-04-28 10:37:02 +0200 |
---|---|---|
committer | Stefan Haller <stefan@haller-berlin.de> | 2024-04-30 13:50:46 +0200 |
commit | b7673577a20c04b7fe711363b1fdc270030fdae6 (patch) | |
tree | 80706e71bb4c818e32e32948675b98ccc601131a | |
parent | 00c55d5711832a87f35b822ca87ceb1ab66a7e37 (diff) |
Enable the commit graph in the divergence view
-rw-r--r-- | pkg/gui/context/sub_commits_context.go | 2 | ||||
-rw-r--r-- | pkg/gui/presentation/commits.go | 90 | ||||
-rw-r--r-- | pkg/gui/presentation/commits_test.go | 179 |
3 files changed, 252 insertions, 19 deletions
diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go index b37be8667..f540dba87 100644 --- a/pkg/gui/context/sub_commits_context.go +++ b/pkg/gui/context/sub_commits_context.go @@ -75,7 +75,7 @@ func NewSubCommitsContext( endIdx, // Don't show the graph in the left/right view; we'd like to, but // it's too complicated: - shouldShowGraph(c) && viewModel.GetRefToShowDivergenceFrom() == "", + shouldShowGraph(c), git_commands.NewNullBisectInfo(), false, ) diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go index cff36bf30..c385d3407 100644 --- a/pkg/gui/presentation/commits.go +++ b/pkg/gui/presentation/commits.go @@ -24,6 +24,7 @@ import ( type pipeSetCacheKey struct { commitHash string commitCount int + divergence models.Divergence } var ( @@ -78,24 +79,76 @@ func GetCommitListDisplayStrings( // function expects to be passed the index of the commit in terms of the `commits` slice var getGraphLine func(int) string if showGraph { - // this is where the graph begins (may be beyond the TODO commits depending on startIdx, - // but we'll never include TODO commits as part of the graph because it'll be messy) - graphOffset := max(startIdx, rebaseOffset) - - pipeSets := loadPipesets(commits[rebaseOffset:]) - pipeSetOffset := max(startIdx-rebaseOffset, 0) - graphPipeSets := pipeSets[pipeSetOffset:max(endIdx-rebaseOffset, 0)] - graphCommits := commits[graphOffset:endIdx] - graphLines := graph.RenderAux( - graphPipeSets, - graphCommits, - selectedCommitHash, - ) - getGraphLine = func(idx int) string { - if idx >= graphOffset { - return graphLines[idx-graphOffset] - } else { - return "" + if len(commits) > 0 && commits[0].Divergence != models.DivergenceNone { + // Showing a divergence log; we know we don't have any rebasing + // commits in this case. But we need to render separate graphs for + // the Local and Remote sections. + allGraphLines := []string{} + + _, localSectionStart, found := lo.FindIndexOf( + commits, func(c *models.Commit) bool { return c.Divergence == models.DivergenceLeft }) + if !found { + localSectionStart = len(commits) + } + + if localSectionStart > 0 { + // we have some remote commits + pipeSets := loadPipesets(commits[:localSectionStart]) + if startIdx < localSectionStart { + // some of the remote commits are visible + start := startIdx + end := min(endIdx, localSectionStart) + graphPipeSets := pipeSets[start:end] + graphCommits := commits[start:end] + graphLines := graph.RenderAux( + graphPipeSets, + graphCommits, + selectedCommitHash, + ) + allGraphLines = append(allGraphLines, graphLines...) + } + } + if localSectionStart < len(commits) { + // we have some local commits + pipeSets := loadPipesets(commits[localSectionStart:]) + if localSectionStart < endIdx { + // some of the local commits are visible + graphOffset := max(startIdx, localSectionStart) + pipeSetOffset := max(startIdx-localSectionStart, 0) + graphPipeSets := pipeSets[pipeSetOffset : endIdx-localSectionStart] + graphCommits := commits[graphOffset:endIdx] + graphLines := graph.RenderAux( + graphPipeSets, + graphCommits, + selectedCommitHash, + ) + allGraphLines = append(allGraphLines, graphLines...) + } + } + + getGraphLine = func(idx int) string { + return allGraphLines[idx-startIdx] + } + } else { + // this is where the graph begins (may be beyond the TODO commits depending on startIdx, + // but we'll never include TODO commits as part of the graph because it'll be messy) + graphOffset := max(startIdx, rebaseOffset) + + pipeSets := loadPipesets(commits[rebaseOffset:]) + pipeSetOffset := max(startIdx-rebaseOffset, 0) + graphPipeSets := pipeSets[pipeSetOffset:max(endIdx-rebaseOffset, 0)] + graphCommits := commits[graphOffset:endIdx] + graphLines := graph.RenderAux( + graphPipeSets, + graphCommits, + selectedCommitHash, + ) + getGraphLine = func(idx int) string { + if idx >= graphOffset { + return graphLines[idx-graphOffset] + } else { + return "" + } } } } else { @@ -205,6 +258,7 @@ func loadPipesets(commits []*models.Commit) [][]*graph.Pipe { cacheKey := pipeSetCacheKey{ commitHash: commits[0].Hash, commitCount: len(commits), + divergence: commits[0].Divergence, } pipeSets, ok := pipeSetCache[cacheKey] diff --git a/pkg/gui/presentation/commits_test.go b/pkg/gui/presentation/commits_test.go index 0438b105c..53101cb6d 100644 --- a/pkg/gui/presentation/commits_test.go +++ b/pkg/gui/presentation/commits_test.go @@ -360,6 +360,185 @@ func TestGetCommitListDisplayStrings(t *testing.T) { `), }, { + testName: "graph in divergence view - all commits visible", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1r", Parents: []string{"hash2r"}, Divergence: models.DivergenceRight}, + {Name: "commit2", Hash: "hash2r", Parents: []string{"hash3r", "hash5r"}, Divergence: models.DivergenceRight}, + {Name: "commit3", Hash: "hash3r", Parents: []string{"hash4r"}, Divergence: models.DivergenceRight}, + {Name: "commit1", Hash: "hash1l", Parents: []string{"hash2l"}, Divergence: models.DivergenceLeft}, + {Name: "commit2", Hash: "hash2l", Parents: []string{"hash3l", "hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit3", Hash: "hash3l", Parents: []string{"hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit4", Hash: "hash4l", Parents: []string{"hash5l"}, Divergence: models.DivergenceLeft}, + {Name: "commit5", Hash: "hash5l", Parents: []string{"hash6l"}, Divergence: models.DivergenceLeft}, + }, + startIdx: 0, + endIdx: 8, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↓ hash1r ◯ commit1 + ↓ hash2r ⏣─╮ commit2 + ↓ hash3r ◯ │ commit3 + ↑ hash1l ◯ commit1 + ↑ hash2l ⏣─╮ commit2 + ↑ hash3l ◯ │ commit3 + ↑ hash4l ◯─╯ commit4 + ↑ hash5l ◯ commit5 + `), + }, + { + testName: "graph in divergence view - not all remote commits visible", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1r", Parents: []string{"hash2r"}, Divergence: models.DivergenceRight}, + {Name: "commit2", Hash: "hash2r", Parents: []string{"hash3r", "hash5r"}, Divergence: models.DivergenceRight}, + {Name: "commit3", Hash: "hash3r", Parents: []string{"hash4r"}, Divergence: models.DivergenceRight}, + {Name: "commit1", Hash: "hash1l", Parents: []string{"hash2l"}, Divergence: models.DivergenceLeft}, + {Name: "commit2", Hash: "hash2l", Parents: []string{"hash3l", "hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit3", Hash: "hash3l", Parents: []string{"hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit4", Hash: "hash4l", Parents: []string{"hash5l"}, Divergence: models.DivergenceLeft}, + {Name: "commit5", Hash: "hash5l", Parents: []string{"hash6l"}, Divergence: models.DivergenceLeft}, + }, + startIdx: 2, + endIdx: 8, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↓ hash3r ◯ │ commit3 + ↑ hash1l ◯ commit1 + ↑ hash2l ⏣─╮ commit2 + ↑ hash3l ◯ │ commit3 + ↑ hash4l ◯─╯ commit4 + ↑ hash5l ◯ commit5 + `), + }, + { + testName: "graph in divergence view - not all local commits", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1r", Parents: []string{"hash2r"}, Divergence: models.DivergenceRight}, + {Name: "commit2", Hash: "hash2r", Parents: []string{"hash3r", "hash5r"}, Divergence: models.DivergenceRight}, + {Name: "commit3", Hash: "hash3r", Parents: []string{"hash4r"}, Divergence: models.DivergenceRight}, + {Name: "commit1", Hash: "hash1l", Parents: []string{"hash2l"}, Divergence: models.DivergenceLeft}, + {Name: "commit2", Hash: "hash2l", Parents: []string{"hash3l", "hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit3", Hash: "hash3l", Parents: []string{"hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit4", Hash: "hash4l", Parents: []string{"hash5l"}, Divergence: models.DivergenceLeft}, + {Name: "commit5", Hash: "hash5l", Parents: []string{"hash6l"}, Divergence: models.DivergenceLeft}, + }, + startIdx: 0, + endIdx: 5, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↓ hash1r ◯ commit1 + ↓ hash2r ⏣─╮ commit2 + ↓ hash3r ◯ │ commit3 + ↑ hash1l ◯ commit1 + ↑ hash2l ⏣─╮ commit2 + `), + }, + { + testName: "graph in divergence view - no remote commits visible", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1r", Parents: []string{"hash2r"}, Divergence: models.DivergenceRight}, + {Name: "commit2", Hash: "hash2r", Parents: []string{"hash3r", "hash5r"}, Divergence: models.DivergenceRight}, + {Name: "commit3", Hash: "hash3r", Parents: []string{"hash4r"}, Divergence: models.DivergenceRight}, + {Name: "commit1", Hash: "hash1l", Parents: []string{"hash2l"}, Divergence: models.DivergenceLeft}, + {Name: "commit2", Hash: "hash2l", Parents: []string{"hash3l", "hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit3", Hash: "hash3l", Parents: []string{"hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit4", Hash: "hash4l", Parents: []string{"hash5l"}, Divergence: models.DivergenceLeft}, + {Name: "commit5", Hash: "hash5l", Parents: []string{"hash6l"}, Divergence: models.DivergenceLeft}, + }, + startIdx: 4, + endIdx: 8, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↑ hash2l ⏣─╮ commit2 + ↑ hash3l ◯ │ commit3 + ↑ hash4l ◯─╯ commit4 + ↑ hash5l ◯ commit5 + `), + }, + { + testName: "graph in divergence view - no local commits visible", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1r", Parents: []string{"hash2r"}, Divergence: models.DivergenceRight}, + {Name: "commit2", Hash: "hash2r", Parents: []string{"hash3r", "hash5r"}, Divergence: models.DivergenceRight}, + {Name: "commit3", Hash: "hash3r", Parents: []string{"hash4r"}, Divergence: models.DivergenceRight}, + {Name: "commit1", Hash: "hash1l", Parents: []string{"hash2l"}, Divergence: models.DivergenceLeft}, + {Name: "commit2", Hash: "hash2l", Parents: []string{"hash3l", "hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit3", Hash: "hash3l", Parents: []string{"hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit4", Hash: "hash4l", Parents: []string{"hash5l"}, Divergence: models.DivergenceLeft}, + {Name: "commit5", Hash: "hash5l", Parents: []string{"hash6l"}, Divergence: models.DivergenceLeft}, + }, + startIdx: 0, + endIdx: 2, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↓ hash1r ◯ commit1 + ↓ hash2r ⏣─╮ commit2 + `), + }, + { + testName: "graph in divergence view - no remote commits present", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1l", Parents: []string{"hash2l"}, Divergence: models.DivergenceLeft}, + {Name: "commit2", Hash: "hash2l", Parents: []string{"hash3l", "hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit3", Hash: "hash3l", Parents: []string{"hash4l"}, Divergence: models.DivergenceLeft}, + {Name: "commit4", Hash: "hash4l", Parents: []string{"hash5l"}, Divergence: models.DivergenceLeft}, + {Name: "commit5", Hash: "hash5l", Parents: []string{"hash6l"}, Divergence: models.DivergenceLeft}, + }, + startIdx: 0, + endIdx: 5, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↑ hash1l ◯ commit1 + ↑ hash2l ⏣─╮ commit2 + ↑ hash3l ◯ │ commit3 + ↑ hash4l ◯─╯ commit4 + ↑ hash5l ◯ commit5 + `), + }, + { + testName: "graph in divergence view - no local commits present", + commits: []*models.Commit{ + {Name: "commit1", Hash: "hash1r", Parents: []string{"hash2r"}, Divergence: models.DivergenceRight}, + {Name: "commit2", Hash: "hash2r", Parents: []string{"hash3r", "hash5r"}, Divergence: models.DivergenceRight}, + {Name: "commit3", Hash: "hash3r", Parents: []string{"hash4r"}, Divergence: models.DivergenceRight}, + }, + startIdx: 0, + endIdx: 3, + showGraph: true, + bisectInfo: git_commands.NewNullBisectInfo(), + cherryPickedCommitHashSet: set.New[string](), + showYouAreHereLabel: false, + now: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + expected: formatExpected(` + ↓ hash1r ◯ commit1 + ↓ hash2r ⏣─╮ commit2 + ↓ hash3r ◯ │ commit3 + `), + }, + { testName: "custom time format", commits: []*models.Commit{ {Name: "commit1", Hash: "hash1", UnixTimestamp: 1577844184, AuthorName: "Jesse Duffield"}, |