-
Notifications
You must be signed in to change notification settings - Fork 18
/
github.go
116 lines (95 loc) · 2.58 KB
/
github.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package github
import (
"context"
"encoding/base64"
"errors"
"fmt"
"github.com/cirruslabs/cirrus-cli/pkg/larker/fs"
"github.com/google/go-github/v32/github"
"golang.org/x/oauth2"
"net/http"
"os"
"syscall"
)
var ErrAPI = errors.New("failed to communicate with the GitHub API")
type GitHub struct {
token string
owner string
repo string
reference string
}
func New(owner, repo, reference, token string) *GitHub {
return &GitHub{
token: token,
owner: owner,
repo: repo,
reference: reference,
}
}
func (gh *GitHub) Stat(ctx context.Context, path string) (*fs.FileInfo, error) {
_, directoryContent, err := gh.getContentsWrapper(ctx, path)
if err != nil {
return nil, err
}
if directoryContent != nil {
return &fs.FileInfo{IsDir: true}, nil
}
return &fs.FileInfo{IsDir: false}, nil
}
func (gh *GitHub) Get(ctx context.Context, path string) ([]byte, error) {
fileContent, _, err := gh.getContentsWrapper(ctx, path)
if err != nil {
return nil, err
}
// Simulate os.Read() behavior in case the supplied path points to a directory
if fileContent == nil {
return nil, fs.ErrNormalizedIsADirectory
}
fileBytes, err := base64.StdEncoding.DecodeString(*fileContent.Content)
if err != nil {
return nil, fmt.Errorf("%w: %v", ErrAPI, err)
}
return fileBytes, nil
}
func (gh *GitHub) ReadDir(ctx context.Context, path string) ([]string, error) {
_, directoryContent, err := gh.getContentsWrapper(ctx, path)
if err != nil {
return nil, err
}
// Simulate ioutil.ReadDir() behavior in case the supplied path points to a file
if directoryContent == nil {
return nil, syscall.ENOTDIR
}
var entries []string
for _, fileContent := range directoryContent {
entries = append(entries, *fileContent.Name)
}
return entries, nil
}
func (gh *GitHub) client(ctx context.Context) *github.Client {
var client *http.Client
if gh.token != "" {
tokenSource := oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: gh.token,
})
client = oauth2.NewClient(ctx, tokenSource)
}
return github.NewClient(client)
}
func (gh *GitHub) getContentsWrapper(
ctx context.Context,
path string,
) (*github.RepositoryContent, []*github.RepositoryContent, error) {
fileContent, directoryContent, resp, err := gh.client(ctx).Repositories.GetContents(ctx, gh.owner, gh.repo, path,
&github.RepositoryContentGetOptions{
Ref: gh.reference,
},
)
if err != nil {
if resp != nil && resp.StatusCode == http.StatusNotFound {
return nil, nil, os.ErrNotExist
}
return nil, nil, fmt.Errorf("%w: %v", ErrAPI, err)
}
return fileContent, directoryContent, nil
}