Skip to content

Commit

Permalink
Feat: implemented gitee provider (#124)
Browse files Browse the repository at this point in the history
* Feat: implemented gitee provider (#1)
  • Loading branch information
kit101 authored Nov 18, 2021
1 parent 405c719 commit 7f0aaa8
Show file tree
Hide file tree
Showing 129 changed files with 16,173 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ func main() {
}
```

Create a Gitee client:

```Go
import (
"github.com/drone/go-scm/scm"
"github.com/drone/go-scm/scm/driver/gitee"
)

func main() {
client, err := gitee.New("https://gitee.com/api/v5")
}
```

## Authentication

The scm client does not directly handle authentication. Instead, when creating a new client, provide a `http.Client` that can handle authentication for you. For convenience, this library includes oauth1 and oauth2 implementations that can be used to authenticate requests.
Expand Down
3 changes: 3 additions & 0 deletions scm/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ const (
DriverBitbucket
DriverStash
DriverCoding
DriverGitee
)

// String returns the string representation of Driver.
Expand All @@ -140,6 +141,8 @@ func (d Driver) String() (s string) {
return "stash"
case DriverCoding:
return "coding"
case DriverGitee:
return "gitee"
default:
return "unknown"
}
Expand Down
142 changes: 142 additions & 0 deletions scm/driver/gitee/content.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Copyright 2017 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gitee

import (
"context"
"encoding/base64"
"fmt"

"github.com/drone/go-scm/scm"
)

type contentService struct {
client *wrapper
}

func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) {
endpoint := fmt.Sprintf("repos/%s/contents/%s?ref=%s", repo, path, ref)
out := new(content)
res, err := s.client.do(ctx, "GET", endpoint, nil, out)
raw, _ := base64.StdEncoding.DecodeString(out.Content)
return &scm.Content{
Path: out.Path,
Data: raw,
Sha: out.Sha,
}, res, err
}

func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path)
in := &contentCreateUpdate{
Message: params.Message,
Branch: params.Branch,
Content: params.Data,
Committer: commitAuthor{
Name: params.Signature.Name,
Email: params.Signature.Email,
},
Author: commitAuthor{
Name: params.Signature.Name,
Email: params.Signature.Email,
},
}

res, err := s.client.do(ctx, "POST", endpoint, in, nil)
return res, err
}

func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path)
in := &contentCreateUpdate{
Message: params.Message,
Branch: params.Branch,
Content: params.Data,
Sha: params.Sha,
Committer: commitAuthor{
Name: params.Signature.Name,
Email: params.Signature.Email,
},
Author: commitAuthor{
Name: params.Signature.Name,
Email: params.Signature.Email,
},
}
res, err := s.client.do(ctx, "PUT", endpoint, in, nil)
return res, err
}

func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path)
in := &contentCreateUpdate{
Message: params.Message,
Branch: params.Branch,
Sha: params.Sha,
Committer: commitAuthor{
Name: params.Signature.Name,
Email: params.Signature.Email,
},
Author: commitAuthor{
Name: params.Signature.Name,
Email: params.Signature.Email,
},
}
res, err := s.client.do(ctx, "DELETE", endpoint, in, nil)
return res, err
}

func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) {
endpoint := fmt.Sprintf("repos/%s/contents/%s?ref=%s", repo, path, ref)
out := []*content{}
res, err := s.client.do(ctx, "GET", endpoint, nil, &out)
return convertContentInfoList(out), res, err
}

type content struct {
Name string `json:"name"`
Path string `json:"path"`
Sha string `json:"sha"`
Content string `json:"content"`
Type string `json:"type"`
}

type contentCreateUpdate struct {
Branch string `json:"branch"`
Message string `json:"message"`
Content []byte `json:"content"`
Sha string `json:"sha"`
Author commitAuthor `json:"author"`
Committer commitAuthor `json:"committer"`
}

type commitAuthor struct {
Name string `json:"name"`
Date string `json:"date"`
Email string `json:"email"`
}

func convertContentInfoList(from []*content) []*scm.ContentInfo {
to := []*scm.ContentInfo{}
for _, v := range from {
to = append(to, convertContentInfo(v))
}
return to
}
func convertContentInfo(from *content) *scm.ContentInfo {
to := &scm.ContentInfo{Path: from.Path}
switch from.Type {
case "file":
to.Kind = scm.ContentKindFile
case "dir":
to.Kind = scm.ContentKindDirectory
case "symlink":
to.Kind = scm.ContentKindSymlink
case "submodule":
to.Kind = scm.ContentKindGitlink
default:
to.Kind = scm.ContentKindUnsupported
}
return to
}
200 changes: 200 additions & 0 deletions scm/driver/gitee/content_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// Copyright 2017 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gitee

import (
"context"
"encoding/json"
"io/ioutil"
"testing"

"github.com/drone/go-scm/scm"

"github.com/google/go-cmp/cmp"
"github.com/h2non/gock"
)

func TestContentFind(t *testing.T) {
defer gock.Off()

gock.New("https://gitee.com/api/v5").
Get("/repos/kit101/drone-yml-test/contents/README.md").
MatchParam("ref", "d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83").
Reply(200).
Type("application/json").
SetHeaders(mockHeaders).
File("testdata/content.json")

client := NewDefault()
got, res, err := client.Contents.Find(
context.Background(),
"kit101/drone-yml-test",
"README.md",
"d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83",
)
if err != nil {
t.Error(err)
return
}

want := new(scm.Content)
raw, _ := ioutil.ReadFile("testdata/content.json.golden")
json.Unmarshal(raw, want)

if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("Unexpected Results")
t.Log(diff)
}

t.Run("Request", testRequest(res))
}

func TestContentCreate(t *testing.T) {
defer gock.Off()

gock.New("https://gitee.com/api/v5").
Post("/repos/kit101/drone-yml-test/contents/apitest/CreateByDroneGiteeProvider.md").
Reply(201).
Type("application/json").
SetHeaders(mockHeaders).
File("testdata/content_create.json")

params := &scm.ContentParams{
Message: "my commit message",
Data: []byte("bY3JlYXRlIGJ5IGRyb25lLXNjbSBnaXRlZSBwcm92aWRlci4gMjAyMS0wOC0xNyAyMzowNToxNi4="),
Signature: scm.Signature{
Name: "kit101",
Email: "kit101@gitee.com",
},
}

client := NewDefault()
res, err := client.Contents.Create(
context.Background(),
"kit101/drone-yml-test",
"apitest/CreateByDroneGiteeProvider.md",
params,
)

if err != nil {
t.Error(err)
return
}

if res.Status != 201 {
t.Errorf("Unexpected Results")
}
}

func TestContentUpdate(t *testing.T) {
defer gock.Off()

gock.New("https://gitee.com/api/v5").
Put("/repos/kit101/drone-yml-test/contents/apitest/UpdateByDroneGiteeProvider.md").
Reply(200).
Type("application/json").
SetHeaders(mockHeaders).
File("testdata/content_update.json")

params := &scm.ContentParams{
Message: "my commit message by update",
Data: []byte("bdXBkYXRlIGJ5IGRyb25lLXNjbSBnaXRlZSBwcm92aWRlci4gMjAyMS0wOC0xNyAyMzozMDozNy4="),
Sha: "9de0cf94e1e3c1cbe0a25c3865de4cc9ede7ad3e",
Signature: scm.Signature{
Name: "kit101",
Email: "kit101@gitee.com",
},
}

client := NewDefault()
res, err := client.Contents.Update(
context.Background(),
"kit101/drone-yml-test",
"apitest/UpdateByDroneGiteeProvider.md",
params,
)

if err != nil {
t.Error(err)
return
}

if res.Status != 200 {
t.Errorf("Unexpected Results")
}
}

func TestContentDelete(t *testing.T) {
defer gock.Off()

gock.New("https://gitee.com/api/v5").
Delete("/repos/kit101/drone-yml-test/contents/apitest/DeleteByDroneGiteeProvider.md").
Reply(204).
Type("application/json").
SetHeaders(mockHeaders).
File("testdata/content_delete.json")

contentParams := scm.ContentParams{
Branch: "master",
Sha: "ae0653e4ab697cd77fc559cd798bdb30e8bb4d7e",
Message: "delete commit message",
Signature: scm.Signature{
Name: "kit101",
Email: "kit101@gitee.com",
},
}
client := NewDefault()
res, err := client.Contents.Delete(
context.Background(),
"kit101/drone-yml-test",
"apitest/DeleteByDroneGiteeProvider.md",
&contentParams,
)
if err != nil {
t.Error(err)
return
}

if got, want := res.Status, 204; got != want {
t.Errorf("Want response status %d, got %d", want, got)
}
t.Run("Request", testRequest(res))
}

func TestContentList(t *testing.T) {
defer gock.Off()

gock.New("https://gitee.com/api/v5").
Get("/repos/kit101/drone-yml-test/contents/apitest").
MatchParam("ref", "master").
Reply(200).
Type("application/json").
SetHeaders(mockHeaders).
File("testdata/content_list.json")

client := NewDefault()
got, res, err := client.Contents.List(
context.Background(),
"kit101/drone-yml-test",
"apitest",
"master",
scm.ListOptions{},
)
if err != nil {
t.Error(err)
return
}

want := []*scm.ContentInfo{}
raw, _ := ioutil.ReadFile("testdata/content_list.json.golden")
json.Unmarshal(raw, &want)

if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("Unexpected Results")
t.Log(diff)
}

t.Run("Request", testRequest(res))
}
Loading

0 comments on commit 7f0aaa8

Please sign in to comment.