MCPcopy Create free account
hub / github.com/cli/cli / fetchFile

Function fetchFile

pkg/cmd/repo/read-file/http.go:121–165  ·  view source on GitHub ↗

fetchFile retrieves a single path's metadata and inline content via the REST Contents API. It returns a typed error when the path is a directory, symlink, or submodule. Content is populated only when the API returns it inline; larger files come back with empty content, and it is up to the caller to

(httpClient *http.Client, repo ghrepo.Interface, filePath, ref string)

Source from the content-addressed store, hash-verified

119// it is up to the caller to fetch the raw bytes via fetchRawFile when the content is actually
120// needed.
121func fetchFile(httpClient *http.Client, repo ghrepo.Interface, filePath, ref string) (*repoFile, error) {
122 content, err := fetchContent(httpClient, repo, filePath, ref)
123 if err != nil {
124 return nil, err
125 }
126
127 if content.Type != "file" {
128 // The path resolved to something other than a regular file. Use content.Path
129 // (the API-sanitized path) rather than the user input in these messages, so a
130 // crafted path cannot smuggle terminal escape sequences into our output.
131 switch content.Type {
132 case "dir":
133 return nil, fmt.Errorf("path %q is a directory; use `gh repo read-dir` instead", content.Path)
134 case "symlink":
135 return nil, fmt.Errorf("path %q is a symlink to %q which does not exist", content.Path, content.Target)
136 case "submodule":
137 return nil, fmt.Errorf("path %q is a submodule (%s at %s)", content.Path, content.SubmoduleGitURL, content.SHA)
138 default:
139 return nil, fmt.Errorf("path %q is not a regular file (type: %s)", content.Path, content.Type)
140 }
141 }
142
143 file := &repoFile{
144 Name: content.Name,
145 Path: content.Path,
146 SHA: content.SHA,
147 Size: content.Size,
148 URL: content.URL,
149 HTMLURL: content.HTMLURL,
150 GitURL: content.GitURL,
151 DownloadURL: content.DownloadURL,
152 Type: content.Type,
153 Encoding: content.Encoding,
154 }
155
156 if content.Encoding == "base64" && content.Content != "" {
157 decoded, err := base64.StdEncoding.DecodeString(content.Content)
158 if err != nil {
159 return nil, fmt.Errorf("failed to decode base64 file content: %w", err)
160 }
161 file.Content = decoded
162 }
163
164 return file, nil
165}
166
167// fetchRawFile retrieves the raw bytes of a file, used for files larger than the
168// 1 MB inline content limit of the Contents API.

Callers 1

readFileRunFunction · 0.85

Calls 2

fetchContentFunction · 0.85
ErrorfMethod · 0.65

Tested by

no test coverage detected