1 package ghfs
2
3 import (
4 "context"
5 "fmt"
6 "io"
7 "io/fs"
8
9 "github.com/google/go-github/v47/github"
10 )
11
12
13
14 type fetcher interface {
15 getContents(name string) (*github.RepositoryContent, []*github.RepositoryContent, error)
16 downloadContents(c *github.RepositoryContent) (io.ReadCloser, error)
17 }
18
19
20 type ghFetcher struct {
21 gh *github.Client
22 ctx context.Context
23 owner, repo, ref string
24 }
25
26 func (f *ghFetcher) getContents(name string) (
27 *github.RepositoryContent, []*github.RepositoryContent, error,
28 ) {
29 file, dir, res, err := f.gh.Repositories.GetContents(
30 f.ctx,
31 f.owner,
32 f.repo,
33 name,
34 &github.RepositoryContentGetOptions{Ref: f.ref},
35 )
36
37 if err := f.responseToErr(name, res, err); err != nil {
38 return nil, nil, err
39 }
40
41 return file, dir, nil
42 }
43
44 func (f *ghFetcher) downloadContents(file *github.RepositoryContent) (io.ReadCloser, error) {
45 if file.GetDownloadURL() == "" {
46 return nil, fmt.Errorf("unexpected state: file has no download URL")
47 }
48 dlRes, err := f.gh.Client().Get(file.GetDownloadURL())
49 if err := f.responseToErr(file.GetPath(), &github.Response{Response: dlRes}, err); err != nil {
50 return nil, err
51 }
52 return dlRes.Body, nil
53 }
54
55
56
57 func (f *ghFetcher) responseToErr(name string, res *github.Response, err error) error {
58
59
60 switch {
61 case res.StatusCode == 404:
62 return fmt.Errorf("%w: %s not found in %s/%s@%s",
63 fs.ErrNotExist, name, f.owner, f.repo, f.ref)
64 case res.StatusCode == 403:
65 return fmt.Errorf("%w: failed to retrieve %s from %s/%s@%s",
66 fs.ErrPermission, name, f.owner, f.repo, f.ref)
67 case err != nil:
68 return fmt.Errorf("failed to retrieve %s from %s/%s@%s: %w",
69 name, f.owner, f.repo, f.ref, err)
70 default:
71 return nil
72 }
73 }
74
View as plain text