Skip to content

Commit d436b52

Browse files
authored
Improve DownloadContents and DownloadContentsWithMeta methods (#3573)
1 parent ef319d5 commit d436b52

File tree

2 files changed

+194
-22
lines changed

2 files changed

+194
-22
lines changed

github/repos_contents.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,24 @@ func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string,
139139
func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *Response, error) {
140140
dir := path.Dir(filepath)
141141
filename := path.Base(filepath)
142+
fileContent, _, resp, err := s.GetContents(ctx, owner, repo, filepath, opts)
143+
if err == nil && fileContent != nil {
144+
content, err := fileContent.GetContent()
145+
if err == nil && content != "" {
146+
return io.NopCloser(strings.NewReader(content)), resp, nil
147+
}
148+
}
149+
142150
_, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts)
143151
if err != nil {
144152
return nil, resp, err
145153
}
146154

147155
for _, contents := range dirContents {
148-
if *contents.Name == filename {
149-
if contents.DownloadURL == nil || *contents.DownloadURL == "" {
156+
if contents.GetName() == filename {
157+
if contents.GetDownloadURL() == "" {
150158
return nil, resp, fmt.Errorf("no download link found for %s", filepath)
151159
}
152-
153160
dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil)
154161
if err != nil {
155162
return nil, resp, err
@@ -181,17 +188,24 @@ func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo,
181188
func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *RepositoryContent, *Response, error) {
182189
dir := path.Dir(filepath)
183190
filename := path.Base(filepath)
191+
fileContent, _, resp, err := s.GetContents(ctx, owner, repo, filepath, opts)
192+
if err == nil && fileContent != nil {
193+
content, err := fileContent.GetContent()
194+
if err == nil && content != "" {
195+
return io.NopCloser(strings.NewReader(content)), fileContent, resp, nil
196+
}
197+
}
198+
184199
_, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts)
185200
if err != nil {
186201
return nil, nil, resp, err
187202
}
188203

189204
for _, contents := range dirContents {
190-
if *contents.Name == filename {
191-
if contents.DownloadURL == nil || *contents.DownloadURL == "" {
205+
if contents.GetName() == filename {
206+
if contents.GetDownloadURL() == "" {
192207
return nil, contents, resp, fmt.Errorf("no download link found for %s", filepath)
193208
}
194-
195209
dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil)
196210
if err != nil {
197211
return nil, contents, resp, err

github/repos_contents_test.go

Lines changed: 174 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,66 @@ func TestRepositoriesService_GetReadme(t *testing.T) {
127127
})
128128
}
129129

130-
func TestRepositoriesService_DownloadContents_Success(t *testing.T) {
130+
func TestRepositoriesService_DownloadContents_SuccessForFile(t *testing.T) {
131131
t.Parallel()
132132
client, mux, serverURL := setup(t)
133133

134+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
135+
testMethod(t, r, "GET")
136+
fmt.Fprint(w, `{
137+
"type": "file",
138+
"name": "f",
139+
"content": "foo",
140+
"download_url": "`+serverURL+baseURLPath+`/download/f"
141+
}`)
142+
})
143+
144+
ctx := context.Background()
145+
r, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
146+
if err != nil {
147+
t.Errorf("Repositories.DownloadContents returned error: %v", err)
148+
}
149+
150+
if got, want := resp.Response.StatusCode, http.StatusOK; got != want {
151+
t.Errorf("Repositories.DownloadContents returned status code %v, want %v", got, want)
152+
}
153+
154+
bytes, err := io.ReadAll(r)
155+
if err != nil {
156+
t.Errorf("Error reading response body: %v", err)
157+
}
158+
r.Close()
159+
160+
if got, want := string(bytes), "foo"; got != want {
161+
t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want)
162+
}
163+
164+
const methodName = "DownloadContents"
165+
testBadOptions(t, methodName, func() (err error) {
166+
_, _, err = client.Repositories.DownloadContents(ctx, "\n", "\n", "\n", nil)
167+
return err
168+
})
169+
170+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
171+
got, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
172+
if got != nil {
173+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
174+
}
175+
return resp, err
176+
})
177+
}
178+
179+
func TestRepositoriesService_DownloadContents_SuccessForDirectory(t *testing.T) {
180+
t.Parallel()
181+
client, mux, serverURL := setup(t)
182+
183+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
184+
testMethod(t, r, "GET")
185+
fmt.Fprint(w, `{
186+
"type": "file",
187+
"name": "f"
188+
}`)
189+
})
134190
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
135191
testMethod(t, r, "GET")
136192
fmt.Fprint(w, `[{
@@ -183,6 +239,13 @@ func TestRepositoriesService_DownloadContents_FailedResponse(t *testing.T) {
183239
t.Parallel()
184240
client, mux, serverURL := setup(t)
185241

242+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
243+
testMethod(t, r, "GET")
244+
fmt.Fprint(w, `{
245+
"type": "file",
246+
"name": "f"
247+
}`)
248+
})
186249
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
187250
testMethod(t, r, "GET")
188251
fmt.Fprint(w, `[{
@@ -222,60 +285,83 @@ func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) {
222285
t.Parallel()
223286
client, mux, _ := setup(t)
224287

288+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
289+
testMethod(t, r, "GET")
290+
fmt.Fprint(w, `{
291+
"type": "file",
292+
"name": "f",
293+
"content": ""
294+
}`)
295+
})
225296
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
226297
testMethod(t, r, "GET")
227298
fmt.Fprint(w, `[{
228299
"type": "file",
229300
"name": "f",
301+
"content": ""
230302
}]`)
231303
})
232304

