Skip to content

Commit d59ff61

Browse files
committed
fetch trunk if missing locally
1 parent eb74310 commit d59ff61

3 files changed

Lines changed: 97 additions & 6 deletions

File tree

cmd/add_test.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"fmt"
45
"testing"
56
"time"
67

@@ -593,22 +594,32 @@ func TestAdd_AdoptExistingBranchWithoutCommonBaseFails(t *testing.T) {
593594

594595
func TestAdd_InitializesStackWithExplicitBranch(t *testing.T) {
595596
gitDir := t.TempDir()
596-
var createdBranch, createdBase, checkedOut string
597+
trunkExists := false
598+
var created [][2]string
599+
var checkedOut string
597600
restore := git.SetOps(&git.MockOps{
598601
GitDirFn: func() (string, error) { return gitDir, nil },
599602
CurrentBranchFn: func() (string, error) { return "unstacked", nil },
600603
DefaultBranchFn: func() (string, error) { return "main", nil },
601604
IsRerereEnabledFn: func() (bool, error) { return true, nil },
605+
BranchExistsFn: func(name string) bool { return name == "main" && trunkExists },
606+
RevParseFn: func(ref string) (string, error) {
607+
if ref == "main" && !trunkExists {
608+
return "", fmt.Errorf("unknown revision %s", ref)
609+
}
610+
return "sha-" + ref, nil
611+
},
602612
CreateBranchFn: func(name, base string) error {
603-
createdBranch = name
604-
createdBase = base
613+
created = append(created, [2]string{name, base})
614+
if name == "main" {
615+
trunkExists = true
616+
}
605617
return nil
606618
},
607619
CheckoutBranchFn: func(name string) error {
608620
checkedOut = name
609621
return nil
610622
},
611-
RevParseFn: func(ref string) (string, error) { return "sha-" + ref, nil },
612623
})
613624
defer restore()
614625

@@ -625,8 +636,10 @@ func TestAdd_InitializesStackWithExplicitBranch(t *testing.T) {
625636

626637
require.NoError(t, err)
627638
assert.NotContains(t, output, "not part of a stack")
628-
assert.Equal(t, "first-layer", createdBranch)
629-
assert.Equal(t, "main", createdBase)
639+
assert.Equal(t, [][2]string{
640+
{"main", "origin/main"},
641+
{"first-layer", "main"},
642+
}, created)
630643
assert.Equal(t, "first-layer", checkedOut)
631644

632645
sf, loadErr := stack.Load(gitDir)
@@ -684,6 +697,7 @@ func TestAdd_InitializesGeneratedBranchAndCommits(t *testing.T) {
684697
CurrentBranchFn: func() (string, error) { return currentBranch, nil },
685698
DefaultBranchFn: func() (string, error) { return "main", nil },
686699
IsRerereEnabledFn: func() (bool, error) { return true, nil },
700+
BranchExistsFn: func(name string) bool { return name == "main" },
687701
CreateBranchFn: func(name, base string) error {
688702
assert.Equal(t, expectedBranch, name)
689703
assert.Equal(t, "main", base)

cmd/init.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ func runInit(cfg *config.Config, opts *initOptions) error {
106106
}
107107
}
108108

109+
// The repository's default branch may only exist on the remote if the
110+
// initial local branch was renamed before starting the stack.
111+
if _, err := git.RevParse(trunk); err != nil {
112+
remote, err := pickRemote(cfg, currentBranch, "")
113+
if err != nil {
114+
if !errors.Is(err, errInterrupt) {
115+
cfg.Errorf("failed to resolve remote: %s", err)
116+
}
117+
return ErrSilent
118+
}
119+
if err := ensureLocalTrunk(cfg, trunk, remote); err != nil {
120+
cfg.Errorf("%s", err)
121+
return ErrSilent
122+
}
123+
}
124+
109125
// --- Flag validation ---
110126

111127
// --adopt is deprecated; print a notice and continue normally.

cmd/init_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,67 @@ func TestInit_CustomTrunk(t *testing.T) {
6969
assert.Equal(t, "develop", sf.Stacks[0].Trunk.Branch)
7070
}
7171

72+
func TestInit_RestoresMissingLocalTrunk(t *testing.T) {
73+
gitDir := t.TempDir()
74+
trunkExists := false
75+
var fetchedRemote string
76+
var fetchedBranches []string
77+
var created [][2]string
78+
79+
restore := git.SetOps(&git.MockOps{
80+
GitDirFn: func() (string, error) { return gitDir, nil },
81+
DefaultBranchFn: func() (string, error) { return "main", nil },
82+
CurrentBranchFn: func() (string, error) { return "renamed-branch", nil },
83+
IsRerereEnabledFn: func() (bool, error) { return true, nil },
84+
BranchExistsFn: func(name string) bool {
85+
return name == "renamed-branch" || (name == "main" && trunkExists)
86+
},
87+
ResolveRemoteFn: func(branch string) (string, error) {
88+
assert.Equal(t, "renamed-branch", branch)
89+
return "origin", nil
90+
},
91+
FetchBranchesFn: func(remote string, branches []string) error {
92+
fetchedRemote = remote
93+
fetchedBranches = branches
94+
return nil
95+
},
96+
RevParseFn: func(ref string) (string, error) {
97+
if ref == "main" && !trunkExists {
98+
return "", fmt.Errorf("unknown revision %s", ref)
99+
}
100+
return "sha-" + ref, nil
101+
},
102+
CreateBranchFn: func(name, base string) error {
103+
created = append(created, [2]string{name, base})
104+
if name == "main" {
105+
trunkExists = true
106+
}
107+
return nil
108+
},
109+
CheckoutBranchFn: func(string) error { return nil },
110+
})
111+
defer restore()
112+
113+
cfg, outR, errR := config.NewTestConfig()
114+
err := runInit(cfg, &initOptions{branches: []string{"first-layer"}})
115+
output := collectOutput(cfg, outR, errR)
116+
117+
require.NoError(t, err)
118+
assert.Equal(t, "origin", fetchedRemote)
119+
assert.Equal(t, []string{"main"}, fetchedBranches)
120+
assert.Equal(t, [][2]string{
121+
{"main", "origin/main"},
122+
{"first-layer", "main"},
123+
}, created)
124+
assert.Contains(t, output, "Created local trunk branch main from origin/main")
125+
126+
sf, loadErr := stack.Load(gitDir)
127+
require.NoError(t, loadErr)
128+
require.Len(t, sf.Stacks, 1)
129+
assert.Equal(t, "main", sf.Stacks[0].Trunk.Branch)
130+
assert.Equal(t, []string{"first-layer"}, sf.Stacks[0].BranchNames())
131+
}
132+
72133
func TestInit_AdoptExistingBranches(t *testing.T) {
73134
gitDir := t.TempDir()
74135
restore := git.SetOps(&git.MockOps{

0 commit comments

Comments
 (0)