@@ -1833,6 +1833,20 @@ func filterPaths(entries []*github.TreeEntry, path string, maxResults int) []str
18331833 return matchedPaths
18341834}
18351835
1836+ // looksLikeSHA returns true if the string appears to be a Git commit SHA.
1837+ // A SHA is a 40-character hexadecimal string.
1838+ func looksLikeSHA (s string ) bool {
1839+ if len (s ) != 40 {
1840+ return false
1841+ }
1842+ for _ , c := range s {
1843+ if (c < '0' || c > '9' ) && (c < 'a' || c > 'f' ) && (c < 'A' || c > 'F' ) {
1844+ return false
1845+ }
1846+ }
1847+ return true
1848+ }
1849+
18361850// resolveGitReference takes a user-provided ref and sha and resolves them into a
18371851// definitive commit SHA and its corresponding fully-qualified reference.
18381852//
@@ -1841,8 +1855,11 @@ func filterPaths(entries []*github.TreeEntry, path string, maxResults int) []str
18411855// 1. If a specific commit `sha` is provided, it takes precedence and is used directly,
18421856// and all reference resolution is skipped.
18431857//
1844- // 2. If no `sha` is provided, the function resolves the `ref`
1845- // string into a fully-qualified format (e.g., "refs/heads/main") by trying
1858+ // 1a. If `sha` is empty but `ref` looks like a commit SHA (7-40 hexadecimal characters),
1859+ // it is returned as-is without any API calls or reference resolution.
1860+ //
1861+ // 2. If no `sha` is provided and `ref` does not look like a SHA, the function resolves
1862+ // the `ref` string into a fully-qualified format (e.g., "refs/heads/main") by trying
18461863// the following steps in order:
18471864// a). **Empty Ref:** If `ref` is empty, the repository's default branch is used.
18481865// b). **Fully-Qualified:** If `ref` already starts with "refs/", it's considered fully
@@ -1865,6 +1882,11 @@ func resolveGitReference(ctx context.Context, githubClient *github.Client, owner
18651882 return & raw.ContentOpts {Ref : "" , SHA : sha }, nil
18661883 }
18671884
1885+ // 1a) If sha is empty but ref looks like a SHA, return it without changes
1886+ if sha == "" && looksLikeSHA (ref ) {
1887+ return & raw.ContentOpts {Ref : "" , SHA : ref }, nil
1888+ }
1889+
18681890 originalRef := ref // Keep original ref for clearer error messages down the line.
18691891
18701892 // 2) If no SHA is provided, we try to resolve the ref into a fully-qualified format.
@@ -1905,11 +1927,25 @@ func resolveGitReference(ctx context.Context, githubClient *github.Client, owner
19051927 // The tag lookup also failed. Check if it was a 404 Not Found error.
19061928 ghErr2 , isGhErr2 := err .(* github.ErrorResponse )
19071929 if isGhErr2 && ghErr2 .Response .StatusCode == http .StatusNotFound {
1908- return nil , fmt .Errorf ("could not resolve ref %q as a branch or a tag" , originalRef )
1930+ switch originalRef {
1931+ case "main" :
1932+ // Try "master" next.
1933+ branchRef = "refs/heads/master"
1934+ reference , resp , err = githubClient .Git .GetRef (ctx , owner , repo , branchRef )
1935+ if err == nil {
1936+ ref = branchRef // It's the "master" branch.
1937+ break
1938+ }
1939+ return nil , fmt .Errorf ("attempted to resolve ref %q as 'main' but not found, and 'master' also not found" , originalRef )
1940+ default :
1941+ return nil , fmt .Errorf ("could not resolve ref %q as a branch or a tag" , originalRef )
1942+ }
1943+ }
1944+ if err != nil {
1945+ // The tag lookup failed for a different reason.
1946+ _ , _ = ghErrors .NewGitHubAPIErrorToCtx (ctx , "failed to get reference (tag)" , resp , err )
1947+ return nil , fmt .Errorf ("failed to get reference for tag '%s': %w" , originalRef , err )
19091948 }
1910- // The tag lookup failed for a different reason.
1911- _ , _ = ghErrors .NewGitHubAPIErrorToCtx (ctx , "failed to get reference (tag)" , resp , err )
1912- return nil , fmt .Errorf ("failed to get reference for tag '%s': %w" , originalRef , err )
19131949 }
19141950 } else {
19151951 // The branch lookup failed for a different reason.
0 commit comments