Skip to content

Commit 9b47b89

Browse files
committed
Basic GitHub filesystem support
A gateway to proper filesystem builtins needed for #53.
1 parent 7f09285 commit 9b47b89

File tree

6 files changed

+130
-1
lines changed

6 files changed

+130
-1
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
github.com/go-test/deep v1.0.7
2020
github.com/gogo/protobuf v1.3.1 // indirect
2121
github.com/golang/protobuf v1.4.2
22+
github.com/google/go-github/v32 v32.1.0
2223
github.com/google/uuid v1.1.1
2324
github.com/gorilla/mux v1.7.4 // indirect
2425
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0

go.sum

+4
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
118118
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
119119
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
120120
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
121+
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
122+
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
123+
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
124+
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
121125
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
122126
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
123127
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=

pkg/larker/fs/fs.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package fs
22

3-
import "context"
3+
import (
4+
"context"
5+
)
46

57
type FileSystem interface {
68
Get(ctx context.Context, path string) ([]byte, error)

pkg/larker/fs/github/github.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"encoding/base64"
6+
"errors"
7+
"fmt"
8+
"github.com/google/go-github/v32/github"
9+
"syscall"
10+
)
11+
12+
var ErrAPI = errors.New("failed to communicate with the GitHub API")
13+
14+
type GitHub struct {
15+
client *github.Client
16+
owner string
17+
repo string
18+
reference string
19+
}
20+
21+
func New(owner, repo, reference, token string) *GitHub {
22+
return &GitHub{
23+
client: github.NewClient(nil),
24+
owner: owner,
25+
repo: repo,
26+
reference: reference,
27+
}
28+
}
29+
30+
func (gh *GitHub) Get(ctx context.Context, path string) ([]byte, error) {
31+
fileContent, _, _, err := gh.client.Repositories.GetContents(ctx, gh.owner, gh.repo, path,
32+
&github.RepositoryContentGetOptions{
33+
Ref: gh.reference,
34+
},
35+
)
36+
if err != nil {
37+
return nil, fmt.Errorf("%w: %v", ErrAPI, err)
38+
}
39+
40+
// Simulate os.Read() behavior in case the supplied path points to a directory
41+
if fileContent == nil {
42+
return nil, syscall.EISDIR
43+
}
44+
45+
fileBytes, err := base64.StdEncoding.DecodeString(*fileContent.Content)
46+
if err != nil {
47+
return nil, fmt.Errorf("%w: %v", ErrAPI, err)
48+
}
49+
50+
return fileBytes, nil
51+
}

pkg/larker/fs/github/github_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package github_test
2+
3+
import (
4+
"context"
5+
"errors"
6+
"github.com/cirruslabs/cirrus-cli/pkg/larker/fs"
7+
"github.com/cirruslabs/cirrus-cli/pkg/larker/fs/github"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
"syscall"
11+
"testing"
12+
)
13+
14+
func selfFS() fs.FileSystem {
15+
return github.New("cirruslabs", "cirrus-cli", "master", "")
16+
}
17+
18+
func TestGetFile(t *testing.T) {
19+
fileBytes, err := selfFS().Get(context.Background(), "go.mod")
20+
if err != nil {
21+
t.Fatal(err)
22+
}
23+
24+
assert.Contains(t, string(fileBytes), "module github.com/cirruslabs/cirrus-cli")
25+
}
26+
27+
func TestGetDirectory(t *testing.T) {
28+
_, err := selfFS().Get(context.Background(), ".")
29+
30+
require.Error(t, err)
31+
assert.True(t, errors.Is(err, syscall.EISDIR))
32+
}

pkg/larker/fs/local/local_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package local_test
2+
3+
import (
4+
"context"
5+
"errors"
6+
"github.com/cirruslabs/cirrus-cli/internal/testutil"
7+
"github.com/cirruslabs/cirrus-cli/pkg/larker/fs/local"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
"io/ioutil"
11+
"path/filepath"
12+
"syscall"
13+
"testing"
14+
)
15+
16+
func TestGetFile(t *testing.T) {
17+
// Prepare temporary directory
18+
dir := testutil.TempDir(t)
19+
if err := ioutil.WriteFile(filepath.Join(dir, "some-file.txt"), []byte("some-contents"), 0600); err != nil {
20+
t.Fatal(err)
21+
}
22+
23+
fileBytes, err := local.New(dir).Get(context.Background(), "some-file.txt")
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
28+
assert.Contains(t, string(fileBytes), "some-contents")
29+
}
30+
31+
func TestGetDirectory(t *testing.T) {
32+
// Prepare temporary directory
33+
dir := testutil.TempDir(t)
34+
35+
_, err := local.New(dir).Get(context.Background(), ".")
36+
37+
require.Error(t, err)
38+
assert.True(t, errors.Is(err, syscall.EISDIR))
39+
}

0 commit comments

Comments
 (0)