233305
ctx := context.Background()
234-
_, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
306+
reader, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
235307
if err == nil {
236308
t.Errorf("Repositories.DownloadContents did not return expected error")
237309
}
238310

239311
if resp == nil {
240312
t.Errorf("Repositories.DownloadContents did not return expected response")
241313
}
314+
315+
if reader != nil {
316+
t.Errorf("Repositories.DownloadContents did not return expected reader")
317+
}
242318
}
243319

244320
func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) {
245321
t.Parallel()
246322
client, mux, _ := setup(t)
247323

324+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
325+
testMethod(t, r, "GET")
326+
fmt.Fprint(w, `{
327+
"type": "file",
328+
"name": "f",
329+
"content": ""
330+
}`)
331+
})
332+
248333
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
249334
testMethod(t, r, "GET")
250335
fmt.Fprint(w, `[]`)
251336
})
252337

253338
ctx := context.Background()
254-
_, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
339+
reader, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
255340
if err == nil {
256341
t.Errorf("Repositories.DownloadContents did not return expected error")
257342
}
258343

259344
if resp == nil {
260345
t.Errorf("Repositories.DownloadContents did not return expected response")
261346
}
347+
348+
if reader != nil {
349+
t.Errorf("Repositories.DownloadContents did not return expected reader")
350+
}
262351
}
263352

264-
func TestRepositoriesService_DownloadContentsWithMeta_Success(t *testing.T) {
353+
func TestRepositoriesService_DownloadContentsWithMeta_SuccessForFile(t *testing.T) {
265354
t.Parallel()
266355
client, mux, serverURL := setup(t)
267356

268-
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
357+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
269358
testMethod(t, r, "GET")
270-
fmt.Fprint(w, `[{
359+
fmt.Fprint(w, `{
271360
"type": "file",
272361
"name": "f",
273-
"download_url": "`+serverURL+baseURLPath+`/download/f"
274-
}]`)
275-
})
276-
mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
277-
testMethod(t, r, "GET")
278-
fmt.Fprint(w, "foo")
362+
"download_url": "`+serverURL+baseURLPath+`/download/f",
363+
"content": "foo"
364+
}`)
279365
})
280366

281367
ctx := context.Background()
@@ -324,23 +410,79 @@ func TestRepositoriesService_DownloadContentsWithMeta_Success(t *testing.T) {
324410
})
325411
}
326412

