Merge pull request #2017 from appleboy/gitea

feat: add gitea remote driver.
This commit is contained in:
Brad Rydzewski 2017-05-24 12:37:45 +02:00 committed by GitHub
commit 85c86272c1
44 changed files with 3887 additions and 1 deletions

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"net/http" "net/http"
"net/url" "net/url"
"strings"
"time" "time"
"golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/acme/autocert"
@ -225,6 +226,37 @@ var Command = cli.Command{
Name: "gogs-skip-verify", Name: "gogs-skip-verify",
Usage: "gogs skip ssl verification", Usage: "gogs skip ssl verification",
}, },
cli.BoolFlag{
EnvVar: "DRONE_GITEA",
Name: "gitea",
Usage: "gitea driver is enabled",
},
cli.StringFlag{
EnvVar: "DRONE_GITEA_URL",
Name: "gitea-server",
Usage: "gitea server address",
Value: "https://try.gitea.io",
},
cli.StringFlag{
EnvVar: "DRONE_GITEA_GIT_USERNAME",
Name: "gitea-git-username",
Usage: "gitea service account username",
},
cli.StringFlag{
EnvVar: "DRONE_GITEA_GIT_PASSWORD",
Name: "gitea-git-password",
Usage: "gitea service account password",
},
cli.BoolFlag{
EnvVar: "DRONE_GITEA_PRIVATE_MODE",
Name: "gitea-private-mode",
Usage: "gitea private mode enabled",
},
cli.BoolFlag{
EnvVar: "DRONE_GITEA_SKIP_VERIFY",
Name: "gitea-skip-verify",
Usage: "gitea skip ssl verification",
},
cli.BoolFlag{ cli.BoolFlag{
EnvVar: "DRONE_BITBUCKET", EnvVar: "DRONE_BITBUCKET",
Name: "bitbucket", Name: "bitbucket",
@ -415,7 +447,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store) {
droneserver.Config.Server.Cert = c.String("server-cert") droneserver.Config.Server.Cert = c.String("server-cert")
droneserver.Config.Server.Key = c.String("server-key") droneserver.Config.Server.Key = c.String("server-key")
droneserver.Config.Server.Pass = c.String("agent-secret") droneserver.Config.Server.Pass = c.String("agent-secret")
droneserver.Config.Server.Host = c.String("server-host") droneserver.Config.Server.Host = strings.TrimRight(c.String("server-host"), "/")
droneserver.Config.Server.Port = c.String("server-addr") droneserver.Config.Server.Port = c.String("server-addr")
droneserver.Config.Pipeline.Networks = c.StringSlice("network") droneserver.Config.Pipeline.Networks = c.StringSlice("network")
droneserver.Config.Pipeline.Volumes = c.StringSlice("volume") droneserver.Config.Pipeline.Volumes = c.StringSlice("volume")

View file

@ -0,0 +1,141 @@
package fixtures
import (
"net/http"
"github.com/gin-gonic/gin"
)
// Handler returns an http.Handler that is capable of handling a variety of mock
// Gitea requests and returning mock responses.
func Handler() http.Handler {
gin.SetMode(gin.TestMode)
e := gin.New()
e.GET("/api/v1/repos/:owner/:name", getRepo)
e.GET("/api/v1/repos/:owner/:name/raw/:commit/:file", getRepoFile)
e.POST("/api/v1/repos/:owner/:name/hooks", createRepoHook)
e.GET("/api/v1/repos/:owner/:name/hooks", listRepoHooks)
e.DELETE("/api/v1/repos/:owner/:name/hooks/:id", deleteRepoHook)
e.POST("/api/v1/repos/:owner/:name/statuses/:commit", createRepoCommitStatus)
e.GET("/api/v1/user/repos", getUserRepos)
return e
}
func listRepoHooks(c *gin.Context) {
c.String(200, listRepoHookPayloads)
}
func getRepo(c *gin.Context) {
switch c.Param("name") {
case "repo_not_found":
c.String(404, "")
default:
c.String(200, repoPayload)
}
}
func createRepoCommitStatus(c *gin.Context) {
if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
c.String(200, repoPayload)
}
c.String(404, "")
}
func getRepoFile(c *gin.Context) {
if c.Param("file") == "file_not_found" {
c.String(404, "")
}
if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
c.String(200, repoFilePayload)
}
c.String(404, "")
}
func createRepoHook(c *gin.Context) {
in := struct {
Type string `json:"type"`
Conf struct {
Type string `json:"content_type"`
URL string `json:"url"`
} `json:"config"`
}{}
c.BindJSON(&in)
if in.Type != "gitea" ||
in.Conf.Type != "json" ||
in.Conf.URL != "http://localhost" {
c.String(500, "")
return
}
c.String(200, "{}")
}
func deleteRepoHook(c *gin.Context) {
c.String(200, "{}")
}
func getUserRepos(c *gin.Context) {
switch c.Request.Header.Get("Authorization") {
case "token repos_not_found":
c.String(404, "")
default:
c.String(200, userRepoPayload)
}
}
const listRepoHookPayloads = `
[
{
"id": 1,
"type": "gitea",
"config": {
"content_type": "json",
"url": "http:\/\/localhost\/hook?access_token=1234567890"
}
}
]
`
const repoPayload = `
{
"owner": {
"login": "test_name",
"email": "octocat@github.com",
"avatar_url": "https:\/\/secure.gravatar.com\/avatar\/8c58a0be77ee441bb8f8595b7f1b4e87"
},
"full_name": "test_name\/repo_name",
"private": true,
"html_url": "http:\/\/localhost\/test_name\/repo_name",
"clone_url": "http:\/\/localhost\/test_name\/repo_name.git",
"permissions": {
"admin": true,
"push": true,
"pull": true
}
}
`
const repoFilePayload = `{ platform: linux/amd64 }`
const userRepoPayload = `
[
{
"owner": {
"login": "test_name",
"email": "octocat@github.com",
"avatar_url": "https:\/\/secure.gravatar.com\/avatar\/8c58a0be77ee441bb8f8595b7f1b4e87"
},
"full_name": "test_name\/repo_name",
"private": true,
"html_url": "http:\/\/localhost\/test_name\/repo_name",
"clone_url": "http:\/\/localhost\/test_name\/repo_name.git",
"permissions": {
"admin": true,
"push": true,
"pull": true
}
}
]
`

View file

@ -0,0 +1,140 @@
package fixtures
// HookPush is a sample Gitea push hook
const HookPush = `
{
"ref": "refs/heads/master",
"before": "4b2626259b5a97b6b4eab5e6cca66adb986b672b",
"after": "ef98532add3b2feb7a137426bba1248724367df5",
"compare_url": "http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5",
"commits": [
{
"id": "ef98532add3b2feb7a137426bba1248724367df5",
"message": "bump\n",
"url": "http://gitea.golang.org/gordon/hello-world/commit/ef98532add3b2feb7a137426bba1248724367df5",
"author": {
"name": "Gordon the Gopher",
"email": "gordon@golang.org",
"username": "gordon"
}
}
],
"repository": {
"id": 1,
"name": "hello-world",
"full_name": "gordon/hello-world",
"html_url": "http://gitea.golang.org/gordon/hello-world",
"ssh_url": "git@gitea.golang.org:gordon/hello-world.git",
"clone_url": "http://gitea.golang.org/gordon/hello-world.git",
"description": "",
"website": "",
"watchers": 1,
"owner": {
"name": "gordon",
"email": "gordon@golang.org",
"username": "gordon"
},
"private": true
},
"pusher": {
"name": "gordon",
"email": "gordon@golang.org",
"username": "gordon"
},
"sender": {
"login": "gordon",
"id": 1,
"avatar_url": "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
}
}
`
// HookPushTag is a sample Gitea tag hook
const HookPushTag = `{
"secret": "l26Un7G7HXogLAvsyf2hOA4EMARSTsR3",
"ref": "v1.0.0",
"ref_type": "tag",
"repository": {
"id": 1,
"owner": {
"id": 1,
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
},
"name": "hello-world",
"full_name": "gordon/hello-world",
"description": "",
"private": true,
"fork": false,
"html_url": "http://gitea.golang.org/gordon/hello-world",
"ssh_url": "git@gitea.golang.org:gordon/hello-world.git",
"clone_url": "http://gitea.golang.org/gordon/hello-world.git",
"default_branch": "master",
"created_at": "2015-10-22T19:32:44Z",
"updated_at": "2016-11-24T13:37:16Z"
},
"sender": {
"id": 1,
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
}
}`
// HookPullRequest is a sample pull_request webhook payload
const HookPullRequest = `{
"action": "opened",
"number": 1,
"pull_request": {
"html_url": "http://gitea.golang.org/gordon/hello-world/pull/1",
"state": "open",
"title": "Update the README with new information",
"body": "please merge",
"user": {
"id": 1,
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
},
"base_branch": "master",
"base": {
"label": "master",
"ref": "master",
"sha": "9353195a19e45482665306e466c832c46560532d"
},
"head_branch": "feature/changes",
"head": {
"label": "feature/changes",
"ref": "feature/changes",
"sha": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c"
}
},
"repository": {
"id": 35129377,
"name": "hello-world",
"full_name": "gordon/hello-world",
"owner": {
"id": 1,
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
},
"private": true,
"html_url": "http://gitea.golang.org/gordon/hello-world",
"clone_url": "https://gitea.golang.org/gordon/hello-world.git",
"default_branch": "master"
},
"sender": {
"id": 1,
"login": "gordon",
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
}
}`

357
remote/gitea/gitea.go Normal file
View file

