mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-11-14 00:33:35 -04:00
The commits panel will need to call it. All it knows is the name of the checked-out branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
150 lines
4.9 KiB
Go
150 lines
4.9 KiB
Go
package branchstack
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
"github.com/samber/lo"
|
|
"github.com/stefanhaller/git-todo-parser/todo"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestBranchesBelow(t *testing.T) {
|
|
hashPool := &utils.StringPool{}
|
|
commit := func(hash string, status models.CommitStatus, parents ...string) *models.Commit {
|
|
return models.NewCommit(hashPool, models.NewCommitOpts{Hash: hash, Status: status, Parents: parents})
|
|
}
|
|
todoCommit := func(hash string) *models.Commit {
|
|
return models.NewCommit(hashPool, models.NewCommitOpts{Hash: hash, Action: todo.Pick, Status: models.StatusRebasing})
|
|
}
|
|
branch := func(name string, tip string) *models.Branch {
|
|
return &models.Branch{Name: name, CommitHash: tip}
|
|
}
|
|
|
|
current := branch("current", "c3")
|
|
mainBranches := []string{"master", "main"}
|
|
|
|
scenarios := []struct {
|
|
testName string
|
|
commits []*models.Commit
|
|
branches []*models.Branch
|
|
// The branch to look for branches below; the one called "current" if nil
|
|
current *models.Branch
|
|
expected []string
|
|
}{
|
|
{
|
|
testName: "stack of branches, closest to the current one first",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed),
|
|
commit("c2", models.StatusPushed),
|
|
commit("c1", models.StatusUnpushed),
|
|
commit("m1", models.StatusMerged),
|
|
},
|
|
branches: []*models.Branch{current, branch("first", "c1"), branch("second", "c2"), branch("master", "m1")},
|
|
expected: []string{"second", "first"},
|
|
},
|
|
{
|
|
testName: "branch pointing at the same commit as the current one",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed),
|
|
commit("m1", models.StatusMerged),
|
|
},
|
|
branches: []*models.Branch{current, branch("twin", "c3")},
|
|
expected: []string{"twin"},
|
|
},
|
|
{
|
|
testName: "several branches pointing at one commit keep their order",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed),
|
|
commit("c1", models.StatusUnpushed),
|
|
},
|
|
branches: []*models.Branch{current, branch("one", "c1"), branch("two", "c1")},
|
|
expected: []string{"one", "two"},
|
|
},
|
|
{
|
|
testName: "main branches are left out even if their tip isn't merged",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed),
|
|
commit("c1", models.StatusUnpushed),
|
|
},
|
|
branches: []*models.Branch{current, branch("main", "c1")},
|
|
expected: []string{},
|
|
},
|
|
{
|
|
testName: "nothing is stacked below a main branch",
|
|
commits: []*models.Commit{
|
|
commit("m2", models.StatusUnpushed, "m1", "w1"),
|
|
commit("w1", models.StatusUnpushed, "m1"),
|
|
commit("m1", models.StatusMerged),
|
|
},
|
|
branches: []*models.Branch{branch("master", "m2"), branch("wip", "w1")},
|
|
current: branch("master", "m2"),
|
|
expected: []string{},
|
|
},
|
|
{
|
|
testName: "branches merged into a local main branch below the current one are left out",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed, "c2"),
|
|
commit("c2", models.StatusUnpushed, "m2"),
|
|
commit("m2", models.StatusUnpushed, "m1", "w1"),
|
|
commit("w1", models.StatusUnpushed, "m1"),
|
|
commit("m1", models.StatusMerged),
|
|
},
|
|
branches: []*models.Branch{current, branch("first", "c2"), branch("master", "m2"), branch("wip", "w1")},
|
|
expected: []string{"first"},
|
|
},
|
|
{
|
|
testName: "branches merged into a local main branch that was merged into the current one are left out",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed, "c2", "m2"),
|
|
commit("m2", models.StatusUnpushed, "m1", "w1"),
|
|
commit("w1", models.StatusUnpushed, "m1"),
|
|
commit("c2", models.StatusUnpushed, "m1"),
|
|
commit("m1", models.StatusMerged),
|
|
},
|
|
branches: []*models.Branch{current, branch("first", "c2"), branch("master", "m2"), branch("wip", "w1")},
|
|
expected: []string{"first"},
|
|
},
|
|
{
|
|
testName: "branches whose tip is merged are left out",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed),
|
|
commit("m1", models.StatusMerged),
|
|
commit("m0", models.StatusMerged),
|
|
},
|
|
branches: []*models.Branch{current, branch("old", "m0"), branch("master", "m1")},
|
|
expected: []string{},
|
|
},
|
|
{
|
|
testName: "branches whose tip is not among the commits are left out",
|
|
commits: []*models.Commit{
|
|
commit("c3", models.StatusUnpushed),
|
|
},
|
|
branches: []*models.Branch{current, branch("sibling", "s1")},
|
|
expected: []string{},
|
|
},
|
|
{
|
|
testName: "todo commits of a rebase don't count",
|
|
commits: []*models.Commit{
|
|
todoCommit("t1"),
|
|
commit("c3", models.StatusUnpushed),
|
|
},
|
|
branches: []*models.Branch{current, branch("other", "t1")},
|
|
expected: []string{},
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.testName, func(t *testing.T) {
|
|
branch := current
|
|
if s.current != nil {
|
|
branch = s.current
|
|
}
|
|
result := BranchesBelow(s.commits, s.branches, branch.Name, mainBranches)
|
|
names := lo.Map(result, func(b *models.Branch, _ int) string { return b.Name })
|
|
assert.Equal(t, s.expected, names)
|
|
})
|
|
}
|
|
}
|