327-
func TestRepositoriesService_DownloadContentsWithMeta_FailedResponse(t *testing.T) {
413+
func TestRepositoriesService_DownloadContentsWithMeta_SuccessForDirectory(t *testing.T) {
328414
t.Parallel()
329415
client, mux, serverURL := setup(t)
330416

331417
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
332418
testMethod(t, r, "GET")
333419
fmt.Fprint(w, `[{
420+
"type": "file",
421+
"name": "f",
422+
"download_url": "`+serverURL+baseURLPath+`/download/f"
423+
}]`)
424+
})
425+
mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
426+
testMethod(t, r, "GET")
427+
fmt.Fprint(w, "foo")
428+
})
429+
430+
ctx := context.Background()
431+
r, c, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
432+
if err != nil {
433+
t.Errorf("Repositories.DownloadContentsWithMeta returned error: %v", err)
434+
}
435+
436+
if got, want := resp.Response.StatusCode, http.StatusOK; got != want {
437+
t.Errorf("Repositories.DownloadContentsWithMeta returned status code %v, want %v", got, want)
438+
}
439+
440+
bytes, err := io.ReadAll(r)
441+
if err != nil {
442+
t.Errorf("Error reading response body: %v", err)
443+
}
444+
r.Close()
445+
446+
if got, want := string(bytes), "foo"; got != want {
447+
t.Errorf("Repositories.DownloadContentsWithMeta returned %v, want %v", got, want)
448+
}
449+
450+
if c != nil && c.Name != nil {
451+
if got, want := *c.Name, "f"; got != want {
452+
t.Errorf("Repositories.DownloadContentsWithMeta returned content name %v, want %v", got, want)
453+
}
454+
} else {
455+
t.Errorf("Returned RepositoryContent is null")
456+
}
457+
}
458+
459+
func TestRepositoriesService_DownloadContentsWithMeta_FailedResponse(t *testing.T) {
460+
t.Parallel()
461+
client, mux, serverURL := setup(t)
462+
463+
downloadURL := fmt.Sprintf("%s%s/download/f", serverURL, baseURLPath)
464+
465+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
466+
testMethod(t, r, "GET")
467+
fmt.Fprint(w, `{
334468
"type": "file",
335469
"name": "f",
336-
"download_url": "`+serverURL+baseURLPath+`/download/f"
337-
}]`)
470+
"download_url": "`+downloadURL+`"
471+
}`)
338472
})
339473
mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
340474
testMethod(t, r, "GET")
341475
w.WriteHeader(http.StatusInternalServerError)
342476
fmt.Fprint(w, "foo error")
343477
})
478+
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
479+
testMethod(t, r, "GET")
480+
fmt.Fprint(w, `[{
481+
"type": "file",
482+
"name": "f",
483+
"download_url": "`+downloadURL+`"
484+
}]`)
485+
})
344486

345487
ctx := context.Background()
346488
r, c, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
@@ -375,23 +517,39 @@ func TestRepositoriesService_DownloadContentsWithMeta_NoDownloadURL(t *testing.T
375517
t.Parallel()
376518
client, mux, _ := setup(t)
377519

520+
mux.HandleFunc("/repos/o/r/contents/d/f", func(w http.ResponseWriter, r *http.Request) {
521+
testMethod(t, r, "GET")
522+
fmt.Fprint(w, `{
523+
"type": "file",
524+
"name": "f",
525+
}`)
526+
})
378527
mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
379528
testMethod(t, r, "GET")
380529
fmt.Fprint(w, `[{
381530
"type": "file",
382531
"name": "f",
532+
"content": ""
383533
}]`)
384534
})
385535

386536
ctx := context.Background()
387-
_, _, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
537+
reader, contents, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
388538
if err == nil {
389539
t.Errorf("Repositories.DownloadContentsWithMeta did not return expected error")
390540
}
391541

542+
if reader != nil {
543+
t.Errorf("Repositories.DownloadContentsWithMeta did not return expected reader")
544+
}
545+
392546
if resp == nil {
393547
t.Errorf("Repositories.DownloadContentsWithMeta did not return expected response")
394548
}
549+
550+
if contents == nil {
551+
t.Errorf("Repositories.DownloadContentsWithMeta did not return expected content")
552+
}
395553
}
396554

397555
func TestRepositoriesService_DownloadContentsWithMeta_NoFile(t *testing.T) {

0 commit comments

Comments
 (0)