You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-scm/scm/driver/gitea/repo.go

318 lines
8.5 KiB
Go

// 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 gitea
import (
"context"
"fmt"
"net/url"
"strconv"
"time"
"git.awesome-for.me/liuzhiguo/go-scm/scm"
)
type repositoryService struct {
client *wrapper
}
func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s", repo)
out := new(repository)
res, err := s.client.do(ctx, "GET", path, nil, out)
return convertRepository(out), res, err
}
func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s/hooks/%s", repo, id)
out := new(hook)
res, err := s.client.do(ctx, "GET", path, nil, out)
return convertHook(out), res, err
}
func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s", repo)
out := new(repository)
res, err := s.client.do(ctx, "GET", path, nil, out)
return convertRepository(out).Perm, res, err
}
func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
path := fmt.Sprintf("api/v1/user/repos?%s", encodeListOptions(opts))
out := []*repository{}
res, err := s.client.do(ctx, "GET", path, nil, &out)
return convertRepositoryList(out), res, err
}
func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) {
// gitea does not support search filters, hence calling List api without search filtering
return s.List(ctx, opts.ListOptions)
}
func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s/hooks?%s", repo, encodeListOptions(opts))
out := []*hook{}
res, err := s.client.do(ctx, "GET", path, nil, &out)
return convertHookList(out), res, err
}
func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s/statuses/%s?%s", repo, ref, encodeListOptions(opts))
out := []*status{}
res, err := s.client.do(ctx, "GET", path, nil, &out)
return convertStatusList(out), res, err
}
func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
target, err := url.Parse(input.Target)
if err != nil {
return nil, nil, err
}
params := target.Query()
params.Set("secret", input.Secret)
target.RawQuery = params.Encode()
path := fmt.Sprintf("api/v1/repos/%s/hooks", repo)
in := new(hook)
in.Type = "gitea"
in.Active = true
in.Config.Secret = input.Secret
in.Config.ContentType = "json"
in.Config.URL = target.String()
in.Events = append(
input.NativeEvents,
convertHookEvent(input.Events)...,
)
out := new(hook)
res, err := s.client.do(ctx, "POST", path, in, out)
return convertHook(out), res, err
}
func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s/statuses/%s", repo, ref)
in := &statusInput{
State: convertFromState(input.State),
Context: input.Label,
Description: input.Desc,
TargetURL: input.Target,
}
out := new(status)
res, err := s.client.do(ctx, "POST", path, in, out)
return convertStatus(out), res, err
}
func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
target, err := url.Parse(input.Target)
if err != nil {
return nil, nil, err
}
params := target.Query()
params.Set("secret", input.Secret)
target.RawQuery = params.Encode()
path := fmt.Sprintf("api/v1/repos/%s/hooks/%s", repo, id)
in := new(hook)
in.Type = "gitea"
in.Active = true
in.Config.Secret = input.Secret
in.Config.ContentType = "json"
in.Config.URL = target.String()
in.Events = append(
input.NativeEvents,
convertHookEvent(input.Events)...,
)
out := new(hook)
res, err := s.client.do(ctx, "PATCH", path, in, out)
return convertHook(out), res, err
}
func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) {
path := fmt.Sprintf("api/v1/repos/%s/hooks/%s", repo, id)
return s.client.do(ctx, "DELETE", path, nil, nil)
}
//
// native data structures
//
type (
// gitea repository resource.
repository struct {
ID int `json:"id"`
Owner user `json:"owner"`
Name string `json:"name"`
FullName string `json:"full_name"`
Private bool `json:"private"`
Fork bool `json:"fork"`
HTMLURL string `json:"html_url"`
SSHURL string `json:"ssh_url"`
CloneURL string `json:"clone_url"`
DefaultBranch string `json:"default_branch"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Permissions perm `json:"permissions"`
Archived bool `json:"archived"`
}
// gitea permissions details.
perm struct {
Admin bool `json:"admin"`
Push bool `json:"push"`
Pull bool `json:"pull"`
}
// gitea hook resource.
hook struct {
ID int `json:"id"`
Type string `json:"type"`
Events []string `json:"events"`
Active bool `json:"active"`
Config hookConfig `json:"config"`
}
// gitea hook configuration details.
hookConfig struct {
URL string `json:"url"`
ContentType string `json:"content_type"`
Secret string `json:"secret"`
}
// gitea status resource.
status struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
State string `json:"status"`
TargetURL string `json:"target_url"`
Description string `json:"description"`
Context string `json:"context"`
}
// gitea status creation request.
statusInput struct {
State string `json:"state"`
TargetURL string `json:"target_url"`
Description string `json:"description"`
Context string `json:"context"`
}
)
//
// native data structure conversion
//
func convertRepositoryList(src []*repository) []*scm.Repository {
var dst []*scm.Repository
for _, v := range src {
dst = append(dst, convertRepository(v))
}
return dst
}
func convertRepository(src *repository) *scm.Repository {
return &scm.Repository{
ID: strconv.Itoa(src.ID),
Namespace: userLogin(&src.Owner),
Name: src.Name,
Perm: convertPerm(src.Permissions),
Branch: src.DefaultBranch,
Private: src.Private,
Clone: src.CloneURL,
CloneSSH: src.SSHURL,
Link: src.HTMLURL,
Archived: src.Archived,
}
}
func convertPerm(src perm) *scm.Perm {
return &scm.Perm{
Push: src.Push,
Pull: src.Pull,
Admin: src.Admin,
}
}
func convertHookList(src []*hook) []*scm.Hook {
var dst []*scm.Hook
for _, v := range src {
dst = append(dst, convertHook(v))
}
return dst
}
func convertHook(from *hook) *scm.Hook {
return &scm.Hook{
ID: strconv.Itoa(from.ID),
Active: from.Active,
Target: from.Config.URL,
Events: from.Events,
}
}
func convertHookEvent(from scm.HookEvents) []string {
var events []string
if from.PullRequest {
events = append(events, "pull_request")
}
if from.Issue {
events = append(events, "issues")
}
if from.IssueComment || from.PullRequestComment {
events = append(events, "issue_comment")
}
if from.Branch || from.Tag {
events = append(events, "create")
events = append(events, "delete")
}
if from.Push {
events = append(events, "push")
}
return events
}
func convertStatusList(src []*status) []*scm.Status {
var dst []*scm.Status
for _, v := range src {
dst = append(dst, convertStatus(v))
}
return dst
}
func convertStatus(from *status) *scm.Status {
return &scm.Status{
State: convertState(from.State),
Label: from.Context,
Desc: from.Description,
Target: from.TargetURL,
}
}
func convertState(from string) scm.State {
switch from {
case "error":
return scm.StateError
case "failure":
return scm.StateFailure
case "pending":
return scm.StatePending
case "success":
return scm.StateSuccess
default:
return scm.StateUnknown
}
}
func convertFromState(from scm.State) string {
switch from {
case scm.StatePending, scm.StateRunning:
return "pending"
case scm.StateSuccess:
return "success"
case scm.StateFailure:
return "failure"
default:
return "error"
}
}