@ -0,0 +1,357 @@
package gitea
import (
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"code.gitea.io/sdk/gitea"
"github.com/drone/drone/model"
"github.com/drone/drone/remote"
)
// Opts defines configuration options.
type Opts struct {
URL string // Gitea server url.
Username string // Optional machine account username.
Password string // Optional machine account password.
PrivateMode bool // Gitea is running in private mode.
SkipVerify bool // Skip ssl verification.
}
type client struct {
URL string
Machine string
Username string
Password string
PrivateMode bool
SkipVerify bool
}
const (
DescPending = "the build is pending"
DescRunning = "the build is running"
DescSuccess = "the build was successful"
DescFailure = "the build failed"
DescCanceled = "the build canceled"
DescBlocked = "the build is pending approval"
DescDeclined = "the build was rejected"
)
// getStatus is a helper function that converts a Drone
// status to a Gitea status.
func getStatus(status string) gitea.StatusState {
switch status {
case model.StatusPending, model.StatusBlocked:
return gitea.StatusPending
case model.StatusRunning:
return gitea.StatusPending
case model.StatusSuccess:
return gitea.StatusSuccess
case model.StatusFailure, model.StatusError:
return gitea.StatusFailure
case model.StatusKilled:
return gitea.StatusFailure
case model.StatusDeclined:
return gitea.StatusWarning
default:
return gitea.StatusFailure
}
}
// getDesc is a helper function that generates a description
// message for the build based on the status.
func getDesc(status string) string {
switch status {
case model.StatusPending:
return DescPending
case model.StatusRunning:
return DescRunning
case model.StatusSuccess:
return DescSuccess
case model.StatusFailure, model.StatusError:
return DescFailure
case model.StatusKilled:
return DescCanceled
case model.StatusBlocked:
return DescBlocked
case model.StatusDeclined:
return DescDeclined
default:
return DescFailure
}
}
// New returns a Remote implementation that integrates with Gitea, an open
// source Git service written in Go. See https://gitea.io/
func New(opts Opts) (remote.Remote, error) {
url, err := url.Parse(opts.URL)
if err != nil {
return nil, err
}
host, _, err := net.SplitHostPort(url.Host)
if err == nil {
url.Host = host
}
return &client{
URL: opts.URL,
Machine: url.Host,
Username: opts.Username,
Password: opts.Password,
PrivateMode: opts.PrivateMode,
SkipVerify: opts.SkipVerify,
}, nil
}
// Login authenticates an account with Gitea using basic authenticaiton. The
// Gitea account details are returned when the user is successfully authenticated.
func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) {
var (
username = req.FormValue("username")
password = req.FormValue("password")
)
// if the username or password is empty we re-direct to the login screen.
if len(username) == 0 || len(password) == 0 {
http.Redirect(res, req, "/login/form", http.StatusSeeOther)
return nil, nil
}
client := c.newClient()
// try to fetch drone token if it exists
var accessToken string
tokens, err := client.ListAccessTokens(username, password)
if err == nil {
for _, token := range tokens {
if token.Name == "drone" {
accessToken = token.Sha1
break
}
}
}
// if drone token not found, create it
if accessToken == "" {
token, terr := client.CreateAccessToken(
username,
password,
gitea.CreateAccessTokenOption{Name: "drone"},
)
if terr != nil {
return nil, terr
}
accessToken = token.Sha1
}
client = c.newClientToken(accessToken)
account, err := client.GetUserInfo(username)
if err != nil {
return nil, err
}
return &model.User{
Token: accessToken,
Login: account.UserName,
Email: account.Email,
Avatar: expandAvatar(c.URL, account.AvatarURL),
}, nil
}
// Auth is not supported by the Gitea driver.
func (c *client) Auth(token, secret string) (string, error) {
return "", fmt.Errorf("Not Implemented")
}
// Teams is supported by the Gitea driver.
func (c *client) Teams(u *model.User) ([]*model.Team, error) {
client := c.newClientToken(u.Token)
orgs, err := client.ListMyOrgs()
if err != nil {
return nil, err
}
var teams []*model.Team
for _, org := range orgs {
teams = append(teams, toTeam(org, c.URL))
}
return teams, nil
}
// TeamPerm is not supported by the Gitea driver.
func (c *client) TeamPerm(u *model.User, org string) (*model.Perm, error) {
return nil, nil
}
// Repo returns the named Gitea repository.
func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) {
client := c.newClientToken(u.Token)
repo, err := client.GetRepo(owner, name)
if err != nil {
return nil, err
}
if c.PrivateMode {
repo.Private = true
}
return toRepo(repo), nil
}
// Repos returns a list of all repositories for the Gitea account, including
// organization repositories.
func (c *client) Repos(u *model.User) ([]*model.RepoLite, error) {
repos := []*model.RepoLite{}
client := c.newClientToken(u.Token)
all, err := client.ListMyRepos()
if err != nil {
return repos, err
}
for _, repo := range all {
repos = append(repos, toRepoLite(repo))
}
return repos, err
}
// Perm returns the user permissions for the named Gitea repository.
func (c *client) Perm(u *model.User, owner, name string) (*model.Perm, error) {
client := c.newClientToken(u.Token)
repo, err := client.GetRepo(owner, name)
if err != nil {
return nil, err
}
return toPerm(repo.Permissions), nil
}
// File fetches the file from the Gitea repository and returns its contents.
func (c *client) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) {
client := c.newClientToken(u.Token)
cfg, err := client.GetFile(r.Owner, r.Name, b.Commit, f)
return cfg, err
}
// FileRef fetches the file from the Gitea repository and returns its contents.
func (c *client) FileRef(u *model.User, r *model.Repo, ref, f string) ([]byte, error) {
return c.newClientToken(u.Token).GetFile(r.Owner, r.Name, ref, f)
}
// Status is supported by the Gitea driver.
func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string) error {
client := c.newClientToken(u.Token)
status := getStatus(b.Status)
desc := getDesc(b.Status)
_, err := client.CreateStatus(
r.Owner,
r.Name,
b.Commit,
gitea.CreateStatusOption{
State: status,
TargetURL: link,
Description: desc,
Context: "",
},
)
return err
}
// Netrc returns a netrc file capable of authenticating Gitea requests and
// cloning Gitea repositories. The netrc will use the global machine account
// when configured.
func (c *client) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) {
if c.Password != "" {
return &model.Netrc{
Login: c.Username,
Password: c.Password,
Machine: c.Machine,
}, nil
}
return &model.Netrc{
Login: u.Token,
Password: "x-oauth-basic",
Machine: c.Machine,
}, nil
}
// Activate activates the repository by registering post-commit hooks with
// the Gitea repository.
func (c *client) Activate(u *model.User, r *model.Repo, link string) error {
config := map[string]string{
"url": link,
"secret": r.Hash,
"content_type": "json",
}
hook := gitea.CreateHookOption{
Type: "gitea",
Config: config,
Events: []string{"push", "create", "pull_request"},
Active: true,
}
client := c.newClientToken(u.Token)
_, err := client.CreateRepoHook(r.Owner, r.Name, hook)
return err
}
// Deactivate deactives the repository be removing repository push hooks from
// the Gitea repository.
func (c *client) Deactivate(u *model.User, r *model.Repo, link string) error {
client := c.newClientToken(u.Token)
hooks, err := client.ListRepoHooks(r.Owner, r.Name)
if err != nil {
return err
}
hook := matchingHooks(hooks, link)
if hook != nil {
return client.DeleteRepoHook(r.Owner, r.Name, hook.ID)
}
return nil
}
// Hook parses the incoming Gitea hook and returns the Repository and Build
// details. If the hook is unsupported nil values are returned.
func (c *client) Hook(r *http.Request) (*model.Repo, *model.Build, error) {
return parseHook(r)
}
// helper function to return the Gitea client
func (c *client) newClient() *gitea.Client {
return c.newClientToken("")
}
// helper function to return the Gitea client
func (c *client) newClientToken(token string) *gitea.Client {
client := gitea.NewClient(c.URL, token)
if c.SkipVerify {
httpClient := &http.Client{}
httpClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client.SetHTTPClient(httpClient)
}
return client
}
// helper function to return matching hooks.
func matchingHooks(hooks []*gitea.Hook, rawurl string) *gitea.Hook {
link, err := url.Parse(rawurl)
if err != nil {
return nil
}
for _, hook := range hooks {
if val, ok := hook.Config["url"]; ok {
hookurl, err := url.Parse(val)
if err == nil && hookurl.Host == link.Host {
return hook
}
}
}
return nil
}

181
remote/gitea/gitea_test.go Normal file
View file

@ -0,0 +1,181 @@
package gitea
import (
"net/http/httptest"
"testing"
"github.com/drone/drone/model"
"github.com/drone/drone/remote/gitea/fixtures"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
)
func Test_gitea(t *testing.T) {
gin.SetMode(gin.TestMode)
s := httptest.NewServer(fixtures.Handler())
c, _ := New(Opts{
URL: s.URL,
SkipVerify: true,
})
g := goblin.Goblin(t)
g.Describe("Gitea", func() {
g.After(func() {
s.Close()
})
g.Describe("Creating a remote", func() {
g.It("Should return client with specified options", func() {
remote, _ := New(Opts{
URL: "http://localhost:8080",
Username: "someuser",
Password: "password",
SkipVerify: true,
PrivateMode: true,
})
g.Assert(remote.(*client).URL).Equal("http://localhost:8080")
g.Assert(remote.(*client).Machine).Equal("localhost")
g.Assert(remote.(*client).Username).Equal("someuser")
g.Assert(remote.(*client).Password).Equal("password")
g.Assert(remote.(*client).SkipVerify).Equal(true)
g.Assert(remote.(*client).PrivateMode).Equal(true)
})
g.It("Should handle malformed url", func() {
_, err := New(Opts{URL: "%gh&%ij"})
g.Assert(err != nil).IsTrue()
})
})
g.Describe("Generating a netrc file", func() {
g.It("Should return a netrc with the user token", func() {
remote, _ := New(Opts{
URL: "http://gitea.com",
})
netrc, _ := remote.Netrc(fakeUser, nil)
g.Assert(netrc.Machine).Equal("gitea.com")
g.Assert(netrc.Login).Equal(fakeUser.Token)
g.Assert(netrc.Password).Equal("x-oauth-basic")
})
g.It("Should return a netrc with the machine account", func() {
remote, _ := New(Opts{
URL: "http://gitea.com",
Username: "someuser",
Password: "password",
})
netrc, _ := remote.Netrc(nil, nil)
g.Assert(netrc.Machine).Equal("gitea.com")
g.Assert(netrc.Login).Equal("someuser")
g.Assert(netrc.Password).Equal("password")
})
})
g.Describe("Requesting a repository", func() {
g.It("Should return the repository details", func() {
repo, err := c.Repo(fakeUser, fakeRepo.Owner, fakeRepo.Name)
g.Assert(err == nil).IsTrue()
g.Assert(repo.Owner).Equal(fakeRepo.Owner)
g.Assert(repo.Name).Equal(fakeRepo.Name)
g.Assert(repo.FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name)
g.Assert(repo.IsPrivate).IsTrue()
g.Assert(repo.Clone).Equal("http://localhost/test_name/repo_name.git")
g.Assert(repo.Link).Equal("http://localhost/test_name/repo_name")
})
g.It("Should handle a not found error", func() {
_, err := c.Repo(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(err != nil).IsTrue()
})
})
g.Describe("Requesting repository permissions", func() {
g.It("Should return the permission details", func() {
perm, err := c.Perm(fakeUser, fakeRepo.Owner, fakeRepo.Name)
g.Assert(err == nil).IsTrue()
g.Assert(perm.Admin).IsTrue()
g.Assert(perm.Push).IsTrue()
g.Assert(perm.Pull).IsTrue()
})
g.It("Should handle a not found error", func() {
_, err := c.Perm(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(err != nil).IsTrue()
})
})
g.Describe("Requesting a repository list", func() {
g.It("Should return the repository list", func() {
repos, err := c.Repos(fakeUser)
g.Assert(err == nil).IsTrue()
g.Assert(repos[0].Owner).Equal(fakeRepo.Owner)
g.Assert(repos[0].Name).Equal(fakeRepo.Name)
g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name)
})
g.It("Should handle a not found error", func() {
_, err := c.Repos(fakeUserNoRepos)
g.Assert(err != nil).IsTrue()
})
})
g.It("Should register repository hooks", func() {
err := c.Activate(fakeUser, fakeRepo, "http://localhost")
g.Assert(err == nil).IsTrue()
})
g.It("Should remove repository hooks", func() {
err := c.Deactivate(fakeUser, fakeRepo, "http://localhost")
g.Assert(err == nil).IsTrue()
})
g.It("Should return a repository file", func() {
raw, err := c.File(fakeUser, fakeRepo, fakeBuild, ".drone.yml")
g.Assert(err == nil).IsTrue()
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }")
})
g.It("Should return nil from send build status", func() {
err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://gitea.io")
g.Assert(err == nil).IsTrue()
})
g.Describe("Given an authentication request", func() {
g.It("Should redirect to login form")
g.It("Should create an access token")
g.It("Should handle an access token error")
g.It("Should return the authenticated user")
})
g.Describe("Given a repository hook", func() {
g.It("Should skip non-push events")
g.It("Should return push details")
g.It("Should handle a parsing error")
})
})
}
var (
fakeUser = &model.User{
Login: "someuser",
Token: "cfcd2084",
}
fakeUserNoRepos = &model.User{
Login: "someuser",
Token: "repos_not_found",
}
fakeRepo = &model.Repo{
Owner: "test_name",
Name: "repo_name",
FullName: "test_name/repo_name",
}
fakeRepoNotFound = &model.Repo{
Owner: "test_name",
Name: "repo_not_found",
FullName: "test_name/repo_not_found",
}
fakeBuild = &model.Build{
Commit: "9ecad50",
}
)

221
remote/gitea/helper.go Normal file
View file

@ -0,0 +1,221 @@
package gitea
import (
"encoding/json"
"fmt"
"io"
"net/url"
"strings"
"time"
"code.gitea.io/sdk/gitea"
"github.com/drone/drone/model"
)
// helper function that converts a Gitea repository to a Drone repository.
func toRepoLite(from *gitea.Repository) *model.RepoLite {
name := strings.Split(from.FullName, "/")[1]
avatar := expandAvatar(
from.HTMLURL,
from.Owner.AvatarURL,
)
return &model.RepoLite{
Name: name,
Owner: from.Owner.UserName,
FullName: from.FullName,
Avatar: avatar,
}
}
// helper function that converts a Gitea repository to a Drone repository.
func toRepo(from *gitea.Repository) *model.Repo {
name := strings.Split(from.FullName, "/")[1]
avatar := expandAvatar(
from.HTMLURL,
from.Owner.AvatarURL,
)
return &model.Repo{
Kind: model.RepoGit,
Name: name,
Owner: from.Owner.UserName,
FullName: from.FullName,
Avatar: avatar,
Link: from.HTMLURL,
IsPrivate: from.Private,
Clone: from.CloneURL,
Branch: "master",
}
}
// helper function that converts a Gitea permission to a Drone permission.
func toPerm(from *gitea.Permission) *model.Perm {
return &model.Perm{
Pull: from.Pull,
Push: from.Push,
Admin: from.Admin,
}
}
// helper function that converts a Gitea team to a Drone team.
func toTeam(from *gitea.Organization, link string) *model.Team {
return &model.Team{
Login: from.UserName,
Avatar: expandAvatar(link, from.AvatarURL),
}
}
// helper function that extracts the Build data from a Gitea push hook
func buildFromPush(hook *pushHook) *model.Build {
avatar := expandAvatar(
hook.Repo.URL,
fixMalformedAvatar(hook.Sender.Avatar),
)
author := hook.Sender.Login
if author == "" {
author = hook.Sender.Username
}
sender := hook.Sender.Username
if sender == "" {
sender = hook.Sender.Login
}
return &model.Build{
Event: model.EventPush,
Commit: hook.After,
Ref: hook.Ref,
Link: hook.Compare,
Branch: strings.TrimPrefix(hook.Ref, "refs/heads/"),
Message: hook.Commits[0].Message,
Avatar: avatar,
Author: author,
Timestamp: time.Now().UTC().Unix(),
Sender: sender,
}
}
// helper function that extracts the Build data from a Gitea tag hook
func buildFromTag(hook *pushHook) *model.Build {
avatar := expandAvatar(
hook.Repo.URL,
fixMalformedAvatar(hook.Sender.Avatar),
)
author := hook.Sender.Login
if author == "" {
author = hook.Sender.Username
}
sender := hook.Sender.Username
if sender == "" {
sender = hook.Sender.Login
}
return &model.Build{
Event: model.EventTag,
Commit: hook.After,
Ref: fmt.Sprintf("refs/tags/%s", hook.Ref),
Link: fmt.Sprintf("%s/src/%s", hook.Repo.URL, hook.Ref),
Branch: fmt.Sprintf("refs/tags/%s", hook.Ref),
Message: fmt.Sprintf("created tag %s", hook.Ref),
Avatar: avatar,
Author: author,
Sender: sender,
Timestamp: time.Now().UTC().Unix(),
}
}
// helper function that extracts the Build data from a Gitea pull_request hook
func buildFromPullRequest(hook *pullRequestHook) *model.Build {
avatar := expandAvatar(
hook.Repo.URL,
fixMalformedAvatar(hook.PullRequest.User.Avatar),
)
sender := hook.Sender.Username
if sender == "" {
sender = hook.Sender.Login
}
build := &model.Build{
Event: model.EventPull,
Commit: hook.PullRequest.Head.Sha,
Link: hook.PullRequest.URL,
Ref: fmt.Sprintf("refs/pull/%d/head", hook.Number),
Branch: hook.PullRequest.BaseBranch,
Message: hook.PullRequest.Title,
Author: hook.PullRequest.User.Username,
Avatar: avatar,
Sender: sender,
Title: hook.PullRequest.Title,
Refspec: fmt.Sprintf("%s:%s",
hook.PullRequest.HeadBranch,
hook.PullRequest.BaseBranch,
),
}
return build
}
// helper function that extracts the Repository data from a Gitea push hook
func repoFromPush(hook *pushHook) *model.Repo {
return &model.Repo{
Name: hook.Repo.Name,
Owner: hook.Repo.Owner.Username,
FullName: hook.Repo.FullName,
Link: hook.Repo.URL,
}
}
// helper function that extracts the Repository data from a Gitea pull_request hook
func repoFromPullRequest(hook *pullRequestHook) *model.Repo {
return &model.Repo{
Name: hook.Repo.Name,
Owner: hook.Repo.Owner.Username,
FullName: hook.Repo.FullName,
Link: hook.Repo.URL,
}
}
// helper function that parses a push hook from a read closer.
func parsePush(r io.Reader) (*pushHook, error) {
push := new(pushHook)
err := json.NewDecoder(r).Decode(push)
return push, err
}
func parsePullRequest(r io.Reader) (*pullRequestHook, error) {
pr := new(pullRequestHook)
err := json.NewDecoder(r).Decode(pr)
return pr, err
}
// fixMalformedAvatar is a helper function that fixes an avatar url if malformed
// (currently a known bug with gitea)
func fixMalformedAvatar(url string) string {
index := strings.Index(url, "///")
if index != -1 {
return url[index+1:]
}
index = strings.Index(url, "//avatars/")
if index != -1 {
return strings.Replace(url, "//avatars/", "/avatars/", -1)
}
return url
}
// expandAvatar is a helper function that converts a relative avatar URL to the
// absolute url.
func expandAvatar(repo, rawurl string) string {
aurl, err := url.Parse(rawurl)
if err != nil {
return rawurl
}
if aurl.IsAbs() {
// Url is already absolute
return aurl.String()
}
// Resolve to base
burl, err := url.Parse(repo)
if err != nil {
return rawurl
}
aurl = burl.ResolveReference(aurl)
return aurl.String()
}

249
remote/gitea/helper_test.go Normal file
View file

@ -0,0 +1,249 @@
package gitea
import (
"bytes"
"testing"
"code.gitea.io/sdk/gitea"
"github.com/drone/drone/model"
"github.com/drone/drone/remote/gitea/fixtures"
"github.com/franela/goblin"
)
func Test_parse(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("Gitea", func() {
g.It("Should parse push hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf)
g.Assert(err == nil).IsTrue()
g.Assert(hook.Ref).Equal("refs/heads/master")
g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b")
g.Assert(hook.Compare).Equal("http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.URL).Equal("http://gitea.golang.org/gordon/hello-world")
g.Assert(hook.Repo.Owner.Name).Equal("gordon")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.Username).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Pusher.Name).Equal("gordon")
g.Assert(hook.Pusher.Email).Equal("gordon@golang.org")
g.Assert(hook.Pusher.Username).Equal("gordon")
g.Assert(hook.Sender.Login).Equal("gordon")
g.Assert(hook.Sender.Avatar).Equal("http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
g.It("Should parse tag hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPushTag)
hook, err := parsePush(buf)
g.Assert(err == nil).IsTrue()
g.Assert(hook.Ref).Equal("v1.0.0")
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.URL).Equal("http://gitea.golang.org/gordon/hello-world")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.Username).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Sender.Username).Equal("gordon")
g.Assert(hook.Sender.Avatar).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
g.It("Should parse pull_request hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, err := parsePullRequest(buf)
g.Assert(err == nil).IsTrue()
g.Assert(hook.Action).Equal("opened")
g.Assert(hook.Number).Equal(int64(1))
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.URL).Equal("http://gitea.golang.org/gordon/hello-world")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.Username).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Sender.Username).Equal("gordon")
g.Assert(hook.Sender.Avatar).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(hook.PullRequest.Title).Equal("Update the README with new information")
g.Assert(hook.PullRequest.Body).Equal("please merge")
g.Assert(hook.PullRequest.State).Equal("open")
g.Assert(hook.PullRequest.User.Username).Equal("gordon")
g.Assert(hook.PullRequest.Base.Label).Equal("master")
g.Assert(hook.PullRequest.Base.Ref).Equal("master")
g.Assert(hook.PullRequest.Head.Label).Equal("feature/changes")
g.Assert(hook.PullRequest.Head.Ref).Equal("feature/changes")
})
g.It("Should return a Build struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
build := buildFromPush(hook)
g.Assert(build.Event).Equal(model.EventPush)
g.Assert(build.Commit).Equal(hook.After)
g.Assert(build.Ref).Equal(hook.Ref)
g.Assert(build.Link).Equal(hook.Compare)
g.Assert(build.Branch).Equal("master")
g.Assert(build.Message).Equal(hook.Commits[0].Message)
g.Assert(build.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(build.Author).Equal(hook.Sender.Login)
})
g.It("Should return a Repo struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
repo := repoFromPush(hook)
g.Assert(repo.Name).Equal(hook.Repo.Name)
g.Assert(repo.Owner).Equal(hook.Repo.Owner.Username)
g.Assert(repo.FullName).Equal("gordon/hello-world")
g.Assert(repo.Link).Equal(hook.Repo.URL)
})
g.It("Should return a Build struct from a pull_request hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
build := buildFromPullRequest(hook)
g.Assert(build.Event).Equal(model.EventPull)
g.Assert(build.Commit).Equal(hook.PullRequest.Head.Sha)
g.Assert(build.Ref).Equal("refs/pull/1/head")
g.Assert(build.Link).Equal(hook.PullRequest.URL)
g.Assert(build.Branch).Equal("master")
g.Assert(build.Message).Equal(hook.PullRequest.Title)
g.Assert(build.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(build.Author).Equal(hook.PullRequest.User.Username)
})
g.It("Should return a Repo struct from a pull_request hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
repo := repoFromPullRequest(hook)
g.Assert(repo.Name).Equal(hook.Repo.Name)
g.Assert(repo.Owner).Equal(hook.Repo.Owner.Username)
g.Assert(repo.FullName).Equal("gordon/hello-world")
g.Assert(repo.Link).Equal(hook.Repo.URL)
})
g.It("Should return a Perm struct from a Gitea Perm", func() {
perms := []gitea.Permission{
{true, true, true},
{true, true, false},
{true, false, false},
}
for _, from := range perms {
perm := toPerm(&from)
g.Assert(perm.Pull).Equal(from.Pull)
g.Assert(perm.Push).Equal(from.Push)
g.Assert(perm.Admin).Equal(from.Admin)
}
})
g.It("Should return a Team struct from a Gitea Org", func() {
from := &gitea.Organization{
UserName: "drone",
AvatarURL: "/avatars/1",
}
to := toTeam(from, "http://localhost:80")
g.Assert(to.Login).Equal(from.UserName)
g.Assert(to.Avatar).Equal("http://localhost:80/avatars/1")
})
g.It("Should return a Repo struct from a Gitea Repo", func() {
from := gitea.Repository{
FullName: "gophers/hello-world",
Owner: &gitea.User{
UserName: "gordon",
AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
CloneURL: "http://gitea.golang.org/gophers/hello-world.git",
HTMLURL: "http://gitea.golang.org/gophers/hello-world",
Private: true,
}
repo := toRepo(&from)
g.Assert(repo.FullName).Equal(from.FullName)
g.Assert(repo.Owner).Equal(from.Owner.UserName)
g.Assert(repo.Name).Equal("hello-world")
g.Assert(repo.Branch).Equal("master")
g.Assert(repo.Link).Equal(from.HTMLURL)
g.Assert(repo.Clone).Equal(from.CloneURL)
g.Assert(repo.Avatar).Equal(from.Owner.AvatarURL)
g.Assert(repo.IsPrivate).Equal(from.Private)
})
g.It("Should return a RepoLite struct from a Gitea Repo", func() {
from := gitea.Repository{
FullName: "gophers/hello-world",
Owner: &gitea.User{
UserName: "gordon",
AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
}
repo := toRepoLite(&from)
g.Assert(repo.FullName).Equal(from.FullName)
g.Assert(repo.Owner).Equal(from.Owner.UserName)
g.Assert(repo.Name).Equal("hello-world")
g.Assert(repo.Avatar).Equal(from.Owner.AvatarURL)
})
g.It("Should correct a malformed avatar url", func() {
var urls = []struct {
Before string
After string
}{
{
"http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"http://gitea.golang.org/avatars/1",
"http://gitea.golang.org/avatars/1",
},
{
"http://gitea.golang.org//avatars/1",
"http://gitea.golang.org/avatars/1",
},
}
for _, url := range urls {
got := fixMalformedAvatar(url.Before)
g.Assert(got).Equal(url.After)
}
})
g.It("Should expand the avatar url", func() {
var urls = []struct {
Before string
After string
}{
{
"/avatars/1",
"http://gitea.io/avatars/1",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"/gitea/avatars/2",
"http://gitea.io/gitea/avatars/2",
},
}
var repo = "http://gitea.io/foo/bar"
for _, url := range urls {
got := expandAvatar(repo, url.Before)
g.Assert(got).Equal(url.After)
}
})
})
}

