Skip to content

Commit 887ea1d

Browse files
committed
fix: validate default branch exists before setting HEAD in List method
The List method was blindly setting HEAD to point to the configured default branch without verifying the branch actually exists. This caused "couldn't find remote ref" errors when cloning repositories with misconfigured default branches (e.g., pointing to non-existent "master" branch). Changes: - Add validation to check if configured default branch exists - Implement fallback logic: prefer "main" branch, then first available branch - Add warning logs when falling back to different branch - Handle edge case of repositories with no branches - Prevent fatal clone errors due to invalid HEAD references Fixes scenarios where repository default branch configuration points to non-existent branches, improving clone reliability and user experience.
1 parent faed7fa commit 887ea1d

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

cmd/git-remote-gitopia/gitopia.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,25 @@ func (h *GitopiaHandler) List(remote *core.Remote, forPush bool) ([]string, erro
122122
if err != nil {
123123
return out, err
124124
}
125+
126+
// Track available branches and find a suitable HEAD candidate
127+
var headCandidate string
128+
defaultBranchExists := false
129+
125130
for _, branch := range branchAllRes.Branch {
126131
out = append(out, fmt.Sprintf("%s %s%s", branch.Sha, branchPrefix, branch.Name))
132+
133+
// Check if the configured default branch exists
134+
if branch.Name == h.remoteRepository.DefaultBranch {
135+
defaultBranchExists = true
136+
headCandidate = branch.Name
137+
} else if headCandidate == "" {
138+
// Fallback: use the first branch we find
139+
headCandidate = branch.Name
140+
} else if branch.Name == "main" {
141+
// Prefer "main" over other branches as fallback
142+
headCandidate = branch.Name
143+
}
127144
}
128145

129146
tagAllRes, err := h.queryClient.RepositoryTagAll(context.Background(), &gitopiatypes.QueryAllRepositoryTagRequest{
@@ -140,7 +157,18 @@ func (h *GitopiaHandler) List(remote *core.Remote, forPush bool) ([]string, erro
140157
out = append(out, fmt.Sprintf("%s %s%s", tag.Sha, tagPrefix, tag.Name))
141158
}
142159

143-
out = append(out, fmt.Sprintf("@refs/heads/%s HEAD", h.remoteRepository.DefaultBranch))
160+
// Only set HEAD if we have a valid branch to point to
161+
if headCandidate != "" {
162+
if !defaultBranchExists && headCandidate != h.remoteRepository.DefaultBranch {
163+
// Log a warning if we're falling back to a different branch
164+
remote.Logger.Printf("Warning: configured default branch '%s' doesn't exist, using '%s' as HEAD\n",
165+
h.remoteRepository.DefaultBranch, headCandidate)
166+
}
167+
out = append(out, fmt.Sprintf("@refs/heads/%s HEAD", headCandidate))
168+
} else {
169+
// No branches exist at all - this is a serious issue
170+
remote.Logger.Printf("Warning: repository has no branches, HEAD will not be set\n")
171+
}
144172

145173
return out, nil
146174
}
@@ -152,7 +180,7 @@ func (h *GitopiaHandler) Fetch(remote *core.Remote, refsToFetch []core.RefToFetc
152180
// Check if any refs need force
153181
needsForce := false
154182
var processedRefs []string
155-
183+
156184
for _, ref := range refsToFetch {
157185
refSpec := ref.Ref
158186
if strings.HasPrefix(refSpec, "+") {
@@ -168,12 +196,12 @@ func (h *GitopiaHandler) Fetch(remote *core.Remote, refsToFetch []core.RefToFetc
168196
"fetch",
169197
"--no-write-fetch-head",
170198
}
171-
199+
172200
// Add force flag if any ref needs it
173201
if needsForce || remote.Force {
174202
args = append(args, "--force")
175203
}
176-
204+
177205
args = append(args, remoteURL)
178206
args = append(args, processedRefs...)
179207

0 commit comments

Comments
 (0)