MCPcopy
hub / github.com/github/github-mcp-server / resolveGitReference

Function resolveGitReference

pkg/github/repositories_helper.go:207–303  ·  view source on GitHub ↗

resolveGitReference takes a user-provided ref and sha and resolves them into a definitive commit SHA and its corresponding fully-qualified reference. The resolution logic follows a clear priority: 1. If a specific commit `sha` is provided, it takes precedence and is used directly, and all referenc

(ctx context.Context, githubClient *github.Client, owner, repo, ref, sha string)

Source from the content-addressed store, hash-verified

205// Any unexpected (non-404) errors during the resolution process are returned
206// immediately. All API errors are logged with rich context to aid diagnostics.
207func resolveGitReference(ctx context.Context, githubClient *github.Client, owner, repo, ref, sha string) (*raw.ContentOpts, bool, error) {
208 // 1) If SHA explicitly provided, it's the highest priority.
209 if sha != "" {
210 return &raw.ContentOpts{Ref: "", SHA: sha}, false, nil
211 }
212
213 // 1a) If sha is empty but ref looks like a SHA, return it without changes
214 if looksLikeSHA(ref) {
215 return &raw.ContentOpts{Ref: "", SHA: ref}, false, nil
216 }
217
218 originalRef := ref // Keep original ref for clearer error messages down the line.
219
220 // 2) If no SHA is provided, we try to resolve the ref into a fully-qualified format.
221 var reference *github.Reference
222 var resp *github.Response
223 var err error
224 var fallbackUsed bool
225
226 switch {
227 case originalRef == "":
228 // 2a) If ref is empty, determine the default branch.
229 reference, err = resolveDefaultBranch(ctx, githubClient, owner, repo)
230 if err != nil {
231 return nil, false, err // Error is already wrapped in resolveDefaultBranch.
232 }
233 ref = reference.GetRef()
234 case strings.HasPrefix(originalRef, "refs/"):
235 // 2b) Already fully qualified. The reference will be fetched at the end.
236 case strings.HasPrefix(originalRef, "heads/") || strings.HasPrefix(originalRef, "tags/"):
237 // 2c) Partially qualified. Make it fully qualified.
238 ref = "refs/" + originalRef
239 default:
240 // 2d) It's a short name, so we try to resolve it to either a branch or a tag.
241 branchRef := "refs/heads/" + originalRef
242 reference, resp, err = githubClient.Git.GetRef(ctx, owner, repo, branchRef)
243
244 if err == nil {
245 ref = branchRef // It's a branch.
246 } else {
247 // The branch lookup failed. Check if it was a 404 Not Found error.
248 ghErr, isGhErr := err.(*github.ErrorResponse)
249 if isGhErr && ghErr.Response.StatusCode == http.StatusNotFound {
250 tagRef := "refs/tags/" + originalRef
251 reference, resp, err = githubClient.Git.GetRef(ctx, owner, repo, tagRef)
252 if err == nil {
253 ref = tagRef // It's a tag.
254 } else {
255 // The tag lookup also failed. Check if it was a 404 Not Found error.
256 ghErr2, isGhErr2 := err.(*github.ErrorResponse)
257 if isGhErr2 && ghErr2.Response.StatusCode == http.StatusNotFound {
258 if originalRef == "main" {
259 reference, err = resolveDefaultBranch(ctx, githubClient, owner, repo)
260 if err != nil {
261 return nil, false, err // Error is already wrapped in resolveDefaultBranch.
262 }
263 // Update ref to the actual default branch ref so the note can be generated
264 ref = reference.GetRef()

Callers 2

GetFileContentsFunction · 0.85
Test_resolveGitReferenceFunction · 0.85

Calls 2

looksLikeSHAFunction · 0.85
resolveDefaultBranchFunction · 0.85

Tested by 1

Test_resolveGitReferenceFunction · 0.68