107
remote/gitea/parse.go Normal file
View file

@ -0,0 +1,107 @@
package gitea
import (
"io"
"net/http"
"github.com/drone/drone/model"
)
const (
hookEvent = "X-Gitea-Event"
hookPush = "push"
hookCreated = "create"
hookPullRequest = "pull_request"
actionOpen = "opened"
actionSync = "synchronize"
stateOpen = "open"
refBranch = "branch"
refTag = "tag"
)
// parseHook parses a Gitea hook from an http.Request request and returns
// Repo and Build detail. If a hook type is unsupported nil values are returned.
func parseHook(r *http.Request) (*model.Repo, *model.Build, error) {
switch r.Header.Get(hookEvent) {
case hookPush:
return parsePushHook(r.Body)
case hookCreated:
return parseCreatedHook(r.Body)
case hookPullRequest:
return parsePullRequestHook(r.Body)
}
return nil, nil, nil
}
// parsePushHook parses a push hook and returns the Repo and Build details.
// If the commit type is unsupported nil values are returned.
func parsePushHook(payload io.Reader) (*model.Repo, *model.Build, error) {
var (
repo *model.Repo
build *model.Build
)
push, err := parsePush(payload)
if err != nil {
return nil, nil, err
}
// is this even needed?
if push.RefType == refBranch {
return nil, nil, nil
}
repo = repoFromPush(push)
build = buildFromPush(push)
return repo, build, err
}
// parseCreatedHook parses a push hook and returns the Repo and Build details.
// If the commit type is unsupported nil values are returned.
func parseCreatedHook(payload io.Reader) (*model.Repo, *model.Build, error) {
var (
repo *model.Repo
build *model.Build
)
push, err := parsePush(payload)
if err != nil {
return nil, nil, err
}
if push.RefType != refTag {
return nil, nil, nil
}
repo = repoFromPush(push)
build = buildFromTag(push)
return repo, build, err
}
// parsePullRequestHook parses a pull_request hook and returns the Repo and Build details.
func parsePullRequestHook(payload io.Reader) (*model.Repo, *model.Build, error) {
var (
repo *model.Repo
build *model.Build
)
pr, err := parsePullRequest(payload)
if err != nil {
return nil, nil, err
}
// Don't trigger builds for non-code changes, or if PR is not open
if pr.Action != actionOpen && pr.Action != actionSync {
return nil, nil, nil
}
if pr.PullRequest.State != stateOpen {
return nil, nil, nil
}
repo = repoFromPullRequest(pr)
build = buildFromPullRequest(pr)
return repo, build, err
}

View file

@ -0,0 +1 @@
package gitea

127
remote/gitea/types.go Normal file
View file

@ -0,0 +1,127 @@
package gitea
type pushHook struct {
Ref string `json:"ref"`
Before string `json:"before"`
After string `json:"after"`
Compare string `json:"compare_url"`
RefType string `json:"ref_type"`
Pusher struct {
Name string `json:"name"`
Email string `json:"email"`
Login string `json:"login"`
Username string `json:"username"`
} `json:"pusher"`
Repo struct {
ID int64 `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
URL string `json:"html_url"`
Private bool `json:"private"`
Owner struct {
Name string `json:"name"`
Email string `json:"email"`
Username string `json:"username"`
} `json:"owner"`
} `json:"repository"`
Commits []struct {
ID string `json:"id"`
Message string `json:"message"`
URL string `json:"url"`
} `json:"commits"`
Sender struct {
ID int64 `json:"id"`
Login string `json:"login"`
Username string `json:"username"`
Avatar string `json:"avatar_url"`
} `json:"sender"`
}
type pullRequestHook struct {
Action string `json:"action"`
Number int64 `json:"number"`
PullRequest struct {
ID int64 `json:"id"`
User struct {
ID int64 `json:"id"`
Username string `json:"username"`
Name string `json:"full_name"`
Email string `json:"email"`
Avatar string `json:"avatar_url"`
} `json:"user"`
Title string `json:"title"`
Body string `json:"body"`
Labels []string `json:"labels"`
State string `json:"state"`
URL string `json:"html_url"`
Mergeable bool `json:"mergeable"`
Merged bool `json:"merged"`
MergeBase string `json:"merge_base"`
BaseBranch string `json:"base_branch"`
Base struct {
Label string `json:"label"`
Ref string `json:"ref"`
Sha string `json:"sha"`
Repo struct {
ID int64 `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
URL string `json:"html_url"`
Private bool `json:"private"`
Owner struct {
ID int64 `json:"id"`
Username string `json:"username"`
Name string `json:"full_name"`
Email string `json:"email"`
Avatar string `json:"avatar_url"`
} `json:"owner"`
} `json:"repo"`
} `json:"base"`
HeadBranch string `json:"head_branch"`
Head struct {
Label string `json:"label"`
Ref string `json:"ref"`
Sha string `json:"sha"`
Repo struct {
ID int64 `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
URL string `json:"html_url"`
Private bool `json:"private"`
Owner struct {
ID int64 `json:"id"`
Username string `json:"username"`
Name string `json:"full_name"`
Email string `json:"email"`
Avatar string `json:"avatar_url"`
} `json:"owner"`
} `json:"repo"`
} `json:"head"`
} `json:"pull_request"`
Repo struct {
ID int64 `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
URL string `json:"html_url"`
Private bool `json:"private"`
Owner struct {
ID int64 `json:"id"`
Username string `json:"username"`
Name string `json:"full_name"`
Email string `json:"email"`
Avatar string `json:"avatar_url"`
} `json:"owner"`
} `json:"repository"`
Sender struct {
ID int64 `json:"id"`
Login string `json:"login"`
Username string `json:"username"`
Name string `json:"full_name"`
Email string `json:"email"`
Avatar string `json:"avatar_url"`
} `json:"sender"`
}

View file

@ -7,6 +7,7 @@ import (
"github.com/drone/drone/remote" "github.com/drone/drone/remote"
"github.com/drone/drone/remote/bitbucket" "github.com/drone/drone/remote/bitbucket"
"github.com/drone/drone/remote/bitbucketserver" "github.com/drone/drone/remote/bitbucketserver"
"github.com/drone/drone/remote/gitea"
"github.com/drone/drone/remote/github" "github.com/drone/drone/remote/github"
"github.com/drone/drone/remote/gitlab" "github.com/drone/drone/remote/gitlab"
"github.com/drone/drone/remote/gogs" "github.com/drone/drone/remote/gogs"
@ -39,6 +40,8 @@ func setupRemote(c *cli.Context) (remote.Remote, error) {
return setupStash(c) return setupStash(c)
case c.Bool("gogs"): case c.Bool("gogs"):
return setupGogs(c) return setupGogs(c)
case c.Bool("gitea"):
return setupGitea(c)
default: default:
return nil, fmt.Errorf("version control system not configured") return nil, fmt.Errorf("version control system not configured")
} }
@ -63,6 +66,17 @@ func setupGogs(c *cli.Context) (remote.Remote, error) {
}) })
} }
// helper function to setup the Gitea remote from the CLI arguments.
func setupGitea(c *cli.Context) (remote.Remote, error) {
return gitea.New(gitea.Opts{
URL: c.String("gitea-server"),
Username: c.String("gitea-git-username"),
Password: c.String("gitea-git-password"),
PrivateMode: c.Bool("gitea-private-mode"),
SkipVerify: c.Bool("gitea-skip-verify"),
})
}
// helper function to setup the Stash remote from the CLI arguments. // helper function to setup the Stash remote from the CLI arguments.
func setupStash(c *cli.Context) (remote.Remote, error) { func setupStash(c *cli.Context) (remote.Remote, error) {
return bitbucketserver.New(bitbucketserver.Opts{ return bitbucketserver.New(bitbucketserver.Opts{

20
vendor/code.gitea.io/sdk/LICENSE generated vendored Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2016 The Gitea Authors
Copyright (c) 2014 The Gogs Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

22
vendor/code.gitea.io/sdk/gitea/admin_org.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// AdminCreateOrg create an organization
func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
org := new(Organization)
return org, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user),
jsonHeader, bytes.NewReader(body), org)
}

22
vendor/code.gitea.io/sdk/gitea/admin_repo.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// AdminCreateRepo create a repo
func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
repo := new(Repository)
return repo, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user),
jsonHeader, bytes.NewReader(body), repo)
}

74
vendor/code.gitea.io/sdk/gitea/admin_user.go generated vendored Normal file
View file

@ -0,0 +1,74 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// CreateUserOption create user options
type CreateUserOption struct {
SourceID int64 `json:"source_id"`
LoginName string `json:"login_name"`
Username string `json:"username" binding:"Required;AlphaDashDot;MaxSize(35)"`
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
Password string `json:"password" binding:"MaxSize(255)"`
SendNotify bool `json:"send_notify"`
}
// AdminCreateUser create a user
func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
user := new(User)
return user, c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user)
}
// EditUserOption edit user options
type EditUserOption struct {
SourceID int64 `json:"source_id"`
LoginName string `json:"login_name"`
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
Password string `json:"password" binding:"MaxSize(255)"`
Website string `json:"website" binding:"MaxSize(50)"`
Location string `json:"location" binding:"MaxSize(50)"`
Active *bool `json:"active"`
Admin *bool `json:"admin"`
AllowGitHook *bool `json:"allow_git_hook"`
AllowImportLocal *bool `json:"allow_import_local"`
MaxRepoCreation *int `json:"max_repo_creation"`
}
// AdminEditUser modify user informations
func (c *Client) AdminEditUser(user string, opt EditUserOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body))
return err
}
// AdminDeleteUser delete one user according name
func (c *Client) AdminDeleteUser(user string) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
return err
}
// AdminCreateUserPublicKey create one user with options
func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
key := new(PublicKey)
return key, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key)
}

5
vendor/code.gitea.io/sdk/gitea/doc.go generated vendored Normal file
View file

@ -0,0 +1,5 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea // import "code.gitea.io/sdk/gitea"

38
vendor/code.gitea.io/sdk/gitea/fork.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// ListForks list a repository's forks
func (c *Client) ListForks(user, repo string) ([]*Repository, error) {
forks := make([]*Repository, 10)
err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/forks", user, repo),
nil, nil, &forks)
return forks, err
}
// CreateForkOption options for creating a fork
type CreateForkOption struct {
Organization *string `json:"organization"`
}
// CreateFork create a fork of a repository
func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, error) {
body, err := json.Marshal(form)
if err != nil {
return nil, err
}
fork := new(Repository)
err = c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/forks", user, repo),
jsonHeader, bytes.NewReader(body), &fork)
return fork, err
}

101
vendor/code.gitea.io/sdk/gitea/gitea.go generated vendored Normal file
View file

