Skip to content

Commit 9415db1

Browse files
committed
fix: download contents
Fix google#3810. Fix google#2480. Signed-off-by: Leonard Sheng Sheng Lee <[email protected]>
1 parent 79cf23a commit 9415db1

1 file changed

Lines changed: 42 additions & 57 deletions

File tree

‎github/repos_contents.go‎

Lines changed: 42 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -97,54 +97,6 @@ func (r *RepositoryContent) GetContent() (string, error) {
9797
}
9898
}
9999

100-
// DownloadContent downloads the content of a file using the information from
101-
// the RepositoryContent. This method supports files of any size and works with
102-
// RepositoryContent entries obtained from GetContents calls on both individual
103-
// files and directories.
104-
//
105-
// It returns an io.ReadCloser for the file content and an *http.Response for
106-
// the download request (which may be nil if content was obtained without an
107-
// HTTP request). It is the caller's responsibility to close the ReadCloser.
108-
func (r *RepositoryContent) DownloadContent(ctx context.Context, httpClient *http.Client) (io.ReadCloser, *http.Response, error) {
109-
// Check if this is a file.
110-
if r.Type == nil || *r.Type != "file" {
111-
return nil, nil, fmt.Errorf("cannot download content for type %q (only files are supported)", r.GetType())
112-
}
113-
114-
// Handle empty files.
115-
if r.Size != nil && *r.Size == 0 {
116-
return io.NopCloser(strings.NewReader("")), nil, nil
117-
}
118-
119-
// Try to use the inline content if available.
120-
if r.Content != nil && *r.Content != "" {
121-
content, err := r.GetContent()
122-
if err == nil {
123-
return io.NopCloser(strings.NewReader(content)), nil, nil
124-
}
125-
// If GetContent fails (e.g., encoding "none"), fall through to use DownloadURL.
126-
}
127-
128-
// Use the download URL.
129-
if r.DownloadURL == nil || *r.DownloadURL == "" {
130-
return nil, nil, errors.New("no download URL available for this file")
131-
}
132-
133-
req, err := http.NewRequestWithContext(ctx, "GET", *r.DownloadURL, nil)
134-
if err != nil {
135-
return nil, nil, err
136-
}
137-
138-
resp, err := httpClient.Do(req)
139-
if err != nil {
140-
return nil, nil, err
141-
}
142-
143-
// Return the response body even for non-2xx status codes.
144-
// Callers should check resp.StatusCode to verify success.
145-
return resp.Body, resp, nil
146-
}
147-
148100
// GetReadme gets the Readme file for the repository.
149101
//
150102
// GitHub API docs: https://docs.github.com/rest/repos/contents#get-a-repository-readme
@@ -176,6 +128,9 @@ func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string,
176128
// to GetContents which is limited to 1 Mb files. It is the caller's
177129
// responsibility to close the ReadCloser.
178130
//
131+
// Note: If you need the file's metadata (name, SHA, URL, etc.) in addition to
132+
// its content, use DownloadContentsWithMeta instead.
133+
//
179134
// It is possible for the download to result in a failed response when the
180135
// returned error is nil. Callers should check the returned Response status
181136
// code to verify the content is from a successful response.
@@ -188,10 +143,14 @@ func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo,
188143
return reader, resp, err
189144
}
190145

191-
// DownloadContentsWithMeta is identical to DownloadContents but additionally
192-
// returns the RepositoryContent of the requested file. This additional data
193-
// is useful for future operations involving the requested file. For merely
194-
// reading the content of a file, DownloadContents is perfectly adequate.
146+
// DownloadContentsWithMeta returns both an io.ReadCloser for the file content
147+
// and the RepositoryContent metadata for the requested file. This function will
148+
// work with files of any size, as opposed to GetContents which is limited to 1 Mb
149+
// files. It is the caller's responsibility to close the ReadCloser.
150+
//
151+
// Use this method when you need access to the file's metadata (SHA, name, path,
152+
// URL, etc.) in addition to its content. If you only need the content, use
153+
// DownloadContents for a simpler API.
195154
//
196155
// It is possible for the download to result in a failed response when the
197156
// returned error is nil. Callers should check the returned Response status
@@ -209,17 +168,43 @@ func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owne
209168
return nil, nil, resp, fmt.Errorf("no file found at %v", filepath)
210169
}
211170

212-
reader, httpResp, err := fileContent.DownloadContent(ctx, s.client.client)
171+
// Check if this is a file.
172+
if fileContent.Type == nil || *fileContent.Type != "file" {
173+
return nil, nil, resp, fmt.Errorf("cannot download content for type %q (only files are supported)", fileContent.GetType())
174+
}
175+
176+
// Handle empty files.
177+
if fileContent.Size != nil && *fileContent.Size == 0 {
178+
return io.NopCloser(strings.NewReader("")), fileContent, resp, nil
179+
}
180+
181+
// Try to use the inline content if available.
182+
if fileContent.Content != nil && *fileContent.Content != "" {
183+
content, err := fileContent.GetContent()
184+
if err == nil {
185+
return io.NopCloser(strings.NewReader(content)), fileContent, resp, nil
186+
}
187+
// If GetContent fails (e.g., encoding "none"), fall through to use DownloadURL.
188+
}
189+
190+
// Use the download URL.
191+
if fileContent.DownloadURL == nil || *fileContent.DownloadURL == "" {
192+
return nil, fileContent, resp, errors.New("no download URL available for this file")
193+
}
194+
195+
req, err := http.NewRequestWithContext(ctx, "GET", *fileContent.DownloadURL, nil)
213196
if err != nil {
214197
return nil, fileContent, resp, err
215198
}
216199

217-
// If we got an HTTP response from the download, wrap it in a Response.
218-
if httpResp != nil {
219-
return reader, fileContent, &Response{Response: httpResp}, nil
200+
httpResp, err := s.client.client.Do(req)
201+
if err != nil {
202+
return nil, fileContent, resp, err
220203
}
221204

222-
return reader, fileContent, resp, nil
205+
// Return the response body even for non-2xx status codes.
206+
// Callers should check resp.StatusCode to verify success.
207+
return httpResp.Body, fileContent, &Response{Response: httpResp}, nil
223208
}
224209

225210
// GetContents can return either the metadata and content of a single file

0 commit comments

Comments
 (0)