move active branch indices to stack

This commit is contained in:
Sameen Karim
2026-03-22 09:38:08 -07:00
parent d22f0c3377
commit 7bb5ca271c
3 changed files with 58 additions and 23 deletions
+14 -23
View File
@@ -68,26 +68,22 @@ func runNavigate(cfg *config.Config, delta int) error {
idx := s.IndexOf(currentBranch)
if idx < 0 {
// Might be on the trunk
if currentBranch == s.Trunk.Branch {
if delta > 0 && len(s.Branches) > 0 {
targetIdx := s.FirstActiveBranchIndex()
if targetIdx < 0 {
// All merged — fall back to top branch with warning
targetIdx = len(s.Branches) - 1
cfg.Warningf("Warning: all branches in this stack have been merged")
}
target := s.Branches[targetIdx].Branch
if err := git.CheckoutBranch(target); err != nil {
return err
}
cfg.Successf("Switched to %s", target)
return nil
// Current branch is the trunk (not in s.Branches).
// loadStack guarantees the branch is part of the stack.
if delta > 0 && len(s.Branches) > 0 {
targetIdx := s.FirstActiveBranchIndex()
if targetIdx < 0 {
targetIdx = len(s.Branches) - 1
cfg.Warningf("Warning: all branches in this stack have been merged")
}
cfg.Printf("Already at the bottom of the stack")
target := s.Branches[targetIdx].Branch
if err := git.CheckoutBranch(target); err != nil {
return err
}
cfg.Successf("Switched to %s", target)
return nil
}
cfg.Errorf("current branch %q is not in the stack", currentBranch)
cfg.Printf("Already at the bottom of the stack")
return nil
}
@@ -110,12 +106,7 @@ func runNavigate(cfg *config.Config, delta int) error {
}
} else {
// Build list of active (non-merged) branch indices
var activeIndices []int
for i, b := range s.Branches {
if !b.IsMerged() {
activeIndices = append(activeIndices, i)
}
}
activeIndices := s.ActiveBranchIndices()
// Find current position in active list
activePos := -1
+11
View File
@@ -124,6 +124,17 @@ func (s *Stack) FirstActiveBranchIndex() int {
return -1
}
// ActiveBranchIndices returns the indices of all non-merged branches.
func (s *Stack) ActiveBranchIndices() []int {
var indices []int
for i, b := range s.Branches {
if !b.IsMerged() {
indices = append(indices, i)
}
}
return indices
}
// ActiveBaseBranch returns the effective parent for a branch, skipping merged
// ancestors. For the first active branch (or any branch whose downstack is all
// merged), this returns the trunk.
+33
View File
@@ -192,6 +192,39 @@ func TestFirstActiveBranchIndex(t *testing.T) {
})
}
// --- ActiveBranchIndices: navigation ---
func TestActiveBranchIndices(t *testing.T) {
t.Run("all active", func(t *testing.T) {
s := makeStack("main", "b1", "b2", "b3")
assert.Equal(t, []int{0, 1, 2}, s.ActiveBranchIndices())
})
t.Run("some merged", func(t *testing.T) {
s := Stack{
Trunk: BranchRef{Branch: "main"},
Branches: []BranchRef{
makeMergedBranch("b1", 1),
{Branch: "b2"},
makeMergedBranch("b3", 3),
{Branch: "b4"},
},
}
assert.Equal(t, []int{1, 3}, s.ActiveBranchIndices())
})
t.Run("all merged", func(t *testing.T) {
s := Stack{
Trunk: BranchRef{Branch: "main"},
Branches: []BranchRef{
makeMergedBranch("b1", 1),
makeMergedBranch("b2", 2),
},
}
assert.Empty(t, s.ActiveBranchIndices())
})
}
// --- Load / Save round-trip persistence ---
func TestLoad_Save_RoundTrip(t *testing.T) {