@ -0,0 +1,101 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"strings"
)
// Version return the library version
func Version() string {
return "0.12.3"
}
// Client represents a Gogs API client.
type Client struct {
url string
accessToken string
client *http.Client
}
// NewClient initializes and returns a API client.
func NewClient(url, token string) *Client {
return &Client{
url: strings.TrimSuffix(url, "/"),
accessToken: token,
client: &http.Client{},
}
}
// SetHTTPClient replaces default http.Client with user given one.
func (c *Client) SetHTTPClient(client *http.Client) {
c.client = client
}
func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest(method, c.url+"/api/v1"+path, body)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "token "+c.accessToken)
for k, v := range header {
req.Header[k] = v
}
return c.client.Do(req)
}
func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, error) {
resp, err := c.doRequest(method, path, header, body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
switch resp.StatusCode {
case 403:
return nil, errors.New("403 Forbidden")
case 404:
return nil, errors.New("404 Not Found")
}
if resp.StatusCode/100 != 2 {
errMap := make(map[string]interface{})
if err = json.Unmarshal(data, &errMap); err != nil {
return nil, err
}
return nil, errors.New(errMap["message"].(string))
}
return data, nil
}
func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) error {
data, err := c.getResponse(method, path, header, body)
if err != nil {
return err
}
return json.Unmarshal(data, obj)
}
func (c *Client) getStatusCode(method, path string, header http.Header, body io.Reader) (int, error) {
resp, err := c.doRequest(method, path, header, body)
if err != nil {
return -1, err
}
defer resp.Body.Close()
return resp.StatusCode, nil
}

391
vendor/code.gitea.io/sdk/gitea/hook.go generated vendored Normal file
View file

@ -0,0 +1,391 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
)
var (
// ErrInvalidReceiveHook FIXME
ErrInvalidReceiveHook = errors.New("Invalid JSON payload received over webhook")
)
// Hook a hook is a web hook when one repository changed
type Hook struct {
ID int64 `json:"id"`
Type string `json:"type"`
URL string `json:"-"`
Config map[string]string `json:"config"`
Events []string `json:"events"`
Active bool `json:"active"`
Updated time.Time `json:"updated_at"`
Created time.Time `json:"created_at"`
}
// ListOrgHooks list all the hooks of one organization
func (c *Client) ListOrgHooks(org string) ([]*Hook, error) {
hooks := make([]*Hook, 0, 10)
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks", org), nil, nil, &hooks)
}
// ListRepoHooks list all the hooks of one repository
func (c *Client) ListRepoHooks(user, repo string) ([]*Hook, error) {
hooks := make([]*Hook, 0, 10)
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), nil, nil, &hooks)
}
// GetOrgHook get a hook of an organization
func (c *Client) GetOrgHook(org string, id int64) (*Hook, error) {
h := new(Hook)
return h, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h)
}
// GetRepoHook get a hook of a repository
func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, error) {
h := new(Hook)
return h, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h)
}
// CreateHookOption options when create a hook
type CreateHookOption struct {
Type string `json:"type" binding:"Required"`
Config map[string]string `json:"config" binding:"Required"`
Events []string `json:"events"`
Active bool `json:"active"`
}
// CreateOrgHook create one hook for an organization, with options
func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
h := new(Hook)
return h, c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/hooks", org), jsonHeader, bytes.NewReader(body), h)
}
// CreateRepoHook create one hook for a repository, with options
func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
h := new(Hook)
return h, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h)
}
// EditHookOption options when modify one hook
type EditHookOption struct {
Config map[string]string `json:"config"`
Events []string `json:"events"`
Active *bool `json:"active"`
}
// EditOrgHook modify one hook of an organization, with hook id and options
func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body))
return err
}
// EditRepoHook modify one hook of a repository, with hook id and options
func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body))
return err
}
// DeleteOrgHook delete one hook from an organization, with hook id
func (c *Client) DeleteOrgHook(org string, id int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/org/%s/hooks/%d", org, id), nil, nil)
return err
}
// DeleteRepoHook delete one hook from a repository, with hook id
func (c *Client) DeleteRepoHook(user, repo string, id int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
return err
}
// Payloader payload is some part of one hook
type Payloader interface {
SetSecret(string)
JSONPayload() ([]byte, error)
}
// PayloadUser FIXME
type PayloadUser struct {
Name string `json:"name"`
Email string `json:"email"`
UserName string `json:"username"`
}
// PayloadCommit FIXME: consider use same format as API when commits API are added.
type PayloadCommit struct {
ID string `json:"id"`
Message string `json:"message"`
URL string `json:"url"`
Author *PayloadUser `json:"author"`
Committer *PayloadUser `json:"committer"`
Verification *PayloadCommitVerification `json:"verification"`
Timestamp time.Time `json:"timestamp"`
}
// PayloadCommitVerification represent the GPG verification part of a commit. FIXME: like PayloadCommit consider use same format as API when commits API are added.
type PayloadCommitVerification struct {
Verified bool `json:"verified"`
Reason string `json:"reason"`
Signature string `json:"signature"`
Payload string `json:"payload"`
}
var (
_ Payloader = &CreatePayload{}
_ Payloader = &PushPayload{}
_ Payloader = &IssuePayload{}
_ Payloader = &PullRequestPayload{}
)
// _________ __
// \_ ___ \_______ ____ _____ _/ |_ ____
// / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \
// \ \____| | \/\ ___/ / __ \| | \ ___/
// \______ /|__| \___ >____ /__| \___ >
// \/ \/ \/ \/
// CreatePayload FIXME
type CreatePayload struct {
Secret string `json:"secret"`
Sha string `json:"sha"`
Ref string `json:"ref"`
RefType string `json:"ref_type"`
Repo *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// SetSecret FIXME
func (p *CreatePayload) SetSecret(secret string) {
p.Secret = secret
}
// JSONPayload return payload information
func (p *CreatePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ParseCreateHook parses create event hook content.
func ParseCreateHook(raw []byte) (*CreatePayload, error) {
hook := new(CreatePayload)
if err := json.Unmarshal(raw, hook); err != nil {
return nil, err
}
// it is possible the JSON was parsed, however,
// was not from Gogs (maybe was from Bitbucket)
// So we'll check to be sure certain key fields
// were populated
switch {
case hook.Repo == nil:
return nil, ErrInvalidReceiveHook
case len(hook.Ref) == 0:
return nil, ErrInvalidReceiveHook
}
return hook, nil
}
// __________ .__
// \______ \__ __ _____| |__
// | ___/ | \/ ___/ | \
// | | | | /\___ \| Y \
// |____| |____//____ >___| /
// \/ \/
// PushPayload represents a payload information of push event.
type PushPayload struct {
Secret string `json:"secret"`
Ref string `json:"ref"`
Before string `json:"before"`
After string `json:"after"`
CompareURL string `json:"compare_url"`
Commits []*PayloadCommit `json:"commits"`
Repo *Repository `json:"repository"`
Pusher *User `json:"pusher"`
Sender *User `json:"sender"`
}
// SetSecret FIXME
func (p *PushPayload) SetSecret(secret string) {
p.Secret = secret
}
// JSONPayload FIXME
func (p *PushPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ParsePushHook parses push event hook content.
func ParsePushHook(raw []byte) (*PushPayload, error) {
hook := new(PushPayload)
if err := json.Unmarshal(raw, hook); err != nil {
return nil, err
}
switch {
case hook.Repo == nil:
return nil, ErrInvalidReceiveHook
case len(hook.Ref) == 0:
return nil, ErrInvalidReceiveHook
}
return hook, nil
}
// Branch returns branch name from a payload
func (p *PushPayload) Branch() string {
return strings.Replace(p.Ref, "refs/heads/", "", -1)
}
// .___
// | | ______ ________ __ ____
// | |/ ___// ___/ | \_/ __ \
// | |\___ \ \___ \| | /\ ___/
// |___/____ >____ >____/ \___ >
// \/ \/ \/
// HookIssueAction FIXME
type HookIssueAction string
const (
// HookIssueOpened opened
HookIssueOpened HookIssueAction = "opened"
// HookIssueClosed closed
HookIssueClosed HookIssueAction = "closed"
// HookIssueReOpened reopened
HookIssueReOpened HookIssueAction = "reopened"
// HookIssueEdited edited
HookIssueEdited HookIssueAction = "edited"
// HookIssueAssigned assigned
HookIssueAssigned HookIssueAction = "assigned"
// HookIssueUnassigned unassigned
HookIssueUnassigned HookIssueAction = "unassigned"
// HookIssueLabelUpdated label_updated
HookIssueLabelUpdated HookIssueAction = "label_updated"
// HookIssueLabelCleared label_cleared
HookIssueLabelCleared HookIssueAction = "label_cleared"
// HookIssueSynchronized synchronized
HookIssueSynchronized HookIssueAction = "synchronized"
// HookIssueMilestoned is an issue action for when a milestone is set on an issue.
HookIssueMilestoned HookIssueAction = "milestoned"
// HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue.
HookIssueDemilestoned HookIssueAction = "demilestoned"
)
// IssuePayload represents the payload information that is sent along with an issue event.
type IssuePayload struct {
Secret string `json:"secret"`
Action HookIssueAction `json:"action"`
Index int64 `json:"number"`
Changes *ChangesPayload `json:"changes,omitempty"`
Issue *Issue `json:"issue"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// SetSecret modifies the secret of the IssuePayload.
func (p *IssuePayload) SetSecret(secret string) {
p.Secret = secret
}
// JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces.
func (p *IssuePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ChangesFromPayload FIXME
type ChangesFromPayload struct {
From string `json:"from"`
}
// ChangesPayload FIXME
type ChangesPayload struct {
Title *ChangesFromPayload `json:"title,omitempty"`
Body *ChangesFromPayload `json:"body,omitempty"`
}
// __________ .__ .__ __________ __
// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
// \/ \/ |__| \/ \/
// PullRequestPayload represents a payload information of pull request event.
type PullRequestPayload struct {
Secret string `json:"secret"`
Action HookIssueAction `json:"action"`
Index int64 `json:"number"`
Changes *ChangesPayload `json:"changes,omitempty"`
PullRequest *PullRequest `json:"pull_request"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// SetSecret modifies the secret of the PullRequestPayload.
func (p *PullRequestPayload) SetSecret(secret string) {
p.Secret = secret
}
// JSONPayload FIXME
func (p *PullRequestPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
//__________ .__ __
//\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__.
// | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | |
// | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ |
// |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____|
// \/ \/|__| \/ \/
// HookRepoAction an action that happens to a repo
type HookRepoAction string
const (
// HookRepoCreated created
HookRepoCreated HookRepoAction = "created"
// HookRepoDeleted deleted
HookRepoDeleted HookRepoAction = "deleted"
)
// RepositoryPayload payload for repository webhooks
type RepositoryPayload struct {
Secret string `json:"secret"`
Action HookRepoAction `json:"action"`
Repository *Repository `json:"repository"`
Organization *User `json:"organization"`
Sender *User `json:"sender"`
}
// SetSecret set the payload's secret
func (p *RepositoryPayload) SetSecret(secret string) {
p.Secret = secret
}
// JSONPayload JSON representation of the payload
func (p *RepositoryPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}

118
vendor/code.gitea.io/sdk/gitea/issue.go generated vendored Normal file
View file

@ -0,0 +1,118 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// StateType issue state type
type StateType string
const (
// StateOpen pr is opend
StateOpen StateType = "open"
// StateClosed pr is closed
StateClosed StateType = "closed"
)
// PullRequestMeta PR info if an issue is a PR
type PullRequestMeta struct {
HasMerged bool `json:"merged"`
Merged *time.Time `json:"merged_at"`
}
// Issue an issue to a repository
type Issue struct {
ID int64 `json:"id"`
URL string `json:"url"`
Index int64 `json:"number"`
Poster *User `json:"user"`
Title string `json:"title"`
Body string `json:"body"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
Assignee *User `json:"assignee"`
State StateType `json:"state"`
Comments int `json:"comments"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
PullRequest *PullRequestMeta `json:"pull_request"`
}
// ListIssueOption list issue options
type ListIssueOption struct {
Page int
State string
}
// ListIssues returns all issues assigned the authenticated user
func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, error) {
issues := make([]*Issue, 0, 10)
return issues, c.getParsedResponse("GET", fmt.Sprintf("/issues?page=%d", opt.Page), nil, nil, &issues)
}
// ListUserIssues returns all issues assigned to the authenticated user
func (c *Client) ListUserIssues(opt ListIssueOption) ([]*Issue, error) {
issues := make([]*Issue, 0, 10)
return issues, c.getParsedResponse("GET", fmt.Sprintf("/user/issues?page=%d", opt.Page), nil, nil, &issues)
}
// ListRepoIssues returns all issues for a given repository
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) {
issues := make([]*Issue, 0, 10)
return issues, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues?page=%d", owner, repo, opt.Page), nil, nil, &issues)
}
// GetIssue returns a single issue for a given repository
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) {
issue := new(Issue)
return issue, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
}
// CreateIssueOption options to create one issue
type CreateIssueOption struct {
Title string `json:"title" binding:"Required"`
Body string `json:"body"`
Assignee string `json:"assignee"`
Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"`
Closed bool `json:"closed"`
}
// CreateIssue create a new issue for a given repository
func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
issue := new(Issue)
return issue, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
jsonHeader, bytes.NewReader(body), issue)
}
// EditIssueOption edit issue options
type EditIssueOption struct {
Title string `json:"title"`
Body *string `json:"body"`
Assignee *string `json:"assignee"`
Milestone *int64 `json:"milestone"`
State *string `json:"state"`
}
// EditIssue modify an existing issue for a given repository
func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
issue := new(Issue)
return issue, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
jsonHeader, bytes.NewReader(body), issue)
}

72
vendor/code.gitea.io/sdk/gitea/issue_comment.go generated vendored Normal file
View file

@ -0,0 +1,72 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Comment represents a comment in commit and issue page.
type Comment struct {
ID int64 `json:"id"`
HTMLURL string `json:"html_url"`
PRURL string `json:"pull_request_url"`
IssueURL string `json:"issue_url"`
Poster *User `json:"user"`
Body string `json:"body"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// ListIssueComments list comments on an issue.
func (c *Client) ListIssueComments(owner, repo string, index int64) ([]*Comment, error) {
comments := make([]*Comment, 0, 10)
return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), nil, nil, &comments)
}
// ListRepoIssueComments list comments for a given repo.
func (c *Client) ListRepoIssueComments(owner, repo string) ([]*Comment, error) {
comments := make([]*Comment, 0, 10)
return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo), nil, nil, &comments)
}
// CreateIssueCommentOption is option when creating an issue comment.
type CreateIssueCommentOption struct {
Body string `json:"body" binding:"Required"`
}
// CreateIssueComment create comment on an issue.
func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
comment := new(Comment)
return comment, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment)
}
// EditIssueCommentOption is option when editing an issue comment.
type EditIssueCommentOption struct {
Body string `json:"body" binding:"Required"`
}
// EditIssueComment edits an issue comment.
func (c *Client) EditIssueComment(owner, repo string, index, commentID int64, opt EditIssueCommentOption) (*Comment, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
comment := new(Comment)
return comment, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/:%s/:%s/issues/%d/comments/%d", owner, repo, index, commentID), jsonHeader, bytes.NewReader(body), comment)
}
// DeleteIssueComment deletes an issue comment.
func (c *Client) DeleteIssueComment(owner, repo string, index, commentID int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/comments/%d", owner, repo, index, commentID), nil, nil)
return err
}

116
vendor/code.gitea.io/sdk/gitea/issue_label.go generated vendored Normal file
View file

@ -0,0 +1,116 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// Label a label to an issue or a pr
type Label struct {
ID int64 `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
URL string `json:"url"`
}
// ListRepoLabels list lables of one reppsitory
func (c *Client) ListRepoLabels(owner, repo string) ([]*Label, error) {
labels := make([]*Label, 0, 10)
return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels", owner, repo), nil, nil, &labels)
}
// GetRepoLabel get one label of repository by repo it
// TODO: maybe we need get a label by name
func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, error) {
label := new(Label)
return label, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
}
// CreateLabelOption create options when one label of repository
type CreateLabelOption struct {
Name string `json:"name" binding:"Required"`
Color string `json:"color" binding:"Required;Size(7)"`
}
// CreateLabel create one label of repository
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
label := new(Label)
return label, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/labels", owner, repo),
jsonHeader, bytes.NewReader(body), label)
}
// EditLabelOption edit label options
type EditLabelOption struct {
Name *string `json:"name"`
Color *string `json:"color"`
}
// EditLabel modify one label with options
func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
label := new(Label)
return label, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label)
}
// DeleteLabel delete one label of repository by id
// TODO: maybe we need delete by name
func (c *Client) DeleteLabel(owner, repo string, id int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
return err
}
// IssueLabelsOption list one issue's labels options
type IssueLabelsOption struct {
Labels []int64 `json:"labels"`
}
// GetIssueLabels get labels of one issue via issue id
func (c *Client) GetIssueLabels(owner, repo string, index int64) ([]*Label, error) {
labels := make([]*Label, 0, 5)
return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil, &labels)
}
// AddIssueLabels add one or more labels to one issue
func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
var labels []*Label
return labels, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
}
// ReplaceIssueLabels replace old labels of issue with new labels
func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
var labels []*Label
return labels, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
}
// DeleteIssueLabel delete one label of one issue by issue id and label id
// TODO: maybe we need delete by label name and issue id
func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
return err
}
// ClearIssueLabels delete all the labels of one issue.
func (c *Client) ClearIssueLabels(owner, repo string, index int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
return err
}

77
vendor/code.gitea.io/sdk/gitea/issue_milestone.go generated vendored Normal file
View file

@ -0,0 +1,77 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Milestone milestone is a collection of issues on one repository
type Milestone struct {
ID int64 `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
State StateType `json:"state"`
OpenIssues int `json:"open_issues"`
ClosedIssues int `json:"closed_issues"`
Closed *time.Time `json:"closed_at"`
Deadline *time.Time `json:"due_on"`
}
// ListRepoMilestones list all the milestones of one repository
func (c *Client) ListRepoMilestones(owner, repo string) ([]*Milestone, error) {
milestones := make([]*Milestone, 0, 10)
return milestones, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), nil, nil, &milestones)
}
// GetMilestone get one milestone by repo name and milestone id
func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, error) {
milestone := new(Milestone)
return milestone, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
}
// CreateMilestoneOption options when creating milestone
type CreateMilestoneOption struct {
Title string `json:"title"`
Description string `json:"description"`
Deadline *time.Time `json:"due_on"`
}
// CreateMilestone create one milestone with options
func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
milestone := new(Milestone)
return milestone, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
}
// EditMilestoneOption options when modify milestone
type EditMilestoneOption struct {
Title string `json:"title"`
Description *string `json:"description"`
State *string `json:"state"`
Deadline *time.Time `json:"due_on"`
}
// EditMilestone modify milestone with options
func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
milestone := new(Milestone)
return milestone, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone)
}
// DeleteMilestone delete one milestone by milestone id
func (c *Client) DeleteMilestone(owner, repo string, id int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
return err
}

56
vendor/code.gitea.io/sdk/gitea/miscellaneous.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
// SearchResults results of search
// swagger:response SearchResults
type SearchResults struct {
OK bool `json:"ok"`
Data []*Repository `json:"data"`
}
// SearchError error of failing search
// swagger:response SearchError
type SearchError struct {
OK bool `json:"ok"`
Error string `json:"error"`
}
// MarkdownOption markdown options
// swagger:parameters renderMarkdown
type MarkdownOption struct {
// Text markdown to render
//
// in: body
Text string
// Mode to render
//
// in: body
Mode string
// Context to render
//
// in: body
Context string
// Is it a wiki page ?
//
// in: body
Wiki bool
}
// MarkdownRender is a rendered markdown document
// swagger:response MarkdownRender
type MarkdownRender string
// ServerVersion wraps the version of the server
// swagger:response ServerVersion
type ServerVersion struct {
Version string
}
// ServerVersion returns the version of the server
func (c *Client) ServerVersion() (string, error) {
v := ServerVersion{}
return v.Version, c.getParsedResponse("GET", "/api/v1/version", nil, nil, &v)
}

67
vendor/code.gitea.io/sdk/gitea/org.go generated vendored Normal file
View file

@ -0,0 +1,67 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// Organization a group of some repositories, users and teams
type Organization struct {
ID int64 `json:"id"`
UserName string `json:"username"`
FullName string `json:"full_name"`
AvatarURL string `json:"avatar_url"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
}
// ListMyOrgs list all of current user's organizations
func (c *Client) ListMyOrgs() ([]*Organization, error) {
orgs := make([]*Organization, 0, 5)
return orgs, c.getParsedResponse("GET", "/user/orgs", nil, nil, &orgs)
}
// ListUserOrgs list all of some user's organizations
func (c *Client) ListUserOrgs(user string) ([]*Organization, error) {
orgs := make([]*Organization, 0, 5)
return orgs, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs", user), nil, nil, &orgs)
}
// GetOrg get one organization by name
func (c *Client) GetOrg(orgname string) (*Organization, error) {
org := new(Organization)
return org, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
}
// CreateOrgOption create one organization options
type CreateOrgOption struct {
UserName string `json:"username" binding:"Required"`
FullName string `json:"full_name"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
}
// EditOrgOption edit one organization options
type EditOrgOption struct {
FullName string `json:"full_name"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
}
// EditOrg modify one organization via options
func (c *Client) EditOrg(orgname string, opt EditOrgOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body))
return err
}

26
vendor/code.gitea.io/sdk/gitea/org_member.go generated vendored Normal file
View file

@ -0,0 +1,26 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// AddOrgMembershipOption add user to organization options
type AddOrgMembershipOption struct {
Role string `json:"role" binding:"Required"`
}
// AddOrgMembership add some one to an organization's member
func (c *Client) AddOrgMembership(org, user string, opt AddOrgMembershipOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("PUT", fmt.Sprintf("/orgs/%s/membership/%s", org, user), jsonHeader, bytes.NewReader(body))
return err
}

27
vendor/code.gitea.io/sdk/gitea/org_team.go generated vendored Normal file
View file

@ -0,0 +1,27 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
// Team is a sub virtual organization of one Organization
type Team struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Permission string `json:"permission"`
}
// CreateTeamOption options when create team
type CreateTeamOption struct {
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
Description string `json:"description" binding:"MaxSize(255)"`
Permission string `json:"permission"`
}
// EditTeamOption options when edit team
type EditTeamOption struct {
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
Description string `json:"description" binding:"MaxSize(255)"`
Permission string `json:"permission"`
}

136
vendor/code.gitea.io/sdk/gitea/pull.go generated vendored Normal file
View file

@ -0,0 +1,136 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// PullRequest represents a pull request API object.
type PullRequest struct {
ID int64 `json:"id"`
URL string `json:"url"`
Index int64 `json:"number"`
Poster *User `json:"user"`
Title string `json:"title"`
Body string `json:"body"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
Assignee *User `json:"assignee"`
State StateType `json:"state"`
Comments int `json:"comments"`
HTMLURL string `json:"html_url"`
DiffURL string `json:"diff_url"`
PatchURL string `json:"patch_url"`
Mergeable bool `json:"mergeable"`
HasMerged bool `json:"merged"`
Merged *time.Time `json:"merged_at"`
MergedCommitID *string `json:"merge_commit_sha"`
MergedBy *User `json:"merged_by"`
Base *PRBranchInfo `json:"base"`
Head *PRBranchInfo `json:"head"`
MergeBase string `json:"merge_base"`
Created *time.Time `json:"created_at"`
Updated *time.Time `json:"updated_at"`
}
// PRBranchInfo base branch info when send a PR
type PRBranchInfo struct {
Name string `json:"label"`
Ref string `json:"ref"`
Sha string `json:"sha"`
RepoID int64 `json:"repo_id"`
Repository *Repository `json:"repo"`
}
// ListPullRequestsOptions options when list PRs
type ListPullRequestsOptions struct {
Page int `json:"page"`
State string `json:"state"`
}
// ListRepoPullRequests list PRs of one repository
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
prs := make([]*PullRequest, 0, 10)
return prs, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls", owner, repo), jsonHeader, bytes.NewReader(body), &prs)
}
// GetPullRequest get information of one PR
func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, error) {
pr := new(PullRequest)
return pr, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr)
}
// CreatePullRequestOption options when creating a pull request
type CreatePullRequestOption struct {
Head string `json:"head" binding:"Required"`
Base string `json:"base" binding:"Required"`
Title string `json:"title" binding:"Required"`
Body string `json:"body"`
Assignee string `json:"assignee"`
Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"`
}
// CreatePullRequest create pull request with options
func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
pr := new(PullRequest)
return pr, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls", owner, repo),
jsonHeader, bytes.NewReader(body), pr)
}
// EditPullRequestOption options when modify pull request
type EditPullRequestOption struct {
Title string `json:"title"`
Body string `json:"body"`
Assignee string `json:"assignee"`
Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"`
State *string `json:"state"`
}
// EditPullRequest modify pull request with PR id and options
func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
pr := new(PullRequest)
return pr, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
jsonHeader, bytes.NewReader(body), pr)
}
// MergePullRequest merge a PR to repository by PR id
func (c *Client) MergePullRequest(owner, repo string, index int64) error {
_, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
return err
}
// IsPullRequestMerged test if one PR is merged to one repository
func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, error) {
statusCode, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
if err != nil {
return false, err
}
return statusCode == 204, nil
}

101
vendor/code.gitea.io/sdk/gitea/release.go generated vendored Normal file
View file

@ -0,0 +1,101 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Release represents a repository release
type Release struct {
ID int64 `json:"id"`
TagName string `json:"tag_name"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
URL string `json:"url"`
TarURL string `json:"tarball_url"`
ZipURL string `json:"zipball_url"`
IsDraft bool `json:"draft"`
IsPrerelease bool `json:"prerelease"`
CreatedAt time.Time `json:"created_at"`
PublishedAt time.Time `json:"published_at"`
Publisher *User `json:"author"`
}
// ListReleases list releases of a repository
func (c *Client) ListReleases(user, repo string) ([]*Release, error) {
releases := make([]*Release, 0, 10)
err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases", user, repo),
nil, nil, &releases)
return releases, err
}
// GetRelease get a release of a repository
func (c *Client) GetRelease(user, repo string, id int64) (*Release, error) {
r := new(Release)
err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
nil, nil, &r)
return r, err
}
// CreateReleaseOption options when creating a release
type CreateReleaseOption struct {
TagName string `json:"tag_name" binding:"Required"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
IsDraft bool `json:"draft"`
IsPrerelease bool `json:"prerelease"`
}
// CreateRelease create a release
func (c *Client) CreateRelease(user, repo string, form CreateReleaseOption) (*Release, error) {
body, err := json.Marshal(form)
if err != nil {
return nil, err
}
r := new(Release)
err = c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/releases", user, repo),
jsonHeader, bytes.NewReader(body), r)
return r, err
}
// EditReleaseOption options when editing a release
type EditReleaseOption struct {
TagName string `json:"tag_name"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
IsDraft *bool `json:"draft"`
IsPrerelease *bool `json:"prerelease"`
}
// EditRelease edit a release
func (c *Client) EditRelease(user, repo string, id int64, form EditReleaseOption) (*Release, error) {
body, err := json.Marshal(form)
if err != nil {
return nil, err
}
r := new(Release)
err = c.getParsedResponse("PATCH",
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
jsonHeader, bytes.NewReader(body), r)
return r, err
}
// DeleteRelease delete a release from a repository
func (c *Client) DeleteRelease(user, repo string, id int64) error {
_, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
nil, nil)
return err
}

167
vendor/code.gitea.io/sdk/gitea/repo.go generated vendored Normal file
View file

@ -0,0 +1,167 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Permission represents a API permission.
type Permission struct {
Admin bool `json:"admin"`
Push bool `json:"push"`
Pull bool `json:"pull"`
}
// Repository represents a API repository.
// swagger:response Repository
type Repository struct {
ID int64 `json:"id"`
Owner *User `json:"owner"`
Name string `json:"name"`
FullName string `json:"full_name"`
Description string `json:"description"`
Empty bool `json:"empty"`
Private bool `json:"private"`
Fork bool `json:"fork"`
Parent *Repository `json:"parent"`
Mirror bool `json:"mirror"`
Size int `json:"size"`
HTMLURL string `json:"html_url"`
SSHURL string `json:"ssh_url"`
CloneURL string `json:"clone_url"`
Website string `json:"website"`
Stars int `json:"stars_count"`
Forks int `json:"forks_count"`
Watchers int `json:"watchers_count"`
OpenIssues int `json:"open_issues_count"`
DefaultBranch string `json:"default_branch"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
Permissions *Permission `json:"permissions,omitempty"`
}
// RepositoryList represents a list of API repository.
// swagger:response RepositoryList
type RepositoryList []*Repository
// ListMyRepos lists all repositories for the authenticated user that has access to.
func (c *Client) ListMyRepos() ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
return repos, c.getParsedResponse("GET", "/user/repos", nil, nil, &repos)
}
// ListUserRepos list all repositories of one user by user's name
func (c *Client) ListUserRepos(user string) ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos", user), nil, nil, &repos)
}
// ListOrgRepos list all repositories of one organization by organization's name
func (c *Client) ListOrgRepos(org string) ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos", org), nil, nil, &repos)
}
// CreateRepoOption options when creating repository
//swagger:parameters createOrgRepo
type CreateRepoOption struct {
// Name of the repository to create
//
// in: body
// unique: true
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"`
// Description of the repository to create
//
// in: body
Description string `json:"description" binding:"MaxSize(255)"`
// Is the repository to create private ?
//
// in: body
Private bool `json:"private"`
// Init the repository to create ?
//
// in: body
AutoInit bool `json:"auto_init"`
// Gitignores to use
//
// in: body
Gitignores string `json:"gitignores"`
// License to use
//
// in: body
License string `json:"license"`
// Readme of the repository to create
//
// in: body
Readme string `json:"readme"`
}
// CreateRepo creates a repository for authenticated user.
func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
repo := new(Repository)
return repo, c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo)
}
// CreateOrgRepo creates an organization repository for authenticated user.
func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
repo := new(Repository)
return repo, c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo)
}
// GetRepo returns information of a repository of given owner.
func (c *Client) GetRepo(owner, reponame string) (*Repository, error) {
repo := new(Repository)
return repo, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
}
// DeleteRepo deletes a repository of user or organization.
func (c *Client) DeleteRepo(owner, repo string) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
return err
}
// MigrateRepoOption options when migrate repository from an external place
type MigrateRepoOption struct {
CloneAddr string `json:"clone_addr" binding:"Required"`
AuthUsername string `json:"auth_username"`
AuthPassword string `json:"auth_password"`
UID int `json:"uid" binding:"Required"`
RepoName string `json:"repo_name" binding:"Required"`
Mirror bool `json:"mirror"`
Private bool `json:"private"`
Description string `json:"description"`
}
// MigrateRepo migrates a repository from other Git hosting sources for the
// authenticated user.
//
// To migrate a repository for a organization, the authenticated user must be a
// owner of the specified organization.
func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
repo := new(Repository)
return repo, c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo)
}
// MirrorSync adds a mirrored repository to the mirror sync queue.
func (c *Client) MirrorSync(owner, repo string) error {
_, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil)
return err
}

27
vendor/code.gitea.io/sdk/gitea/repo_branch.go generated vendored Normal file
View file

@ -0,0 +1,27 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
)
// Branch represents a repository branch.
type Branch struct {
Name string `json:"name"`
Commit *PayloadCommit `json:"commit"`
}
// ListRepoBranches list all the branches of one repository
func (c *Client) ListRepoBranches(user, repo string) ([]*Branch, error) {
branches := make([]*Branch, 0, 10)
return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches", user, repo), nil, nil, &branches)
}
// GetRepoBranch get one branch's information of one repository
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) {
b := new(Branch)
return b, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
}

57
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go generated vendored Normal file
View file

@ -0,0 +1,57 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// ListCollaborators list a repository's collaborators
func (c *Client) ListCollaborators(user, repo string) ([]*User, error) {
collaborators := make([]*User, 0, 10)
err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/collaborators", user, repo),
nil, nil, &collaborators)
return collaborators, err
}
// IsCollaborator check if a user is a collaborator of a repository
func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, error) {
status, err := c.getStatusCode("GET",
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator),
nil, nil)
if err != nil {
return false, err
}
if status == 204 {
return true, nil
}
return false, nil
}
// AddCollaboratorOption options when add some user as a collaborator of a repository
type AddCollaboratorOption struct {
Permission *string `json:"permission"`
}
// AddCollaborator add some user as a collaborator of a repository
func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, bytes.NewReader(body))
return err
}
// DeleteCollaborator remove a collaborator from a repository
func (c *Client) DeleteCollaborator(user, repo, collaborator string) error {
_, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator),
nil, nil)
return err
}

15
vendor/code.gitea.io/sdk/gitea/repo_file.go generated vendored Normal file
View file

@ -0,0 +1,15 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
)
// GetFile downloads a file of repository, ref can be branch/tag/commit.
// e.g.: ref -> master, tree -> macaron.go(no leading slash)
func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, error) {
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), nil, nil)
}

67
vendor/code.gitea.io/sdk/gitea/repo_key.go generated vendored Normal file
View file

@ -0,0 +1,67 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// DeployKey a deploy key
type DeployKey struct {
ID int64 `json:"id"`
Key string `json:"key"`
URL string `json:"url"`
Title string `json:"title"`
Created time.Time `json:"created_at"`
ReadOnly bool `json:"read_only"`
}
// ListDeployKeys list all the deploy keys of one repository
func (c *Client) ListDeployKeys(user, repo string) ([]*DeployKey, error) {
keys := make([]*DeployKey, 0, 10)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys", user, repo), nil, nil, &keys)
}
// GetDeployKey get one deploy key with key id
func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, error) {
key := new(DeployKey)
return key, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
}
// CreateKeyOption options when create deploy key
// swagger:parameters userCurrentPostKey
type CreateKeyOption struct {
// Title of the key to add
//
// in: body
// required: true
// unique: true
Title string `json:"title" binding:"Required"`
// An armored SSH key to add
//
// in: body
// required: true
// unique: true
Key string `json:"key" binding:"Required"`
}
// CreateDeployKey options when create one deploy key
func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
key := new(DeployKey)
return key, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key)
}
// DeleteDeployKey delete deploy key with key id
func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil)
return err
}

42
vendor/code.gitea.io/sdk/gitea/repo_watch.go generated vendored Normal file
View file

@ -0,0 +1,42 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/http"
"time"
)
// WatchInfo represents a API watch status of one repository
// swagger:response WatchInfo
type WatchInfo struct {
Subscribed bool `json:"subscribed"`
Ignored bool `json:"ignored"`
Reason interface{} `json:"reason"`
CreatedAt time.Time `json:"created_at"`
URL string `json:"url"`
RepositoryURL string `json:"repository_url"`
}
// GetWatchedRepos list all the watched repos of user
func (c *Client) GetWatchedRepos(user, pass string) ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user),
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, &repos)
}
// WatchRepo start to watch a repository
func (c *Client) WatchRepo(user, pass, repoUser, repoName string) (*WatchInfo, error) {
i := new(WatchInfo)
return i, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName),
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, i)
}
// UnWatchRepo start to watch a repository
func (c *Client) UnWatchRepo(user, pass, repoUser, repoName string) (int, error) {
return c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName),
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil)
}

95
vendor/code.gitea.io/sdk/gitea/status.go generated vendored Normal file
View file

@ -0,0 +1,95 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// StatusState holds the state of a Status
// It can be "pending", "success", "error", "failure", and "warning"
type StatusState string
const (
// StatusPending is for when the Status is Pending
StatusPending StatusState = "pending"
// StatusSuccess is for when the Status is Success
StatusSuccess StatusState = "success"
// StatusError is for when the Status is Error
StatusError StatusState = "error"
// StatusFailure is for when the Status is Failure
StatusFailure StatusState = "failure"
// StatusWarning is for when the Status is Warning
StatusWarning StatusState = "warning"
)
// Status holds a single Status of a single Commit
type Status struct {
ID int64 `json:"id"`
State StatusState `json:"status"`
TargetURL string `json:"target_url"`
Description string `json:"description"`
URL string `json:"url"`
Context string `json:"context"`
Creator *User `json:"creator"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// CombinedStatus holds the combined state of several statuses for a single commit
type CombinedStatus struct {
State StatusState `json:"state"`
SHA string `json:"sha"`
TotalCount int `json:"total_count"`
Statuses []*Status `json:"statuses"`
Repository *Repository `json:"repository"`
CommitURL string `json:"commit_url"`
URL string `json:"url"`
}
// CreateStatusOption holds the information needed to create a new Status for a Commit
type CreateStatusOption struct {
State StatusState `json:"state"`
TargetURL string `json:"target_url"`
Description string `json:"description"`
Context string `json:"context"`
}
// ListStatusesOption holds pagination information
type ListStatusesOption struct {
Page int
}
// CreateStatus creates a new Status for a given Commit
//
// POST /repos/:owner/:repo/statuses/:sha
func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, error) {
body, err := json.Marshal(&opts)
if err != nil {
return nil, err
}
status := &Status{}
return status, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, sha),
jsonHeader, bytes.NewReader(body), status)
}
// ListStatuses returns all statuses for a given Commit
//
// GET /repos/:owner/:repo/commits/:ref/statuses
func (c *Client) ListStatuses(owner, repo, sha string, opts ListStatusesOption) ([]*Status, error) {
statuses := make([]*Status, 0, 10)
return statuses, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?page=%d", owner, repo, sha, opts.Page), nil, nil, &statuses)
}
// GetCombinedStatus returns the CombinedStatus for a given Commit
//
// GET /repos/:owner/:repo/commits/:ref/status
func (c *Client) GetCombinedStatus(owner, repo, sha string) (*CombinedStatus, error) {
status := &CombinedStatus{}
return status, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, sha), nil, nil, status)
}

41
vendor/code.gitea.io/sdk/gitea/user.go generated vendored Normal file
View file

@ -0,0 +1,41 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"encoding/json"
"fmt"
)
// User represents a API user.
// swagger:response User
type User struct {
ID int64 `json:"id"`
UserName string `json:"login"`
FullName string `json:"full_name"`
Email string `json:"email"`
AvatarURL string `json:"avatar_url"`
}
// UserList represents a list of API user.
// swagger:response UserList
type UserList []*User
// MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility
func (u User) MarshalJSON() ([]byte, error) {
// Re-declaring User to avoid recursion
type shadow User
return json.Marshal(struct {
shadow
CompatUserName string `json:"username"`
}{shadow(u), u.UserName})
}
// GetUserInfo get user info by user's name
func (c *Client) GetUserInfo(user string) (*User, error) {
u := new(User)
err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
return u, err
}

56
vendor/code.gitea.io/sdk/gitea/user_app.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
)
// BasicAuthEncode generate base64 of basic auth head
func BasicAuthEncode(user, pass string) string {
return base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
}
// AccessToken represents a API access token.
// swagger:response AccessToken
type AccessToken struct {
Name string `json:"name"`
Sha1 string `json:"sha1"`
}
// AccessTokenList represents a list of API access token.
// swagger:response AccessTokenList
type AccessTokenList []*AccessToken
// ListAccessTokens lista all the access tokens of user
func (c *Client) ListAccessTokens(user, pass string) ([]*AccessToken, error) {
tokens := make([]*AccessToken, 0, 10)
return tokens, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens", user),
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, &tokens)
}
// CreateAccessTokenOption options when create access token
// swagger:parameters userCreateToken
type CreateAccessTokenOption struct {
Name string `json:"name" binding:"Required"`
}
// CreateAccessToken create one access token with options
func (c *Client) CreateAccessToken(user, pass string, opt CreateAccessTokenOption) (*AccessToken, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
t := new(AccessToken)
return t, c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", user),
http.Header{
"content-type": []string{"application/json"},
"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}},
bytes.NewReader(body), t)
}

48
vendor/code.gitea.io/sdk/gitea/user_email.go generated vendored Normal file
View file

@ -0,0 +1,48 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
)
// Email en email information of user
type Email struct {
Email string `json:"email"`
Verified bool `json:"verified"`
Primary bool `json:"primary"`
}
// ListEmails all the email addresses of user
func (c *Client) ListEmails() ([]*Email, error) {
emails := make([]*Email, 0, 3)
return emails, c.getParsedResponse("GET", "/user/emails", nil, nil, &emails)
}
// CreateEmailOption options when create an email
type CreateEmailOption struct {
Emails []string `json:"emails"`
}
// AddEmail add one email to current user with options
func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
emails := make([]*Email, 0, 3)
return emails, c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), emails)
}
// DeleteEmail delete one email of current users'
func (c *Client) DeleteEmail(opt CreateEmailOption) error {
body, err := json.Marshal(&opt)
if err != nil {
return err
}
_, err = c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body))
return err
}

55
vendor/code.gitea.io/sdk/gitea/user_follow.go generated vendored Normal file
View file

@ -0,0 +1,55 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import "fmt"
// ListMyFollowers list all the followers of current user
func (c *Client) ListMyFollowers(page int) ([]*User, error) {
users := make([]*User, 0, 10)
return users, c.getParsedResponse("GET", fmt.Sprintf("/user/followers?page=%d", page), nil, nil, &users)
}
// ListFollowers list all the followers of one user
func (c *Client) ListFollowers(user string, page int) ([]*User, error) {
users := make([]*User, 0, 10)
return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?page=%d", user, page), nil, nil, &users)
}
// ListMyFollowing list all the users current user followed
func (c *Client) ListMyFollowing(page int) ([]*User, error) {
users := make([]*User, 0, 10)
return users, c.getParsedResponse("GET", fmt.Sprintf("/user/following?page=%d", page), nil, nil, &users)
}
// ListFollowing list all the users the user followed
func (c *Client) ListFollowing(user string, page int) ([]*User, error) {
users := make([]*User, 0, 10)
return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?page=%d", user, page), nil, nil, &users)
}
// IsFollowing if current user followed the target
func (c *Client) IsFollowing(target string) bool {
_, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil)
return err == nil
}
// IsUserFollowing if the user followed the target
func (c *Client) IsUserFollowing(user, target string) bool {
_, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil)
return err == nil
}
// Follow set current user follow the target
func (c *Client) Follow(target string) error {
_, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil)
return err
}
// Unfollow set current user unfollow the target
func (c *Client) Unfollow(target string) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
return err
}

85
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go generated vendored Normal file
View file

@ -0,0 +1,85 @@
// Copyright 2017 Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// GPGKeyList represents a list of GPGKey
// swagger:response GPGKeyList
type GPGKeyList []*GPGKey
// GPGKey a user GPG key to sign commit and tag in repository
// swagger:response GPGKey
type GPGKey struct {
ID int64 `json:"id"`
PrimaryKeyID string `json:"primary_key_id"`
KeyID string `json:"key_id"`
PublicKey string `json:"public_key"`
Emails []*GPGKeyEmail `json:"emails"`
SubsKey []*GPGKey `json:"subkeys"`
CanSign bool `json:"can_sign"`
CanEncryptComms bool `json:"can_encrypt_comms"`
CanEncryptStorage bool `json:"can_encrypt_storage"`
CanCertify bool `json:"can_certify"`
Created time.Time `json:"created_at,omitempty"`
Expires time.Time `json:"expires_at,omitempty"`
}
// GPGKeyEmail a email attache to a GPGKey
// swagger:model GPGKeyEmail
type GPGKeyEmail struct {
Email string `json:"email"`
Verified bool `json:"verified"`
}
// CreateGPGKeyOption options create user GPG key
// swagger:parameters userCurrentPostGPGKey
type CreateGPGKeyOption struct {
// An armored GPG key to add
//
// in: body
// required: true
// unique: true
ArmoredKey string `json:"armored_public_key" binding:"Required"`
}
// ListGPGKeys list all the GPG keys of the user
func (c *Client) ListGPGKeys(user string) ([]*GPGKey, error) {
keys := make([]*GPGKey, 0, 10)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys", user), nil, nil, &keys)
}
// ListMyGPGKeys list all the GPG keys of current user
func (c *Client) ListMyGPGKeys() ([]*GPGKey, error) {
keys := make([]*GPGKey, 0, 10)
return keys, c.getParsedResponse("GET", "/user/gpg_keys", nil, nil, &keys)
}
// GetGPGKey get current user's GPG key by key id
func (c *Client) GetGPGKey(keyID int64) (*GPGKey, error) {
key := new(GPGKey)
return key, c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil, &key)
}
// CreateGPGKey create GPG key with options
func (c *Client) CreateGPGKey(opt CreateGPGKeyOption) (*GPGKey, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
key := new(GPGKey)
return key, c.getParsedResponse("POST", "/user/gpg_keys", jsonHeader, bytes.NewReader(body), key)
}
// DeleteGPGKey delete GPG key with key id
func (c *Client) DeleteGPGKey(keyID int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil)
return err
}

60
vendor/code.gitea.io/sdk/gitea/user_key.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// PublicKeyList represents a list of PublicKey
// swagger:response PublicKeyList
type PublicKeyList []*PublicKey
// PublicKey publickey is a user key to push code to repository
// swagger:response PublicKey
type PublicKey struct {
ID int64 `json:"id"`
Key string `json:"key"`
URL string `json:"url,omitempty"`
Title string `json:"title,omitempty"`
Created time.Time `json:"created_at,omitempty"`
}
// ListPublicKeys list all the public keys of the user
func (c *Client) ListPublicKeys(user string) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 10)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys", user), nil, nil, &keys)
}
// ListMyPublicKeys list all the public keys of current user
func (c *Client) ListMyPublicKeys() ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 10)
return keys, c.getParsedResponse("GET", "/user/keys", nil, nil, &keys)
}
// GetPublicKey get current user's public key by key id
func (c *Client) GetPublicKey(keyID int64) (*PublicKey, error) {
key := new(PublicKey)
return key, c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key)
}
// CreatePublicKey create public key with options
func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
key := new(PublicKey)
return key, c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key)
}
// DeletePublicKey delete public key with key id
func (c *Client) DeletePublicKey(keyID int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil)
return err
}

26
vendor/code.gitea.io/sdk/gitea/utils.go generated vendored Normal file
View file

@ -0,0 +1,26 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"net/http"
)
var jsonHeader = http.Header{"content-type": []string{"application/json"}}
// Bool return address of bool value
func Bool(v bool) *bool {
return &v
}
// String return address of string value
func String(v string) *string {
return &v
}
// Int64 return address of int64 value
func Int64(v int64) *int64 {
return &v
}

6
vendor/vendor.json vendored
View file

@ -6,6 +6,12 @@
"path": "appengine/cloudsql", "path": "appengine/cloudsql",
"revision": "" "revision": ""
}, },
{
"checksumSHA1": "nLhT+bLMj8uLICP+EZbrdoQe6mM=",
"path": "code.gitea.io/sdk/gitea",
"revision": "8cff72208aa458f4efa8fdfbad29b03aee485b8c",
"revisionTime": "2017-05-06T01:37:21Z"
},
{ {
"checksumSHA1": "zTn0jzjOiJlScR1px66MvrgrlLs=", "checksumSHA1": "zTn0jzjOiJlScR1px66MvrgrlLs=",
"origin": "github.com/docker/docker/vendor/github.com/Microsoft/go-winio", "origin": "github.com/docker/docker/vendor/github.com/Microsoft/go-winio",