mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 12:25:47 +02:00
Enable the commit graph in the divergence view (#3537)
- **PR Description** In the "View divergence from upstream" view we have so far disabled the commit graph because it was too difficult to implement properly. I really miss it though, so here's a PR that enables it there, too. For feature branches it is not essential, because these usually don't contain merges and the graph is a trivial line. However, for the master branch against its upstream it is useful too see how many PRs were merged since you last fetched it, and the graph helps a lot with that. Also, when we implement #3536 it will be very useful there, too.
This commit is contained in:
commit
af0897f18f
3 changed files with 251 additions and 18 deletions
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
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{}
|
||||
|
||||
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 ""
|
||||
_, 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]
|
||||
|
|
|
@ -359,6 +359,185 @@ func TestGetCommitListDisplayStrings(t *testing.T) {
|
|||
hash3 ◯ commit3
|
||||
`),
|
||||
},
|
||||
{
|
||||
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{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue