mirror of
https://gitea.com/actions/release-action.git
synced 2024-11-15 14:45:38 +01:00
Compare commits
5 Commits
23a38ad334
...
21a5938ff2
Author | SHA1 | Date | |
---|---|---|---|
|
21a5938ff2 | ||
|
3431cf3373 | ||
|
e14f8acf6d | ||
|
549a1ec092 | ||
|
d3bedf74f5 |
5
main.go
5
main.go
@ -110,7 +110,10 @@ func getFiles(parentDir, files string) ([]string, error) {
|
|||||||
lines := strings.Split(files, "\n")
|
lines := strings.Split(files, "\n")
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
line = strings.Trim(line, "'")
|
line = strings.Trim(line, "'")
|
||||||
line = strings.Trim(line, `"`)
|
line = strings.TrimSpace(strings.Trim(line, `"`))
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if filepath.IsAbs(line) {
|
if filepath.IsAbs(line) {
|
||||||
return nil, fmt.Errorf("file path %s is absolute", line)
|
return nil, fmt.Errorf("file path %s is absolute", line)
|
||||||
}
|
}
|
||||||
|
20
vendor/code.gitea.io/sdk/gitea/LICENSE
generated
vendored
Normal file
20
vendor/code.gitea.io/sdk/gitea/LICENSE
generated
vendored
Normal 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.
|
47
vendor/code.gitea.io/sdk/gitea/admin_cron.go
generated
vendored
Normal file
47
vendor/code.gitea.io/sdk/gitea/admin_cron.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CronTask represents a Cron task
|
||||||
|
type CronTask struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Schedule string `json:"schedule"`
|
||||||
|
Next time.Time `json:"next"`
|
||||||
|
Prev time.Time `json:"prev"`
|
||||||
|
ExecTimes int64 `json:"exec_times"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCronTaskOptions list options for ListCronTasks
|
||||||
|
type ListCronTaskOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCronTasks list available cron tasks
|
||||||
|
func (c *Client) ListCronTasks(opt ListCronTaskOptions) ([]*CronTask, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
ct := make([]*CronTask, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/cron?%s", opt.getURLQuery().Encode()), jsonHeader, nil, &ct)
|
||||||
|
return ct, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunCronTasks run a cron task
|
||||||
|
func (c *Client) RunCronTasks(task string) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&task); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
39
vendor/code.gitea.io/sdk/gitea/admin_org.go
generated
vendored
Normal file
39
vendor/code.gitea.io/sdk/gitea/admin_org.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminListOrgsOptions options for listing admin's organizations
|
||||||
|
type AdminListOrgsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminListOrgs lists all orgs
|
||||||
|
func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
orgs := make([]*Organization, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||||
|
return orgs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminCreateOrg create an organization
|
||||||
|
func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
org := new(Organization)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user), jsonHeader, bytes.NewReader(body), org)
|
||||||
|
return org, resp, err
|
||||||
|
}
|
25
vendor/code.gitea.io/sdk/gitea/admin_repo.go
generated
vendored
Normal file
25
vendor/code.gitea.io/sdk/gitea/admin_repo.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// 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, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
130
vendor/code.gitea.io/sdk/gitea/admin_user.go
generated
vendored
Normal file
130
vendor/code.gitea.io/sdk/gitea/admin_user.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminListUsersOptions options for listing admin users
|
||||||
|
type AdminListUsersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminListUsers lists all users
|
||||||
|
func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateUserOption create user options
|
||||||
|
type CreateUserOption struct {
|
||||||
|
SourceID int64 `json:"source_id"`
|
||||||
|
LoginName string `json:"login_name"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
MustChangePassword *bool `json:"must_change_password"`
|
||||||
|
SendNotify bool `json:"send_notify"`
|
||||||
|
Visibility *VisibleType `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateUserOption struct
|
||||||
|
func (opt CreateUserOption) Validate() error {
|
||||||
|
if len(opt.Email) == 0 {
|
||||||
|
return fmt.Errorf("email is empty")
|
||||||
|
}
|
||||||
|
if len(opt.Username) == 0 {
|
||||||
|
return fmt.Errorf("username is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminCreateUser create a user
|
||||||
|
func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, *Response, error) {
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
user := new(User)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user)
|
||||||
|
return user, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditUserOption edit user options
|
||||||
|
type EditUserOption struct {
|
||||||
|
SourceID int64 `json:"source_id"`
|
||||||
|
LoginName string `json:"login_name"`
|
||||||
|
Email *string `json:"email"`
|
||||||
|
FullName *string `json:"full_name"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
MustChangePassword *bool `json:"must_change_password"`
|
||||||
|
Website *string `json:"website"`
|
||||||
|
Location *string `json:"location"`
|
||||||
|
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"`
|
||||||
|
ProhibitLogin *bool `json:"prohibit_login"`
|
||||||
|
AllowCreateOrganization *bool `json:"allow_create_organization"`
|
||||||
|
Restricted *bool `json:"restricted"`
|
||||||
|
Visibility *VisibleType `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminEditUser modify user informations
|
||||||
|
func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminDeleteUser delete one user according name
|
||||||
|
func (c *Client) AdminDeleteUser(user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminCreateUserPublicKey adds a public key for the user
|
||||||
|
func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(PublicKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminDeleteUserPublicKey deletes a user's public key
|
||||||
|
func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
111
vendor/code.gitea.io/sdk/gitea/attachment.go
generated
vendored
Normal file
111
vendor/code.gitea.io/sdk/gitea/attachment.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// 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 "code.gitea.io/sdk/gitea"
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Attachment a generic attachment
|
||||||
|
type Attachment struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
DownloadCount int64 `json:"download_count"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
DownloadURL string `json:"browser_download_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleaseAttachmentsOptions options for listing release's attachments
|
||||||
|
type ListReleaseAttachmentsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleaseAttachments list release's attachments
|
||||||
|
func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
attachments := make([]*Attachment, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d/assets?%s", user, repo, release, opt.getURLQuery().Encode()),
|
||||||
|
nil, nil, &attachments)
|
||||||
|
return attachments, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReleaseAttachment returns the requested attachment
|
||||||
|
func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
a := new(Attachment)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id),
|
||||||
|
nil, nil, &a)
|
||||||
|
return a, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReleaseAttachment creates an attachment for the given release
|
||||||
|
func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
// Write file to body
|
||||||
|
body := new(bytes.Buffer)
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
part, err := writer.CreateFormFile("attachment", filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = io.Copy(part, file); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err = writer.Close(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
attachment := new(Attachment)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release),
|
||||||
|
http.Header{"Content-Type": {writer.FormDataContentType()}}, body, &attachment)
|
||||||
|
return attachment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditAttachmentOptions options for editing attachments
|
||||||
|
type EditAttachmentOptions struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditReleaseAttachment updates the given attachment with the given options
|
||||||
|
func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
attach := new(Attachment)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, attachment), jsonHeader, bytes.NewReader(body), attach)
|
||||||
|
return attach, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteReleaseAttachment deletes the given attachment including the uploaded file
|
||||||
|
func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
347
vendor/code.gitea.io/sdk/gitea/client.go
generated
vendored
Normal file
347
vendor/code.gitea.io/sdk/gitea/client.go
generated
vendored
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 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 (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
var jsonHeader = http.Header{"content-type": []string{"application/json"}}
|
||||||
|
|
||||||
|
// Version return the library version
|
||||||
|
func Version() string {
|
||||||
|
return "0.15.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client represents a thread-safe Gitea API client.
|
||||||
|
type Client struct {
|
||||||
|
url string
|
||||||
|
accessToken string
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
otp string
|
||||||
|
sudo string
|
||||||
|
debug bool
|
||||||
|
client *http.Client
|
||||||
|
ctx context.Context
|
||||||
|
mutex sync.RWMutex
|
||||||
|
|
||||||
|
serverVersion *version.Version
|
||||||
|
getVersionOnce sync.Once
|
||||||
|
ignoreVersion bool // only set by SetGiteaVersion so don't need a mutex lock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response represents the gitea response
|
||||||
|
type Response struct {
|
||||||
|
*http.Response
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientOption are functions used to init a new client
|
||||||
|
type ClientOption func(*Client) error
|
||||||
|
|
||||||
|
// NewClient initializes and returns a API client.
|
||||||
|
// Usage of all gitea.Client methods is concurrency-safe.
|
||||||
|
func NewClient(url string, options ...ClientOption) (*Client, error) {
|
||||||
|
client := &Client{
|
||||||
|
url: strings.TrimSuffix(url, "/"),
|
||||||
|
client: &http.Client{},
|
||||||
|
ctx: context.Background(),
|
||||||
|
}
|
||||||
|
for _, opt := range options {
|
||||||
|
if err := opt(client); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := client.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClientWithHTTP creates an API client with a custom http client
|
||||||
|
// Deprecated use SetHTTPClient option
|
||||||
|
func NewClientWithHTTP(url string, httpClient *http.Client) *Client {
|
||||||
|
client, _ := NewClient(url, SetHTTPClient(httpClient))
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHTTPClient is an option for NewClient to set custom http client
|
||||||
|
func SetHTTPClient(httpClient *http.Client) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetHTTPClient(httpClient)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHTTPClient replaces default http.Client with user given one.
|
||||||
|
func (c *Client) SetHTTPClient(client *http.Client) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.client = client
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToken is an option for NewClient to set token
|
||||||
|
func SetToken(token string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.mutex.Lock()
|
||||||
|
client.accessToken = token
|
||||||
|
client.mutex.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBasicAuth is an option for NewClient to set username and password
|
||||||
|
func SetBasicAuth(username, password string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetBasicAuth(username, password)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBasicAuth sets username and password
|
||||||
|
func (c *Client) SetBasicAuth(username, password string) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.username, c.password = username, password
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOTP is an option for NewClient to set OTP for 2FA
|
||||||
|
func SetOTP(otp string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetOTP(otp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOTP sets OTP for 2FA
|
||||||
|
func (c *Client) SetOTP(otp string) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.otp = otp
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContext is an option for NewClient to set the default context
|
||||||
|
func SetContext(ctx context.Context) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetContext(ctx)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContext set default context witch is used for http requests
|
||||||
|
func (c *Client) SetContext(ctx context.Context) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.ctx = ctx
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSudo is an option for NewClient to set sudo header
|
||||||
|
func SetSudo(sudo string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetSudo(sudo)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSudo sets username to impersonate.
|
||||||
|
func (c *Client) SetSudo(sudo string) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.sudo = sudo
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDebugMode is an option for NewClient to enable debug mode
|
||||||
|
func SetDebugMode() ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.mutex.Lock()
|
||||||
|
client.debug = true
|
||||||
|
client.mutex.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
debug := c.debug
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("%s: %s\nBody: %v\n", method, c.url+path, body)
|
||||||
|
}
|
||||||
|
req, err := http.NewRequestWithContext(c.ctx, method, c.url+path, body)
|
||||||
|
|
||||||
|
client := c.client // client ref can change from this point on so safe it
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("Response: %v\n\n", resp)
|
||||||
|
}
|
||||||
|
return data, &Response{resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
debug := c.debug
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("%s: %s\nHeader: %v\nBody: %s\n", method, c.url+"/api/v1"+path, header, body)
|
||||||
|
}
|
||||||
|
req, err := http.NewRequestWithContext(c.ctx, method, c.url+"/api/v1"+path, body)
|
||||||
|
if err != nil {
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(c.accessToken) != 0 {
|
||||||
|
req.Header.Set("Authorization", "token "+c.accessToken)
|
||||||
|
}
|
||||||
|
if len(c.otp) != 0 {
|
||||||
|
req.Header.Set("X-GITEA-OTP", c.otp)
|
||||||
|
}
|
||||||
|
if len(c.username) != 0 {
|
||||||
|
req.SetBasicAuth(c.username, c.password)
|
||||||
|
}
|
||||||
|
if len(c.sudo) != 0 {
|
||||||
|
req.Header.Set("Sudo", c.sudo)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := c.client // client ref can change from this point on so safe it
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
|
||||||
|
for k, v := range header {
|
||||||
|
req.Header[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("Response: %v\n\n", resp)
|
||||||
|
}
|
||||||
|
return &Response{resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a response for a HTTP status code indicating an error condition
|
||||||
|
// (non-2XX) to a well-known error value and response body. For non-problematic
|
||||||
|
// (2XX) status codes nil will be returned. Note that on a non-2XX response, the
|
||||||
|
// response body stream will have been read and, hence, is closed on return.
|
||||||
|
func statusCodeToErr(resp *Response) (body []byte, err error) {
|
||||||
|
// no error
|
||||||
|
if resp.StatusCode/100 == 2 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// error: body will be read for details
|
||||||
|
//
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 403:
|
||||||
|
return data, errors.New("403 Forbidden")
|
||||||
|
case 404:
|
||||||
|
return data, errors.New("404 Not Found")
|
||||||
|
case 409:
|
||||||
|
return data, errors.New("409 Conflict")
|
||||||
|
case 422:
|
||||||
|
return data, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
path := resp.Request.URL.Path
|
||||||
|
method := resp.Request.Method
|
||||||
|
header := resp.Request.Header
|
||||||
|
errMap := make(map[string]interface{})
|
||||||
|
if err = json.Unmarshal(data, &errMap); err != nil {
|
||||||
|
// when the JSON can't be parsed, data was probably empty or a
|
||||||
|
// plain string, so we try to return a helpful error anyway
|
||||||
|
return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
|
||||||
|
}
|
||||||
|
return data, errors.New(errMap["message"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) {
|
||||||
|
resp, err := c.doRequest(method, path, header, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
data, err := statusCodeToErr(resp)
|
||||||
|
if err != nil {
|
||||||
|
return data, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// success (2XX), read body
|
||||||
|
data, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) (*Response, error) {
|
||||||
|
data, resp, err := c.getResponse(method, path, header, body)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
return resp, json.Unmarshal(data, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getStatusCode(method, path string, header http.Header, body io.Reader) (int, *Response, error) {
|
||||||
|
resp, err := c.doRequest(method, path, header, body)
|
||||||
|
if err != nil {
|
||||||
|
return -1, resp, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return resp.StatusCode, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pathEscapeSegments escapes segments of a path while not escaping forward slash
|
||||||
|
func pathEscapeSegments(path string) string {
|
||||||
|
slice := strings.Split(path, "/")
|
||||||
|
for index := range slice {
|
||||||
|
slice[index] = url.PathEscape(slice[index])
|
||||||
|
}
|
||||||
|
escapedPath := strings.Join(slice, "/")
|
||||||
|
return escapedPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// escapeValidatePathSegments is a help function to validate and encode url path segments
|
||||||
|
func escapeValidatePathSegments(seg ...*string) error {
|
||||||
|
for i := range seg {
|
||||||
|
if seg[i] == nil || len(*seg[i]) == 0 {
|
||||||
|
return fmt.Errorf("path segment [%d] is empty", i)
|
||||||
|
}
|
||||||
|
*seg[i] = url.PathEscape(*seg[i])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
5
vendor/code.gitea.io/sdk/gitea/doc.go
generated
vendored
Normal file
5
vendor/code.gitea.io/sdk/gitea/doc.go
generated
vendored
Normal 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"
|
49
vendor/code.gitea.io/sdk/gitea/fork.go
generated
vendored
Normal file
49
vendor/code.gitea.io/sdk/gitea/fork.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListForksOptions options for listing repository's forks
|
||||||
|
type ListForksOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListForks list a repository's forks
|
||||||
|
func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
forks := make([]*Repository, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/forks?%s", user, repo, opt.getURLQuery().Encode()),
|
||||||
|
nil, nil, &forks)
|
||||||
|
return forks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateForkOption options for creating a fork
|
||||||
|
type CreateForkOption struct {
|
||||||
|
// organization name, if forking into an organization
|
||||||
|
Organization *string `json:"organization"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFork create a fork of a repository
|
||||||
|
func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
fork := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/forks", user, repo), jsonHeader, bytes.NewReader(body), &fork)
|
||||||
|
return fork, resp, err
|
||||||
|
}
|
28
vendor/code.gitea.io/sdk/gitea/git_blob.go
generated
vendored
Normal file
28
vendor/code.gitea.io/sdk/gitea/git_blob.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitBlobResponse represents a git blob
|
||||||
|
type GitBlobResponse struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
Encoding string `json:"encoding"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlob get the blob of a repository file
|
||||||
|
func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
blob := new(GitBlobResponse)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob)
|
||||||
|
return blob, resp, err
|
||||||
|
}
|
71
vendor/code.gitea.io/sdk/gitea/git_hook.go
generated
vendored
Normal file
71
vendor/code.gitea.io/sdk/gitea/git_hook.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitHook represents a Git repository hook
|
||||||
|
type GitHook struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
IsActive bool `json:"is_active"`
|
||||||
|
Content string `json:"content,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoGitHooksOptions options for listing repository's githooks
|
||||||
|
type ListRepoGitHooksOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoGitHooks list all the Git hooks of one repository
|
||||||
|
func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
hooks := make([]*GitHook, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||||
|
return hooks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoGitHook get a Git hook of a repository
|
||||||
|
func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(GitHook)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditGitHookOption options when modifying one Git hook
|
||||||
|
type EditGitHookOption struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepoGitHook modify one Git hook of a repository
|
||||||
|
func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoGitHook delete one Git hook from a repository
|
||||||
|
func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
20
vendor/code.gitea.io/sdk/gitea/helper.go
generated
vendored
Normal file
20
vendor/code.gitea.io/sdk/gitea/helper.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2020 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
|
||||||
|
|
||||||
|
// OptionalBool convert a bool to a bool reference
|
||||||
|
func OptionalBool(v bool) *bool {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionalString convert a string to a string reference
|
||||||
|
func OptionalString(v string) *string {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionalInt64 convert a int64 to a int64 reference
|
||||||
|
func OptionalInt64(v int64) *int64 {
|
||||||
|
return &v
|
||||||
|
}
|
194
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
Normal file
194
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// 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"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HookType represent all webhook types gitea currently offer
|
||||||
|
type HookType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// HookTypeDingtalk webhook that dingtalk understand
|
||||||
|
HookTypeDingtalk HookType = "dingtalk"
|
||||||
|
// HookTypeDiscord webhook that discord understand
|
||||||
|
HookTypeDiscord HookType = "discord"
|
||||||
|
// HookTypeGitea webhook that gitea understand
|
||||||
|
HookTypeGitea HookType = "gitea"
|
||||||
|
// HookTypeGogs webhook that gogs understand
|
||||||
|
HookTypeGogs HookType = "gogs"
|
||||||
|
// HookTypeMsteams webhook that msteams understand
|
||||||
|
HookTypeMsteams HookType = "msteams"
|
||||||
|
// HookTypeSlack webhook that slack understand
|
||||||
|
HookTypeSlack HookType = "slack"
|
||||||
|
// HookTypeTelegram webhook that telegram understand
|
||||||
|
HookTypeTelegram HookType = "telegram"
|
||||||
|
// HookTypeFeishu webhook that feishu understand
|
||||||
|
HookTypeFeishu HookType = "feishu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListHooksOptions options for listing hooks
|
||||||
|
type ListHooksOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgHooks list all the hooks of one organization
|
||||||
|
func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
hooks := make([]*Hook, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||||
|
return hooks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoHooks list all the hooks of one repository
|
||||||
|
func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
hooks := make([]*Hook, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||||
|
return hooks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgHook get a hook of an organization
|
||||||
|
func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoHook get a hook of a repository
|
||||||
|
func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHookOption options when create a hook
|
||||||
|
type CreateHookOption struct {
|
||||||
|
Type HookType `json:"type"`
|
||||||
|
Config map[string]string `json:"config"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
BranchFilter string `json:"branch_filter"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateHookOption struct
|
||||||
|
func (opt CreateHookOption) Validate() error {
|
||||||
|
if len(opt.Type) == 0 {
|
||||||
|
return fmt.Errorf("hook type needed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrgHook create one hook for an organization, with options
|
||||||
|
func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/hooks", org), jsonHeader, bytes.NewReader(body), h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepoHook create one hook for a repository, with options
|
||||||
|
func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditHookOption options when modify one hook
|
||||||
|
type EditHookOption struct {
|
||||||
|
Config map[string]string `json:"config"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
BranchFilter string `json:"branch_filter"`
|
||||||
|
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) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepoHook modify one hook of a repository, with hook id and options
|
||||||
|
func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrgHook delete one hook from an organization, with hook id
|
||||||
|
func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoHook delete one hook from a repository, with hook id
|
||||||
|
func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
288
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
Normal file
288
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PullRequestMeta PR info if an issue is a PR
|
||||||
|
type PullRequestMeta struct {
|
||||||
|
HasMerged bool `json:"merged"`
|
||||||
|
Merged *time.Time `json:"merged_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepositoryMeta basic repository information
|
||||||
|
type RepositoryMeta struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue represents an issue in a repository
|
||||||
|
type Issue struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
Index int64 `json:"number"`
|
||||||
|
Poster *User `json:"user"`
|
||||||
|
OriginalAuthor string `json:"original_author"`
|
||||||
|
OriginalAuthorID int64 `json:"original_author_id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Labels []*Label `json:"labels"`
|
||||||
|
Milestone *Milestone `json:"milestone"`
|
||||||
|
Assignees []*User `json:"assignees"`
|
||||||
|
// Whether the issue is open or closed
|
||||||
|
State StateType `json:"state"`
|
||||||
|
IsLocked bool `json:"is_locked"`
|
||||||
|
Comments int `json:"comments"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
PullRequest *PullRequestMeta `json:"pull_request"`
|
||||||
|
Repository *RepositoryMeta `json:"repository"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueOption list issue options
|
||||||
|
type ListIssueOption struct {
|
||||||
|
ListOptions
|
||||||
|
State StateType
|
||||||
|
Type IssueType
|
||||||
|
Labels []string
|
||||||
|
Milestones []string
|
||||||
|
KeyWord string
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
// filter by created by username
|
||||||
|
CreatedBy string
|
||||||
|
// filter by assigned to username
|
||||||
|
AssignedBy string
|
||||||
|
// filter by username mentioned
|
||||||
|
MentionedBy string
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateType issue state type
|
||||||
|
type StateType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StateOpen pr/issue is opend
|
||||||
|
StateOpen StateType = "open"
|
||||||
|
// StateClosed pr/issue is closed
|
||||||
|
StateClosed StateType = "closed"
|
||||||
|
// StateAll is all
|
||||||
|
StateAll StateType = "all"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IssueType is issue a pull or only an issue
|
||||||
|
type IssueType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// IssueTypeAll pr and issue
|
||||||
|
IssueTypeAll IssueType = ""
|
||||||
|
// IssueTypeIssue only issues
|
||||||
|
IssueTypeIssue IssueType = "issues"
|
||||||
|
// IssueTypePull only pulls
|
||||||
|
IssueTypePull IssueType = "pulls"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListIssueOption) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
|
||||||
|
if len(opt.State) > 0 {
|
||||||
|
query.Add("state", string(opt.State))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.Labels) > 0 {
|
||||||
|
query.Add("labels", strings.Join(opt.Labels, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.KeyWord) > 0 {
|
||||||
|
query.Add("q", opt.KeyWord)
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Add("type", string(opt.Type))
|
||||||
|
|
||||||
|
if len(opt.Milestones) > 0 {
|
||||||
|
query.Add("milestones", strings.Join(opt.Milestones, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.CreatedBy) > 0 {
|
||||||
|
query.Add("created_by", opt.CreatedBy)
|
||||||
|
}
|
||||||
|
if len(opt.AssignedBy) > 0 {
|
||||||
|
query.Add("assigned_by", opt.AssignedBy)
|
||||||
|
}
|
||||||
|
if len(opt.MentionedBy) > 0 {
|
||||||
|
query.Add("mentioned_by", opt.MentionedBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssues returns all issues assigned the authenticated user
|
||||||
|
func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
issues := make([]*Issue, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse("/repos/issues/search")
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
|
||||||
|
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil {
|
||||||
|
for i := 0; i < len(issues); i++ {
|
||||||
|
if issues[i].Repository != nil {
|
||||||
|
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range issues {
|
||||||
|
c.issueBackwardsCompatibility(issues[i])
|
||||||
|
}
|
||||||
|
return issues, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoIssues returns all issues for a given repository
|
||||||
|
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
issues := make([]*Issue, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
|
||||||
|
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil {
|
||||||
|
for i := 0; i < len(issues); i++ {
|
||||||
|
if issues[i].Repository != nil {
|
||||||
|
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range issues {
|
||||||
|
c.issueBackwardsCompatibility(issues[i])
|
||||||
|
}
|
||||||
|
return issues, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssue returns a single issue for a given repository
|
||||||
|
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
issue := new(Issue)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
|
||||||
|
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil && issue.Repository != nil {
|
||||||
|
issue.Repository.Owner = strings.Split(issue.Repository.FullName, "/")[0]
|
||||||
|
}
|
||||||
|
c.issueBackwardsCompatibility(issue)
|
||||||
|
return issue, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueOption options to create one issue
|
||||||
|
type CreateIssueOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
// milestone id
|
||||||
|
Milestone int64 `json:"milestone"`
|
||||||
|
// list of label ids
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
Closed bool `json:"closed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateIssueOption struct
|
||||||
|
func (opt CreateIssueOption) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssue create a new issue for a given repository
|
||||||
|
func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
issue := new(Issue)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), issue)
|
||||||
|
c.issueBackwardsCompatibility(issue)
|
||||||
|
return issue, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssueOption options for editing an issue
|
||||||
|
type EditIssueOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body *string `json:"body"`
|
||||||
|
Ref *string `json:"ref"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Milestone *int64 `json:"milestone"`
|
||||||
|
State *StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
RemoveDeadline *bool `json:"unset_due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditIssueOption struct
|
||||||
|
func (opt EditIssueOption) Validate() error {
|
||||||
|
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssue modify an existing issue for a given repository
|
||||||
|
func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
issue := new(Issue)
|
||||||
|
resp, err := c.getParsedResponse("PATCH",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), issue)
|
||||||
|
c.issueBackwardsCompatibility(issue)
|
||||||
|
return issue, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) issueBackwardsCompatibility(issue *Issue) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
|
||||||
|
c.mutex.RLock()
|
||||||
|
issue.HTMLURL = fmt.Sprintf("%s/%s/issues/%d", c.url, issue.Repository.FullName, issue.Index)
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
154
vendor/code.gitea.io/sdk/gitea/issue_comment.go
generated
vendored
Normal file
154
vendor/code.gitea.io/sdk/gitea/issue_comment.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// 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"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Comment represents a comment on a commit or issue
|
||||||
|
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"`
|
||||||
|
OriginalAuthor string `json:"original_author"`
|
||||||
|
OriginalAuthorID int64 `json:"original_author_id"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueCommentOptions list comment options
|
||||||
|
type ListIssueCommentOptions struct {
|
||||||
|
ListOptions
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListIssueCommentOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueComments list comments on an issue.
|
||||||
|
func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
comments := make([]*Comment, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments)
|
||||||
|
return comments, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoIssueComments list comments for a given repo.
|
||||||
|
func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
comments := make([]*Comment, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments)
|
||||||
|
return comments, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueComment get a comment for a given repo by id.
|
||||||
|
func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
comment := new(Comment)
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return comment, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, id), nil, nil, &comment)
|
||||||
|
return comment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueCommentOption options for creating a comment on an issue
|
||||||
|
type CreateIssueCommentOption struct {
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateIssueCommentOption struct
|
||||||
|
func (opt CreateIssueCommentOption) Validate() error {
|
||||||
|
if len(opt.Body) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueComment create comment on an issue.
|
||||||
|
func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
comment := new(Comment)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment)
|
||||||
|
return comment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssueCommentOption options for editing a comment
|
||||||
|
type EditIssueCommentOption struct {
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditIssueCommentOption struct
|
||||||
|
func (opt EditIssueCommentOption) Validate() error {
|
||||||
|
if len(opt.Body) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssueComment edits an issue comment.
|
||||||
|
func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
comment := new(Comment)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), jsonHeader, bytes.NewReader(body), comment)
|
||||||
|
return comment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueComment deletes an issue comment.
|
||||||
|
func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
211
vendor/code.gitea.io/sdk/gitea/issue_label.go
generated
vendored
Normal file
211
vendor/code.gitea.io/sdk/gitea/issue_label.go
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
// 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"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Label a label to an issue or a pr
|
||||||
|
type Label struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
// example: 00aabb
|
||||||
|
Color string `json:"color"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLabelsOptions options for listing repository's labels
|
||||||
|
type ListLabelsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoLabels list labels of one repository
|
||||||
|
func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
labels := make([]*Label, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoLabel get one label of repository by repo it
|
||||||
|
func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
label := new(Label)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
|
||||||
|
return label, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateLabelOption options for creating a label
|
||||||
|
type CreateLabelOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
// example: #00aabb
|
||||||
|
Color string `json:"color"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateLabelOption struct
|
||||||
|
func (opt CreateLabelOption) Validate() error {
|
||||||
|
aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !aw {
|
||||||
|
return fmt.Errorf("invalid color format")
|
||||||
|
}
|
||||||
|
if len(strings.TrimSpace(opt.Name)) == 0 {
|
||||||
|
return fmt.Errorf("empty name not allowed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateLabel create one label of repository
|
||||||
|
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(opt.Color) == 6 {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
opt.Color = "#" + opt.Color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
label := new(Label)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/labels", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), label)
|
||||||
|
return label, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditLabelOption options for editing a label
|
||||||
|
type EditLabelOption struct {
|
||||||
|
Name *string `json:"name"`
|
||||||
|
Color *string `json:"color"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditLabelOption struct
|
||||||
|
func (opt EditLabelOption) Validate() error {
|
||||||
|
if opt.Color != nil {
|
||||||
|
aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", *opt.Color)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !aw {
|
||||||
|
return fmt.Errorf("invalid color format")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opt.Name != nil {
|
||||||
|
if len(strings.TrimSpace(*opt.Name)) == 0 {
|
||||||
|
return fmt.Errorf("empty name not allowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditLabel modify one label with options
|
||||||
|
func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
label := new(Label)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label)
|
||||||
|
return label, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteLabel delete one label of repository by id
|
||||||
|
func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueLabels get labels of one issue via issue id
|
||||||
|
func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
labels := make([]*Label, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueLabelsOption a collection of labels
|
||||||
|
type IssueLabelsOption struct {
|
||||||
|
// list of label IDs
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIssueLabels add one or more labels to one issue
|
||||||
|
func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var labels []*Label
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceIssueLabels replace old labels of issue with new labels
|
||||||
|
func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var labels []*Label
|
||||||
|
resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearIssueLabels delete all the labels of one issue.
|
||||||
|
func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
237
vendor/code.gitea.io/sdk/gitea/issue_milestone.go
generated
vendored
Normal file
237
vendor/code.gitea.io/sdk/gitea/issue_milestone.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
// 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"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"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"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated *time.Time `json:"updated_at"`
|
||||||
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
Deadline *time.Time `json:"due_on"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMilestoneOption list milestone options
|
||||||
|
type ListMilestoneOption struct {
|
||||||
|
ListOptions
|
||||||
|
// open, closed, all
|
||||||
|
State StateType
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListMilestoneOption) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if opt.State != "" {
|
||||||
|
query.Add("state", string(opt.State))
|
||||||
|
}
|
||||||
|
if len(opt.Name) != 0 {
|
||||||
|
query.Add("name", opt.Name)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoMilestones list all the milestones of one repository
|
||||||
|
func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
milestones := make([]*Milestone, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/milestones", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &milestones)
|
||||||
|
return milestones, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMilestone get one milestone by repo name and milestone id
|
||||||
|
func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMilestoneByName get one milestone by repo and milestone name
|
||||||
|
func (c *Client) GetMilestoneByName(owner, repo string, name string) (*Milestone, *Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
// backwards compatibility mode
|
||||||
|
m, resp, err := c.resolveMilestoneByName(owner, repo, name)
|
||||||
|
return m, resp, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil, milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMilestoneOption options for creating a milestone
|
||||||
|
type CreateMilestoneOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
State StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_on"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateMilestoneOption struct
|
||||||
|
func (opt CreateMilestoneOption) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMilestone create one milestone with options
|
||||||
|
func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
|
||||||
|
|
||||||
|
// make creating closed milestones need gitea >= v1.13.0
|
||||||
|
// this make it backwards compatible
|
||||||
|
if err == nil && opt.State == StateClosed && milestone.State != StateClosed {
|
||||||
|
closed := StateClosed
|
||||||
|
return c.EditMilestone(owner, repo, milestone.ID, EditMilestoneOption{
|
||||||
|
State: &closed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditMilestoneOption options for editing a milestone
|
||||||
|
type EditMilestoneOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
State *StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_on"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditMilestoneOption struct
|
||||||
|
func (opt EditMilestoneOption) Validate() error {
|
||||||
|
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditMilestone modify milestone with options
|
||||||
|
func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditMilestoneByName modify milestone with options
|
||||||
|
func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMilestoneOption) (*Milestone, *Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
// backwards compatibility mode
|
||||||
|
m, _, err := c.resolveMilestoneByName(owner, repo, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return c.EditMilestone(owner, repo, m.ID, opt)
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMilestone delete one milestone by id
|
||||||
|
func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMilestoneByName delete one milestone by name
|
||||||
|
func (c *Client) DeleteMilestoneByName(owner, repo string, name string) (*Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
// backwards compatibility mode
|
||||||
|
m, _, err := c.resolveMilestoneByName(owner, repo, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.DeleteMilestone(owner, repo, m.ID)
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveMilestoneByName is a fallback method to find milestone id by name
|
||||||
|
func (c *Client) resolveMilestoneByName(owner, repo, name string) (*Milestone, *Response, error) {
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
miles, resp, err := c.ListRepoMilestones(owner, repo, ListMilestoneOption{
|
||||||
|
ListOptions: ListOptions{
|
||||||
|
Page: i,
|
||||||
|
},
|
||||||
|
State: "all",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(miles) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("milestone '%s' do not exist", name)
|
||||||
|
}
|
||||||
|
for _, m := range miles {
|
||||||
|
if strings.ToLower(strings.TrimSpace(m.Title)) == strings.ToLower(strings.TrimSpace(name)) {
|
||||||
|
return m, resp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
vendor/code.gitea.io/sdk/gitea/issue_reaction.go
generated
vendored
Normal file
104
vendor/code.gitea.io/sdk/gitea/issue_reaction.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reaction contain one reaction
|
||||||
|
type Reaction struct {
|
||||||
|
User *User `json:"user"`
|
||||||
|
Reaction string `json:"content"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueReactions get a list reactions of an issue
|
||||||
|
func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactions := make([]*Reaction, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions)
|
||||||
|
return reactions, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueCommentReactions get a list of reactions from a comment of an issue
|
||||||
|
func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactions := make([]*Reaction, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions)
|
||||||
|
return reactions, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// editReactionOption contain the reaction type
|
||||||
|
type editReactionOption struct {
|
||||||
|
Reaction string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostIssueReaction add a reaction to an issue
|
||||||
|
func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactionResponse := new(Reaction)
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), reactionResponse)
|
||||||
|
return reactionResponse, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueReaction remove a reaction from an issue
|
||||||
|
func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostIssueCommentReaction add a reaction to a comment of an issue
|
||||||
|
func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactionResponse := new(Reaction)
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID),
|
||||||
|
jsonHeader, bytes.NewReader(body), reactionResponse)
|
||||||
|
return reactionResponse, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueCommentReaction remove a reaction from a comment of an issue
|
||||||
|
func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
57
vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
generated
vendored
Normal file
57
vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StopWatch represents a running stopwatch of an issue / pr
|
||||||
|
type StopWatch struct {
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Seconds int64 `json:"seconds"`
|
||||||
|
Duration string `json:"duration"`
|
||||||
|
IssueIndex int64 `json:"issue_index"`
|
||||||
|
IssueTitle string `json:"issue_title"`
|
||||||
|
RepoOwnerName string `json:"repo_owner_name"`
|
||||||
|
RepoName string `json:"repo_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyStopwatches list all stopwatches
|
||||||
|
func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) {
|
||||||
|
stopwatches := make([]*StopWatch, 0, 1)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/stopwatches", nil, nil, &stopwatches)
|
||||||
|
return stopwatches, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueStopwatch delete / cancel a specific stopwatch
|
||||||
|
func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartIssueStopWatch starts a stopwatch for an existing issue for a given
|
||||||
|
// repository
|
||||||
|
func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopIssueStopWatch stops an existing stopwatch for an issue in a given
|
||||||
|
// repository
|
||||||
|
func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
87
vendor/code.gitea.io/sdk/gitea/issue_subscription.go
generated
vendored
Normal file
87
vendor/code.gitea.io/sdk/gitea/issue_subscription.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetIssueSubscribers get list of users who subscribed on an issue
|
||||||
|
func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
subscribers := make([]*User, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers)
|
||||||
|
return subscribers, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIssueSubscription Subscribe user to issue
|
||||||
|
func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusCreated {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
if status == http.StatusOK {
|
||||||
|
return resp, fmt.Errorf("already subscribed")
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueSubscription unsubscribe user from issue
|
||||||
|
func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusCreated {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
if status == http.StatusOK {
|
||||||
|
return resp, fmt.Errorf("already unsubscribed")
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckIssueSubscription check if current user is subscribed to an issue
|
||||||
|
func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
wi := new(WatchInfo)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/check", owner, repo, index), nil, nil, wi)
|
||||||
|
return wi, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueSubscribe subscribe current user to an issue
|
||||||
|
func (c *Client) IssueSubscribe(owner, repo string, index int64) (*Response, error) {
|
||||||
|
u, _, err := c.GetMyUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.AddIssueSubscription(owner, repo, index, u.UserName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueUnSubscribe unsubscribe current user from an issue
|
||||||
|
func (c *Client) IssueUnSubscribe(owner, repo string, index int64) (*Response, error) {
|
||||||
|
u, _, err := c.GetMyUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.DeleteIssueSubscription(owner, repo, index, u.UserName)
|
||||||
|
}
|
142
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
generated
vendored
Normal file
142
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// 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"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TrackedTime worked time for an issue / pr
|
||||||
|
type TrackedTime struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
// Time in seconds
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
// deprecated (only for backwards compatibility)
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
UserName string `json:"user_name"`
|
||||||
|
// deprecated (only for backwards compatibility)
|
||||||
|
IssueID int64 `json:"issue_id"`
|
||||||
|
Issue *Issue `json:"issue"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTrackedTimesOptions options for listing repository's tracked times
|
||||||
|
type ListTrackedTimesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
// User filter is only used by ListRepoTrackedTimes !!!
|
||||||
|
User string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListTrackedTimesOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.User) != 0 {
|
||||||
|
query.Add("user", opt.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTrackedTimes list tracked times of a repository
|
||||||
|
func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/times", owner, repo))
|
||||||
|
opt.setDefaults()
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
times := make([]*TrackedTime, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
|
||||||
|
return times, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyTrackedTimes list tracked times of the current user
|
||||||
|
func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) {
|
||||||
|
times := make([]*TrackedTime, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, ×)
|
||||||
|
return times, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTimeOption options for adding time to an issue
|
||||||
|
type AddTimeOption struct {
|
||||||
|
// time in seconds
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
// optional
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
// optional
|
||||||
|
User string `json:"user_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the AddTimeOption struct
|
||||||
|
func (opt AddTimeOption) Validate() error {
|
||||||
|
if opt.Time == 0 {
|
||||||
|
return fmt.Errorf("no time to add")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTime adds time to issue with the given index
|
||||||
|
func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(TrackedTime)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueTrackedTimes list tracked times of a single issue for a given repository
|
||||||
|
func (c *Client) ListIssueTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index))
|
||||||
|
opt.setDefaults()
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
times := make([]*TrackedTime, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
|
||||||
|
return times, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetIssueTime reset tracked time of a single issue for a given repository
|
||||||
|
func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteTime delete a specific tracked time by id of a single issue for a given repository
|
||||||
|
func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
42
vendor/code.gitea.io/sdk/gitea/list_options.go
generated
vendored
Normal file
42
vendor/code.gitea.io/sdk/gitea/list_options.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2020 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/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultPageSize = 10
|
||||||
|
const maxPageSize = 50
|
||||||
|
|
||||||
|
// ListOptions options for using Gitea's API pagination
|
||||||
|
type ListOptions struct {
|
||||||
|
Page int
|
||||||
|
PageSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ListOptions) getURLQuery() url.Values {
|
||||||
|
query := make(url.Values)
|
||||||
|
query.Add("page", fmt.Sprintf("%d", o.Page))
|
||||||
|
query.Add("limit", fmt.Sprintf("%d", o.PageSize))
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// setDefaults set default pagination options if none or wrong are set
|
||||||
|
// if you set -1 as page it will set all to 0
|
||||||
|
func (o *ListOptions) setDefaults() {
|
||||||
|
if o.Page < 0 {
|
||||||
|
o.Page, o.PageSize = 0, 0
|
||||||
|
return
|
||||||
|
} else if o.Page == 0 {
|
||||||
|
o.Page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.PageSize < 0 || o.PageSize > maxPageSize {
|
||||||
|
o.PageSize = defaultPageSize
|
||||||
|
}
|
||||||
|
}
|
241
vendor/code.gitea.io/sdk/gitea/notifications.go
generated
vendored
Normal file
241
vendor/code.gitea.io/sdk/gitea/notifications.go
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
// Copyright 2020 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/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
version1_12_3, _ = version.NewVersion("1.12.3")
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotificationThread expose Notification on API
|
||||||
|
type NotificationThread struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Repository *Repository `json:"repository"`
|
||||||
|
Subject *NotificationSubject `json:"subject"`
|
||||||
|
Unread bool `json:"unread"`
|
||||||
|
Pinned bool `json:"pinned"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotificationSubject contains the notification subject (Issue/Pull/Commit)
|
||||||
|
type NotificationSubject struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
LatestCommentURL string `json:"latest_comment_url"`
|
||||||
|
Type NotifySubjectType `json:"type"`
|
||||||
|
State NotifySubjectState `json:"state"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyStatus notification status type
|
||||||
|
type NotifyStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NotifyStatusUnread was not read
|
||||||
|
NotifyStatusUnread NotifyStatus = "unread"
|
||||||
|
// NotifyStatusRead was already read by user
|
||||||
|
NotifyStatusRead NotifyStatus = "read"
|
||||||
|
// NotifyStatusPinned notification is pinned by user
|
||||||
|
NotifyStatusPinned NotifyStatus = "pinned"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotifySubjectType represent type of notification subject
|
||||||
|
type NotifySubjectType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NotifySubjectIssue an issue is subject of an notification
|
||||||
|
NotifySubjectIssue NotifySubjectType = "Issue"
|
||||||
|
// NotifySubjectPull an pull is subject of an notification
|
||||||
|
NotifySubjectPull NotifySubjectType = "Pull"
|
||||||
|
// NotifySubjectCommit an commit is subject of an notification
|
||||||
|
NotifySubjectCommit NotifySubjectType = "Commit"
|
||||||
|
// NotifySubjectRepository an repository is subject of an notification
|
||||||
|
NotifySubjectRepository NotifySubjectType = "Repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotifySubjectState reflect state of notification subject
|
||||||
|
type NotifySubjectState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NotifySubjectOpen if subject is a pull/issue and is open at the moment
|
||||||
|
NotifySubjectOpen NotifySubjectState = "open"
|
||||||
|
// NotifySubjectClosed if subject is a pull/issue and is closed at the moment
|
||||||
|
NotifySubjectClosed NotifySubjectState = "closed"
|
||||||
|
// NotifySubjectMerged if subject is a pull and got merged
|
||||||
|
NotifySubjectMerged NotifySubjectState = "merged"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListNotificationOptions represents the filter options
|
||||||
|
type ListNotificationOptions struct {
|
||||||
|
ListOptions
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
Status []NotifyStatus
|
||||||
|
SubjectTypes []NotifySubjectType
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkNotificationOptions represents the filter & modify options
|
||||||
|
type MarkNotificationOptions struct {
|
||||||
|
LastReadAt time.Time
|
||||||
|
Status []NotifyStatus
|
||||||
|
ToStatus NotifyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode encode options to url query
|
||||||
|
func (opt *ListNotificationOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
for _, s := range opt.Status {
|
||||||
|
query.Add("status-types", string(s))
|
||||||
|
}
|
||||||
|
for _, s := range opt.SubjectTypes {
|
||||||
|
query.Add("subject-type", string(s))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateUserOption struct
|
||||||
|
func (opt ListNotificationOptions) Validate(c *Client) error {
|
||||||
|
if len(opt.Status) != 0 {
|
||||||
|
return c.checkServerVersionGreaterThanOrEqual(version1_12_3)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode encode options to url query
|
||||||
|
func (opt *MarkNotificationOptions) QueryEncode() string {
|
||||||
|
query := make(url.Values)
|
||||||
|
if !opt.LastReadAt.IsZero() {
|
||||||
|
query.Add("last_read_at", opt.LastReadAt.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
for _, s := range opt.Status {
|
||||||
|
query.Add("status-types", string(s))
|
||||||
|
}
|
||||||
|
if len(opt.ToStatus) != 0 {
|
||||||
|
query.Add("to-status", string(opt.ToStatus))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateUserOption struct
|
||||||
|
func (opt MarkNotificationOptions) Validate(c *Client) error {
|
||||||
|
if len(opt.Status) != 0 || len(opt.ToStatus) != 0 {
|
||||||
|
return c.checkServerVersionGreaterThanOrEqual(version1_12_3)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckNotifications list users's notification threads
|
||||||
|
func (c *Client) CheckNotifications() (int64, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
new := struct {
|
||||||
|
New int64 `json:"new"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", "/notifications/new", jsonHeader, nil, &new)
|
||||||
|
return new.New, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNotification get notification thread by ID
|
||||||
|
func (c *Client) GetNotification(id int64) (*NotificationThread, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
thread := new(NotificationThread)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/notifications/threads/%d", id), nil, nil, thread)
|
||||||
|
return thread, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadNotification mark notification thread as read by ID
|
||||||
|
// It optionally takes a second argument if status has to be set other than 'read'
|
||||||
|
func (c *Client) ReadNotification(id int64, status ...NotifyStatus) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link := fmt.Sprintf("/notifications/threads/%d", id)
|
||||||
|
if len(status) != 0 {
|
||||||
|
link += fmt.Sprintf("?to-status=%s", status[0])
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", link, nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNotifications list users's notification threads
|
||||||
|
func (c *Client) ListNotifications(opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse("/notifications")
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
threads := make([]*NotificationThread, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
|
||||||
|
return threads, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadNotifications mark notification threads as read
|
||||||
|
func (c *Client) ReadNotifications(opt MarkNotificationOptions) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse("/notifications")
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoNotifications list users's notification threads on a specific repo
|
||||||
|
func (c *Client) ListRepoNotifications(owner, repo string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
threads := make([]*NotificationThread, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
|
||||||
|
return threads, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadRepoNotifications mark notification threads as read on a specific repo
|
||||||
|
func (c *Client) ReadRepoNotifications(owner, repo string, opt MarkNotificationOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
91
vendor/code.gitea.io/sdk/gitea/oauth2.go
generated
vendored
Normal file
91
vendor/code.gitea.io/sdk/gitea/oauth2.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Oauth2 represents an Oauth2 Application
|
||||||
|
type Oauth2 struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ClientID string `json:"client_id"`
|
||||||
|
ClientSecret string `json:"client_secret"`
|
||||||
|
RedirectURIs []string `json:"redirect_uris"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOauth2Option for listing Oauth2 Applications
|
||||||
|
type ListOauth2Option struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOauth2Option required options for creating an Application
|
||||||
|
type CreateOauth2Option struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
RedirectURIs []string `json:"redirect_uris"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOauth2 create an Oauth2 Application and returns a completed Oauth2 object.
|
||||||
|
func (c *Client) CreateOauth2(opt CreateOauth2Option) (*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
oauth := new(Oauth2)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/applications/oauth2", jsonHeader, bytes.NewReader(body), oauth)
|
||||||
|
return oauth, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOauth2 a specific Oauth2 Application by ID and return a completed Oauth2 object.
|
||||||
|
func (c *Client) UpdateOauth2(oauth2id int64, opt CreateOauth2Option) (*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
oauth := new(Oauth2)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), jsonHeader, bytes.NewReader(body), oauth)
|
||||||
|
return oauth, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOauth2 a specific Oauth2 Application by ID.
|
||||||
|
func (c *Client) GetOauth2(oauth2id int64) (*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
oauth2s := &Oauth2{}
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil, &oauth2s)
|
||||||
|
return oauth2s, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOauth2 all of your Oauth2 Applications.
|
||||||
|
func (c *Client) ListOauth2(opt ListOauth2Option) ([]*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
oauth2s := make([]*Oauth2, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2?%s", opt.getURLQuery().Encode()), nil, nil, &oauth2s)
|
||||||
|
return oauth2s, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOauth2 delete an Oauth2 application by ID
|
||||||
|
func (c *Client) DeleteOauth2(oauth2id int64) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
155
vendor/code.gitea.io/sdk/gitea/org.go
generated
vendored
Normal file
155
vendor/code.gitea.io/sdk/gitea/org.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Organization represents an organization
|
||||||
|
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"`
|
||||||
|
Visibility string `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleType defines the visibility
|
||||||
|
type VisibleType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// VisibleTypePublic Visible for everyone
|
||||||
|
VisibleTypePublic VisibleType = "public"
|
||||||
|
|
||||||
|
// VisibleTypeLimited Visible for every connected user
|
||||||
|
VisibleTypeLimited VisibleType = "limited"
|
||||||
|
|
||||||
|
// VisibleTypePrivate Visible only for organization's members
|
||||||
|
VisibleTypePrivate VisibleType = "private"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOrgsOptions options for listing organizations
|
||||||
|
type ListOrgsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyOrgs list all of current user's organizations
|
||||||
|
func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
orgs := make([]*Organization, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||||
|
return orgs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUserOrgs list all of some user's organizations
|
||||||
|
func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
orgs := make([]*Organization, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||||
|
return orgs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrg get one organization by name
|
||||||
|
func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
org := new(Organization)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
|
||||||
|
return org, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrgOption options for creating an organization
|
||||||
|
type CreateOrgOption struct {
|
||||||
|
Name string `json:"username"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Visibility VisibleType `json:"visibility"`
|
||||||
|
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkVisibilityOpt check if mode exist
|
||||||
|
func checkVisibilityOpt(v VisibleType) bool {
|
||||||
|
return v == VisibleTypePublic || v == VisibleTypeLimited || v == VisibleTypePrivate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateOrgOption struct
|
||||||
|
func (opt CreateOrgOption) Validate() error {
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("empty org name")
|
||||||
|
}
|
||||||
|
if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) {
|
||||||
|
return fmt.Errorf("infalid bisibility option")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrg creates an organization
|
||||||
|
func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, *Response, error) {
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
org := new(Organization)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/orgs", jsonHeader, bytes.NewReader(body), org)
|
||||||
|
return org, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditOrgOption options for editing an organization
|
||||||
|
type EditOrgOption struct {
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Visibility VisibleType `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditOrgOption struct
|
||||||
|
func (opt EditOrgOption) Validate() error {
|
||||||
|
if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) {
|
||||||
|
return fmt.Errorf("infalid bisibility option")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditOrg modify one organization via options
|
||||||
|
func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrg deletes an organization
|
||||||
|
func (c *Client) DeleteOrg(orgname string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
119
vendor/code.gitea.io/sdk/gitea/org_member.go
generated
vendored
Normal file
119
vendor/code.gitea.io/sdk/gitea/org_member.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteOrgMembership remove a member from an organization
|
||||||
|
func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgMembershipOption list OrgMembership options
|
||||||
|
type ListOrgMembershipOption struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgMembership list an organization's members
|
||||||
|
func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", org))
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPublicOrgMembership list an organization's members
|
||||||
|
func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", org))
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckOrgMembership Check if a user is a member of an organization
|
||||||
|
func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return true, resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPublicOrgMembership Check if a user is a member of an organization
|
||||||
|
func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return true, resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPublicOrgMembership publicize/conceal a user's membership
|
||||||
|
func (c *Client) SetPublicOrgMembership(org, user string, visible bool) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
status int
|
||||||
|
err error
|
||||||
|
resp *Response
|
||||||
|
)
|
||||||
|
if visible {
|
||||||
|
status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||||
|
} else {
|
||||||
|
status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return resp, fmt.Errorf("forbidden")
|
||||||
|
default:
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
242
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
Normal file
242
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Team represents a team in an organization
|
||||||
|
type Team struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Organization *Organization `json:"organization"`
|
||||||
|
Permission AccessMode `json:"permission"`
|
||||||
|
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||||
|
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||||
|
Units []RepoUnitType `json:"units"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoUnitType represent all unit types of a repo gitea currently offer
|
||||||
|
type RepoUnitType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RepoUnitCode represent file view of a repository
|
||||||
|
RepoUnitCode RepoUnitType = "repo.code"
|
||||||
|
// RepoUnitIssues represent issues of a repository
|
||||||
|
RepoUnitIssues RepoUnitType = "repo.issues"
|
||||||
|
// RepoUnitPulls represent pulls of a repository
|
||||||
|
RepoUnitPulls RepoUnitType = "repo.pulls"
|
||||||
|
// RepoUnitExtIssues represent external issues of a repository
|
||||||
|
RepoUnitExtIssues RepoUnitType = "repo.ext_issues"
|
||||||
|
// RepoUnitWiki represent wiki of a repository
|
||||||
|
RepoUnitWiki RepoUnitType = "repo.wiki"
|
||||||
|
// RepoUnitExtWiki represent external wiki of a repository
|
||||||
|
RepoUnitExtWiki RepoUnitType = "repo.ext_wiki"
|
||||||
|
// RepoUnitReleases represent releases of a repository
|
||||||
|
RepoUnitReleases RepoUnitType = "repo.releases"
|
||||||
|
// RepoUnitProjects represent projects of a repository
|
||||||
|
RepoUnitProjects RepoUnitType = "repo.projects"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListTeamsOptions options for listing teams
|
||||||
|
type ListTeamsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgTeams lists all teams of an organization
|
||||||
|
func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
teams := make([]*Team, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams)
|
||||||
|
return teams, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyTeams lists all the teams of the current user
|
||||||
|
func (c *Client) ListMyTeams(opt *ListTeamsOptions) ([]*Team, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
teams := make([]*Team, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/teams?%s", opt.getURLQuery().Encode()), nil, nil, &teams)
|
||||||
|
return teams, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeam gets a team by ID
|
||||||
|
func (c *Client) GetTeam(id int64) (*Team, *Response, error) {
|
||||||
|
t := new(Team)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d", id), nil, nil, t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTeamOption options for creating a team
|
||||||
|
type CreateTeamOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Permission AccessMode `json:"permission"`
|
||||||
|
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||||
|
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||||
|
Units []RepoUnitType `json:"units"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateTeamOption struct
|
||||||
|
func (opt CreateTeamOption) Validate() error {
|
||||||
|
if opt.Permission == AccessModeOwner {
|
||||||
|
opt.Permission = AccessModeAdmin
|
||||||
|
} else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin {
|
||||||
|
return fmt.Errorf("permission mode invalid")
|
||||||
|
}
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("name required")
|
||||||
|
}
|
||||||
|
if len(opt.Name) > 30 {
|
||||||
|
return fmt.Errorf("name to long")
|
||||||
|
}
|
||||||
|
if len(opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("description to long")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTeam creates a team for an organization
|
||||||
|
func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Team)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/teams", org), jsonHeader, bytes.NewReader(body), t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditTeamOption options for editing a team
|
||||||
|
type EditTeamOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
Permission AccessMode `json:"permission"`
|
||||||
|
CanCreateOrgRepo *bool `json:"can_create_org_repo"`
|
||||||
|
IncludesAllRepositories *bool `json:"includes_all_repositories"`
|
||||||
|
Units []RepoUnitType `json:"units"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditTeamOption struct
|
||||||
|
func (opt EditTeamOption) Validate() error {
|
||||||
|
if opt.Permission == AccessModeOwner {
|
||||||
|
opt.Permission = AccessModeAdmin
|
||||||
|
} else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin {
|
||||||
|
return fmt.Errorf("permission mode invalid")
|
||||||
|
}
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("name required")
|
||||||
|
}
|
||||||
|
if len(opt.Name) > 30 {
|
||||||
|
return fmt.Errorf("name to long")
|
||||||
|
}
|
||||||
|
if opt.Description != nil && len(*opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("description to long")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditTeam edits a team of an organization
|
||||||
|
func (c *Client) EditTeam(id int64, opt EditTeamOption) (*Response, error) {
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteTeam deletes a team of an organization
|
||||||
|
func (c *Client) DeleteTeam(id int64) (*Response, error) {
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamMembersOptions options for listing team's members
|
||||||
|
type ListTeamMembersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamMembers lists all members of a team
|
||||||
|
func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
members := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members?%s", id, opt.getURLQuery().Encode()), nil, nil, &members)
|
||||||
|
return members, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamMember gets a member of a team
|
||||||
|
func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
m := new(User)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m)
|
||||||
|
return m, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTeamMember adds a member to a team
|
||||||
|
func (c *Client) AddTeamMember(id int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTeamMember removes a member from a team
|
||||||
|
func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamRepositoriesOptions options for listing team's repositories
|
||||||
|
type ListTeamRepositoriesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamRepositories lists all repositories of a team
|
||||||
|
func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions) ([]*Repository, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos?%s", id, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTeamRepository adds a repository to a team
|
||||||
|
func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTeamRepository removes a repository from a team
|
||||||
|
func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
328
vendor/code.gitea.io/sdk/gitea/pull.go
generated
vendored
Normal file
328
vendor/code.gitea.io/sdk/gitea/pull.go
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PRBranchInfo information about a branch
|
||||||
|
type PRBranchInfo struct {
|
||||||
|
Name string `json:"label"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Sha string `json:"sha"`
|
||||||
|
RepoID int64 `json:"repo_id"`
|
||||||
|
Repository *Repository `json:"repo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullRequest represents a pull request
|
||||||
|
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"`
|
||||||
|
Assignees []*User `json:"assignees"`
|
||||||
|
State StateType `json:"state"`
|
||||||
|
IsLocked bool `json:"is_locked"`
|
||||||
|
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"`
|
||||||
|
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
Created *time.Time `json:"created_at"`
|
||||||
|
Updated *time.Time `json:"updated_at"`
|
||||||
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullRequestsOptions options for listing pull requests
|
||||||
|
type ListPullRequestsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
State StateType `json:"state"`
|
||||||
|
// oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority
|
||||||
|
Sort string
|
||||||
|
Milestone int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeStyle is used specify how a pull is merged
|
||||||
|
type MergeStyle string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MergeStyleMerge merge pull as usual
|
||||||
|
MergeStyleMerge MergeStyle = "merge"
|
||||||
|
// MergeStyleRebase rebase pull
|
||||||
|
MergeStyleRebase MergeStyle = "rebase"
|
||||||
|
// MergeStyleRebaseMerge rebase and merge pull
|
||||||
|
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
|
||||||
|
// MergeStyleSquash squash and merge pull
|
||||||
|
MergeStyleSquash MergeStyle = "squash"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListPullRequestsOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if len(opt.State) > 0 {
|
||||||
|
query.Add("state", string(opt.State))
|
||||||
|
}
|
||||||
|
if len(opt.Sort) > 0 {
|
||||||
|
query.Add("sort", opt.Sort)
|
||||||
|
}
|
||||||
|
if opt.Milestone > 0 {
|
||||||
|
query.Add("milestone", fmt.Sprintf("%d", opt.Milestone))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoPullRequests list PRs of one repository
|
||||||
|
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
prs := make([]*PullRequest, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs)
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
for i := range prs {
|
||||||
|
if err := fixPullHeadSha(c, prs[i]); err != nil {
|
||||||
|
return prs, resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequest get information of one PR
|
||||||
|
func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pr := new(PullRequest)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr)
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
if err := fixPullHeadSha(c, pr); err != nil {
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullRequestOption options when creating a pull request
|
||||||
|
type CreatePullRequestOption struct {
|
||||||
|
Head string `json:"head"`
|
||||||
|
Base string `json:"base"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Assignee string `json:"assignee"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Milestone int64 `json:"milestone"`
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullRequest create pull request with options
|
||||||
|
func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pr := new(PullRequest)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), pr)
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditPullRequestOption options when modify pull request
|
||||||
|
type EditPullRequestOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Base string `json:"base"`
|
||||||
|
Assignee string `json:"assignee"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Milestone int64 `json:"milestone"`
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
State *StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditPullRequestOption struct
|
||||||
|
func (opt EditPullRequestOption) Validate(c *Client) error {
|
||||||
|
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
if len(opt.Base) != 0 {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return fmt.Errorf("can not change base gitea to old")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditPullRequest modify pull request with PR id and options
|
||||||
|
func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pr := new(PullRequest)
|
||||||
|
resp, err := c.getParsedResponse("PATCH",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), pr)
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergePullRequestOption options when merging a pull request
|
||||||
|
type MergePullRequestOption struct {
|
||||||
|
Style MergeStyle `json:"Do"`
|
||||||
|
Title string `json:"MergeTitleField"`
|
||||||
|
Message string `json:"MergeMessageField"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var version1_11_5, _ = version.NewVersion("1.11.5")
|
||||||
|
|
||||||
|
// Validate the MergePullRequestOption struct
|
||||||
|
func (opt MergePullRequestOption) Validate(c *Client) error {
|
||||||
|
if opt.Style == MergeStyleSquash {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_11_5); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergePullRequest merge a PR to repository by PR id
|
||||||
|
func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), jsonHeader, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
return status == 200, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPullRequestMerged test if one PR is merged to one repository
|
||||||
|
func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return status == 204, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPullRequestDiffOrPatch gets the patch or diff file as bytes for a PR
|
||||||
|
func (c *Client) getPullRequestDiffOrPatch(owner, repo, kind string, index int64) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &kind); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
r, _, err2 := c.GetRepo(owner, repo)
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if r.Private {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return c.getWebResponse("GET", fmt.Sprintf("/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil)
|
||||||
|
}
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequestPatch gets the .patch file as bytes for a PR
|
||||||
|
func (c *Client) GetPullRequestPatch(owner, repo string, index int64) ([]byte, *Response, error) {
|
||||||
|
return c.getPullRequestDiffOrPatch(owner, repo, "patch", index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequestDiff gets the .diff file as bytes for a PR
|
||||||
|
func (c *Client) GetPullRequestDiff(owner, repo string, index int64) ([]byte, *Response, error) {
|
||||||
|
return c.getPullRequestDiffOrPatch(owner, repo, "diff", index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullRequestCommitsOptions options for listing pull requests
|
||||||
|
type ListPullRequestCommitsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullRequestCommits list commits for a pull request
|
||||||
|
func (c *Client) ListPullRequestCommits(owner, repo string, index int64, opt ListPullRequestCommitsOptions) ([]*Commit, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/commits", owner, repo, index))
|
||||||
|
opt.setDefaults()
|
||||||
|
commits := make([]*Commit, 0, opt.PageSize)
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
|
||||||
|
return commits, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
|
||||||
|
// When no head sha is available, this is because the branch got deleted in the base repo.
|
||||||
|
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
|
||||||
|
// which stays available to resolve the commit sha. This is fixed for gitea >= 1.14.0
|
||||||
|
func fixPullHeadSha(client *Client, pr *PullRequest) error {
|
||||||
|
if pr.Base != nil && pr.Base.Repository != nil && pr.Base.Repository.Owner != nil &&
|
||||||
|
pr.Head != nil && pr.Head.Ref != "" && pr.Head.Sha == "" {
|
||||||
|
owner := pr.Base.Repository.Owner.UserName
|
||||||
|
repo := pr.Base.Repository.Name
|
||||||
|
refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(refs) == 0 {
|
||||||
|
return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
|
||||||
|
}
|
||||||
|
pr.Head.Sha = refs[0].Object.SHA
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
325
vendor/code.gitea.io/sdk/gitea/pull_review.go
generated
vendored
Normal file
325
vendor/code.gitea.io/sdk/gitea/pull_review.go
generated
vendored
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReviewStateType review state type
|
||||||
|
type ReviewStateType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ReviewStateApproved pr is approved
|
||||||
|
ReviewStateApproved ReviewStateType = "APPROVED"
|
||||||
|
// ReviewStatePending pr state is pending
|
||||||
|
ReviewStatePending ReviewStateType = "PENDING"
|
||||||
|
// ReviewStateComment is a comment review
|
||||||
|
ReviewStateComment ReviewStateType = "COMMENT"
|
||||||
|
// ReviewStateRequestChanges changes for pr are requested
|
||||||
|
ReviewStateRequestChanges ReviewStateType = "REQUEST_CHANGES"
|
||||||
|
// ReviewStateRequestReview review is requested from user
|
||||||
|
ReviewStateRequestReview ReviewStateType = "REQUEST_REVIEW"
|
||||||
|
// ReviewStateUnknown state of pr is unknown
|
||||||
|
ReviewStateUnknown ReviewStateType = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
// PullReview represents a pull request review
|
||||||
|
type PullReview struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Reviewer *User `json:"user"`
|
||||||
|
ReviewerTeam *Team `json:"team"`
|
||||||
|
State ReviewStateType `json:"state"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
CommitID string `json:"commit_id"`
|
||||||
|
// Stale indicates if the pull has changed since the review
|
||||||
|
Stale bool `json:"stale"`
|
||||||
|
// Official indicates if the review counts towards the required approval limit, if PR base is a protected branch
|
||||||
|
Official bool `json:"official"`
|
||||||
|
Dismissed bool `json:"dismissed"`
|
||||||
|
CodeCommentsCount int `json:"comments_count"`
|
||||||
|
Submitted time.Time `json:"submitted_at"`
|
||||||
|
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
HTMLPullURL string `json:"pull_request_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullReviewComment represents a comment on a pull request review
|
||||||
|
type PullReviewComment struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Reviewer *User `json:"user"`
|
||||||
|
ReviewID int64 `json:"pull_request_review_id"`
|
||||||
|
Resolver *User `json:"resolver"`
|
||||||
|
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
Path string `json:"path"`
|
||||||
|
CommitID string `json:"commit_id"`
|
||||||
|
OrigCommitID string `json:"original_commit_id"`
|
||||||
|
DiffHunk string `json:"diff_hunk"`
|
||||||
|
LineNum uint64 `json:"position"`
|
||||||
|
OldLineNum uint64 `json:"original_position"`
|
||||||
|
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
HTMLPullURL string `json:"pull_request_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullReviewOptions are options to create a pull review
|
||||||
|
type CreatePullReviewOptions struct {
|
||||||
|
State ReviewStateType `json:"event"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
CommitID string `json:"commit_id"`
|
||||||
|
Comments []CreatePullReviewComment `json:"comments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullReviewComment represent a review comment for creation api
|
||||||
|
type CreatePullReviewComment struct {
|
||||||
|
// the tree path
|
||||||
|
Path string `json:"path"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
// if comment to old file line or 0
|
||||||
|
OldLineNum int64 `json:"old_position"`
|
||||||
|
// if comment to new file line or 0
|
||||||
|
NewLineNum int64 `json:"new_position"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitPullReviewOptions are options to submit a pending pull review
|
||||||
|
type SubmitPullReviewOptions struct {
|
||||||
|
State ReviewStateType `json:"event"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DismissPullReviewOptions are options to dismiss a pull review
|
||||||
|
type DismissPullReviewOptions struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullReviewRequestOptions are options to add or remove pull review requests
|
||||||
|
type PullReviewRequestOptions struct {
|
||||||
|
Reviewers []string `json:"reviewers"`
|
||||||
|
TeamReviewers []string `json:"team_reviewers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullReviewsOptions options for listing PullReviews
|
||||||
|
type ListPullReviewsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreatePullReviewOptions struct
|
||||||
|
func (opt CreatePullReviewOptions) Validate() error {
|
||||||
|
if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
for i := range opt.Comments {
|
||||||
|
if err := opt.Comments[i].Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the SubmitPullReviewOptions struct
|
||||||
|
func (opt SubmitPullReviewOptions) Validate() error {
|
||||||
|
if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreatePullReviewComment struct
|
||||||
|
func (opt CreatePullReviewComment) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Body)) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
if opt.NewLineNum != 0 && opt.OldLineNum != 0 {
|
||||||
|
return fmt.Errorf("old and new line num are set, cant identify the code comment position")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullReviews lists all reviews of a pull request
|
||||||
|
func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
rs := make([]*PullReview, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index))
|
||||||
|
link.RawQuery = opt.ListOptions.getURLQuery().Encode()
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rs)
|
||||||
|
return rs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullReview gets a specific review of a pull request
|
||||||
|
func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(PullReview)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil, &r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullReviewComments lists all comments of a pull request review
|
||||||
|
func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]*PullReviewComment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
rcl := make([]*PullReviewComment, 0, 4)
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/comments", owner, repo, index, id))
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rcl)
|
||||||
|
return rcl, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePullReview delete a specific review from a pull request
|
||||||
|
func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullReview create a review to an pull request
|
||||||
|
func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(PullReview)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitPullReview submit a pending review to an pull request
|
||||||
|
func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(PullReview)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReviewRequests create review requests to an pull request
|
||||||
|
func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteReviewRequests delete review requests to an pull request
|
||||||
|
func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DismissPullReview dismiss a review for a pull request
|
||||||
|
func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt DismissPullReviewOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnDismissPullReview cancel to dismiss a review for a pull request
|
||||||
|
func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id),
|
||||||
|
jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
202
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
Normal file
202
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
// 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"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"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"`
|
||||||
|
HTMLURL string `json:"html_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"`
|
||||||
|
Attachments []*Attachment `json:"assets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleasesOptions options for listing repository's releases
|
||||||
|
type ListReleasesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
IsDraft *bool
|
||||||
|
IsPreRelease *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListReleasesOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
|
||||||
|
if opt.IsDraft != nil {
|
||||||
|
query.Add("draft", fmt.Sprintf("%t", *opt.IsDraft))
|
||||||
|
}
|
||||||
|
if opt.IsPreRelease != nil {
|
||||||
|
query.Add("draft", fmt.Sprintf("%t", *opt.IsPreRelease))
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleases list releases of a repository
|
||||||
|
func (c *Client) ListReleases(owner, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
releases := make([]*Release, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases?%s", owner, repo, opt.QueryEncode()),
|
||||||
|
nil, nil, &releases)
|
||||||
|
return releases, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRelease get a release of a repository by id
|
||||||
|
func (c *Client) GetRelease(owner, repo string, id int64) (*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
|
||||||
|
jsonHeader, nil, &r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReleaseByTag get a release of a repository by tag
|
||||||
|
func (c *Client) GetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
return c.fallbackGetReleaseByTag(owner, repo, tag)
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &tag); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", owner, repo, tag),
|
||||||
|
nil, nil, &r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReleaseOption options when creating a release
|
||||||
|
type CreateReleaseOption 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateReleaseOption struct
|
||||||
|
func (opt CreateReleaseOption) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRelease create a release
|
||||||
|
func (c *Client) CreateRelease(owner, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, 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(owner, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("PATCH",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRelease delete a release from a repository, keeping its tag
|
||||||
|
func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
|
||||||
|
nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteReleaseByTag deletes a release frm a repository by tag
|
||||||
|
func (c *Client) DeleteReleaseByTag(user, repo string, tag string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
|
||||||
|
nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 )
|
||||||
|
func (c *Client) fallbackGetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
rl, resp, err := c.ListReleases(owner, repo, ListReleasesOptions{ListOptions: ListOptions{Page: i}})
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
if len(rl) == 0 {
|
||||||
|
return nil,
|
||||||
|
&Response{&http.Response{StatusCode: 404}},
|
||||||
|
fmt.Errorf("release with tag '%s' not found", tag)
|
||||||
|
}
|
||||||
|
for _, r := range rl {
|
||||||
|
if r.TagName == tag {
|
||||||
|
return r, resp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
534
vendor/code.gitea.io/sdk/gitea/repo.go
generated
vendored
Normal file
534
vendor/code.gitea.io/sdk/gitea/repo.go
generated
vendored
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 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"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Permission represents a set of permissions
|
||||||
|
type Permission struct {
|
||||||
|
Admin bool `json:"admin"`
|
||||||
|
Push bool `json:"push"`
|
||||||
|
Pull bool `json:"pull"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalTracker represents settings for internal tracker
|
||||||
|
type InternalTracker struct {
|
||||||
|
// Enable time tracking (Built-in issue tracker)
|
||||||
|
EnableTimeTracker bool `json:"enable_time_tracker"`
|
||||||
|
// Let only contributors track time (Built-in issue tracker)
|
||||||
|
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
|
||||||
|
// Enable dependencies for issues and pull requests (Built-in issue tracker)
|
||||||
|
EnableIssueDependencies bool `json:"enable_issue_dependencies"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalTracker represents settings for external tracker
|
||||||
|
type ExternalTracker struct {
|
||||||
|
// URL of external issue tracker.
|
||||||
|
ExternalTrackerURL string `json:"external_tracker_url"`
|
||||||
|
// External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.
|
||||||
|
ExternalTrackerFormat string `json:"external_tracker_format"`
|
||||||
|
// External Issue Tracker Number Format, either `numeric` or `alphanumeric`
|
||||||
|
ExternalTrackerStyle string `json:"external_tracker_style"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalWiki represents setting for external wiki
|
||||||
|
type ExternalWiki struct {
|
||||||
|
// URL of external wiki.
|
||||||
|
ExternalWikiURL string `json:"external_wiki_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repository represents a 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"`
|
||||||
|
Template bool `json:"template"`
|
||||||
|
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"`
|
||||||
|
OriginalURL string `json:"original_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"`
|
||||||
|
OpenPulls int `json:"open_pr_counter"`
|
||||||
|
Releases int `json:"release_counter"`
|
||||||
|
DefaultBranch string `json:"default_branch"`
|
||||||
|
Archived bool `json:"archived"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
Permissions *Permission `json:"permissions,omitempty"`
|
||||||
|
HasIssues bool `json:"has_issues"`
|
||||||
|
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
|
||||||
|
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
|
||||||
|
HasWiki bool `json:"has_wiki"`
|
||||||
|
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||||
|
HasPullRequests bool `json:"has_pull_requests"`
|
||||||
|
HasProjects bool `json:"has_projects"`
|
||||||
|
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
|
||||||
|
AllowMerge bool `json:"allow_merge_commits"`
|
||||||
|
AllowRebase bool `json:"allow_rebase"`
|
||||||
|
AllowRebaseMerge bool `json:"allow_rebase_explicit"`
|
||||||
|
AllowSquash bool `json:"allow_squash_merge"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Internal bool `json:"internal"`
|
||||||
|
MirrorInterval string `json:"mirror_interval"`
|
||||||
|
DefaultMergeStyle MergeStyle `json:"default_merge_style"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoType represent repo type
|
||||||
|
type RepoType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RepoTypeNone dont specify a type
|
||||||
|
RepoTypeNone RepoType = ""
|
||||||
|
// RepoTypeSource is the default repo type
|
||||||
|
RepoTypeSource RepoType = "source"
|
||||||
|
// RepoTypeFork is a repo witch was forked from an other one
|
||||||
|
RepoTypeFork RepoType = "fork"
|
||||||
|
// RepoTypeMirror represents an mirror repo
|
||||||
|
RepoTypeMirror RepoType = "mirror"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TrustModel represent how git signatures are handled in a repository
|
||||||
|
type TrustModel string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TrustModelDefault use TM set by global config
|
||||||
|
TrustModelDefault TrustModel = "default"
|
||||||
|
// TrustModelCollaborator gpg signature has to be owned by a repo collaborator
|
||||||
|
TrustModelCollaborator TrustModel = "collaborator"
|
||||||
|
// TrustModelCommitter gpg signature has to match committer
|
||||||
|
TrustModelCommitter TrustModel = "committer"
|
||||||
|
// TrustModelCollaboratorCommitter gpg signature has to match committer and owned by a repo collaborator
|
||||||
|
TrustModelCollaboratorCommitter TrustModel = "collaboratorcommitter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListReposOptions options for listing repositories
|
||||||
|
type ListReposOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyRepos lists all repositories for the authenticated user that has access to.
|
||||||
|
func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/repos?%s", opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUserRepos list all repositories of one user by user's name
|
||||||
|
func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgReposOptions options for a organization's repositories
|
||||||
|
type ListOrgReposOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgRepos list all repositories of one organization by organization's name
|
||||||
|
func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchRepoOptions options for searching repositories
|
||||||
|
type SearchRepoOptions struct {
|
||||||
|
ListOptions
|
||||||
|
|
||||||
|
// The keyword to query
|
||||||
|
Keyword string
|
||||||
|
// Limit search to repositories with keyword as topic
|
||||||
|
KeywordIsTopic bool
|
||||||
|
// Include search of keyword within repository description
|
||||||
|
KeywordInDescription bool
|
||||||
|
|
||||||
|
/*
|
||||||
|
User Filter
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Repo Owner
|
||||||
|
OwnerID int64
|
||||||
|
// Stared By UserID
|
||||||
|
StarredByUserID int64
|
||||||
|
|
||||||
|
/*
|
||||||
|
Repo Attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
// pubic, private or all repositories (defaults to all)
|
||||||
|
IsPrivate *bool
|
||||||
|
// archived, non-archived or all repositories (defaults to all)
|
||||||
|
IsArchived *bool
|
||||||
|
// Exclude template repos from search
|
||||||
|
ExcludeTemplate bool
|
||||||
|
// Filter by "fork", "source", "mirror"
|
||||||
|
Type RepoType
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sort Filters
|
||||||
|
*/
|
||||||
|
|
||||||
|
// sort repos by attribute. Supported values are "alpha", "created", "updated", "size", and "id". Default is "alpha"
|
||||||
|
Sort string
|
||||||
|
// sort order, either "asc" (ascending) or "desc" (descending). Default is "asc", ignored if "sort" is not specified.
|
||||||
|
Order string
|
||||||
|
// Repo owner to prioritize in the results
|
||||||
|
PrioritizedByOwnerID int64
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cover EdgeCases
|
||||||
|
*/
|
||||||
|
// if set all other options are ignored and this string is used as query
|
||||||
|
RawQuery string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *SearchRepoOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if opt.Keyword != "" {
|
||||||
|
query.Add("q", opt.Keyword)
|
||||||
|
}
|
||||||
|
if opt.KeywordIsTopic {
|
||||||
|
query.Add("topic", "true")
|
||||||
|
}
|
||||||
|
if opt.KeywordInDescription {
|
||||||
|
query.Add("includeDesc", "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
// User Filter
|
||||||
|
if opt.OwnerID > 0 {
|
||||||
|
query.Add("uid", fmt.Sprintf("%d", opt.OwnerID))
|
||||||
|
query.Add("exclusive", "true")
|
||||||
|
}
|
||||||
|
if opt.StarredByUserID > 0 {
|
||||||
|
query.Add("starredBy", fmt.Sprintf("%d", opt.StarredByUserID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repo Attributes
|
||||||
|
if opt.IsPrivate != nil {
|
||||||
|
query.Add("is_private", fmt.Sprintf("%v", opt.IsPrivate))
|
||||||
|
}
|
||||||
|
if opt.IsArchived != nil {
|
||||||
|
query.Add("archived", fmt.Sprintf("%v", opt.IsArchived))
|
||||||
|
}
|
||||||
|
if opt.ExcludeTemplate {
|
||||||
|
query.Add("template", "false")
|
||||||
|
}
|
||||||
|
if len(opt.Type) != 0 {
|
||||||
|
query.Add("mode", string(opt.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort Filters
|
||||||
|
if opt.Sort != "" {
|
||||||
|
query.Add("sort", opt.Sort)
|
||||||
|
}
|
||||||
|
if opt.PrioritizedByOwnerID > 0 {
|
||||||
|
query.Add("priority_owner_id", fmt.Sprintf("%d", opt.PrioritizedByOwnerID))
|
||||||
|
}
|
||||||
|
if opt.Order != "" {
|
||||||
|
query.Add("order", opt.Order)
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
type searchRepoResponse struct {
|
||||||
|
Repos []*Repository `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchRepos searches for repositories matching the given filters
|
||||||
|
func (c *Client) SearchRepos(opt SearchRepoOptions) ([]*Repository, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := new(searchRepoResponse)
|
||||||
|
|
||||||
|
link, _ := url.Parse("/repos/search")
|
||||||
|
|
||||||
|
if len(opt.RawQuery) != 0 {
|
||||||
|
link.RawQuery = opt.RawQuery
|
||||||
|
} else {
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
// IsPrivate only works on gitea >= 1.12.0
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil && opt.IsPrivate != nil {
|
||||||
|
if *opt.IsPrivate {
|
||||||
|
// private repos only not supported on gitea <= 1.11.x
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link.Query().Add("private", "false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &repos)
|
||||||
|
return repos.Repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepoOption options when creating repository
|
||||||
|
type CreateRepoOption struct {
|
||||||
|
// Name of the repository to create
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Description of the repository to create
|
||||||
|
Description string `json:"description"`
|
||||||
|
// Whether the repository is private
|
||||||
|
Private bool `json:"private"`
|
||||||
|
// Issue Label set to use
|
||||||
|
IssueLabels string `json:"issue_labels"`
|
||||||
|
// Whether the repository should be auto-intialized?
|
||||||
|
AutoInit bool `json:"auto_init"`
|
||||||
|
// Whether the repository is template
|
||||||
|
Template bool `json:"template"`
|
||||||
|
// Gitignores to use
|
||||||
|
Gitignores string `json:"gitignores"`
|
||||||
|
// License to use
|
||||||
|
License string `json:"license"`
|
||||||
|
// Readme of the repository to create
|
||||||
|
Readme string `json:"readme"`
|
||||||
|
// DefaultBranch of the repository (used when initializes and in template)
|
||||||
|
DefaultBranch string `json:"default_branch"`
|
||||||
|
// TrustModel of the repository
|
||||||
|
TrustModel TrustModel `json:"trust_model"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateRepoOption struct
|
||||||
|
func (opt CreateRepoOption) Validate(c *Client) error {
|
||||||
|
if len(strings.TrimSpace(opt.Name)) == 0 {
|
||||||
|
return fmt.Errorf("name is empty")
|
||||||
|
}
|
||||||
|
if len(opt.Name) > 100 {
|
||||||
|
return fmt.Errorf("name has more than 100 chars")
|
||||||
|
}
|
||||||
|
if len(opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("name has more than 255 chars")
|
||||||
|
}
|
||||||
|
if len(opt.DefaultBranch) > 100 {
|
||||||
|
return fmt.Errorf("name has more than 100 chars")
|
||||||
|
}
|
||||||
|
if len(opt.TrustModel) != 0 {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepo creates a repository for authenticated user.
|
||||||
|
func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrgRepo creates an organization repository for authenticated user.
|
||||||
|
func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepo returns information of a repository of given owner.
|
||||||
|
func (c *Client) GetRepo(owner, reponame string) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoByID returns information of a repository by a giver repository ID.
|
||||||
|
func (c *Client) GetRepoByID(id int64) (*Repository, *Response, error) {
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repositories/%d", id), nil, nil, repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepoOption options when editing a repository's properties
|
||||||
|
type EditRepoOption struct {
|
||||||
|
// name of the repository
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
// a short description of the repository.
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
// a URL with more information about the repository.
|
||||||
|
Website *string `json:"website,omitempty"`
|
||||||
|
// either `true` to make the repository private or `false` to make it public.
|
||||||
|
// Note: you will get a 422 error if the organization restricts changing repository visibility to organization
|
||||||
|
// owners and a non-owner tries to change the value of private.
|
||||||
|
Private *bool `json:"private,omitempty"`
|
||||||
|
// either `true` to make this repository a template or `false` to make it a normal repository
|
||||||
|
Template *bool `json:"template,omitempty"`
|
||||||
|
// either `true` to enable issues for this repository or `false` to disable them.
|
||||||
|
HasIssues *bool `json:"has_issues,omitempty"`
|
||||||
|
// set this structure to configure internal issue tracker (requires has_issues)
|
||||||
|
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
|
||||||
|
// set this structure to use external issue tracker (requires has_issues)
|
||||||
|
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
|
||||||
|
// either `true` to enable the wiki for this repository or `false` to disable it.
|
||||||
|
HasWiki *bool `json:"has_wiki,omitempty"`
|
||||||
|
// set this structure to use external wiki instead of internal (requires has_wiki)
|
||||||
|
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||||
|
// sets the default branch for this repository.
|
||||||
|
DefaultBranch *string `json:"default_branch,omitempty"`
|
||||||
|
// either `true` to allow pull requests, or `false` to prevent pull request.
|
||||||
|
HasPullRequests *bool `json:"has_pull_requests,omitempty"`
|
||||||
|
// either `true` to enable project unit, or `false` to disable them.
|
||||||
|
HasProjects *bool `json:"has_projects,omitempty"`
|
||||||
|
// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`.
|
||||||
|
IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"`
|
||||||
|
// either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`.
|
||||||
|
AllowMerge *bool `json:"allow_merge_commits,omitempty"`
|
||||||
|
// either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging. `has_pull_requests` must be `true`.
|
||||||
|
AllowRebase *bool `json:"allow_rebase,omitempty"`
|
||||||
|
// either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits. `has_pull_requests` must be `true`.
|
||||||
|
AllowRebaseMerge *bool `json:"allow_rebase_explicit,omitempty"`
|
||||||
|
// either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging. `has_pull_requests` must be `true`.
|
||||||
|
AllowSquash *bool `json:"allow_squash_merge,omitempty"`
|
||||||
|
// set to `true` to archive this repository.
|
||||||
|
Archived *bool `json:"archived,omitempty"`
|
||||||
|
// set to a string like `8h30m0s` to set the mirror interval time
|
||||||
|
MirrorInterval *string `json:"mirror_interval,omitempty"`
|
||||||
|
// either `true` to allow mark pr as merged manually, or `false` to prevent it. `has_pull_requests` must be `true`.
|
||||||
|
AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
|
||||||
|
// either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur.
|
||||||
|
AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"`
|
||||||
|
// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`.
|
||||||
|
DefaultMergeStyle *MergeStyle `json:"default_merge_style,omitempty"`
|
||||||
|
// set to `true` to archive this repository.
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepo edit the properties of a repository
|
||||||
|
func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepo deletes a repository of user or organization.
|
||||||
|
func (c *Client) DeleteRepo(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorSync adds a mirrored repository to the mirror sync queue.
|
||||||
|
func (c *Client) MirrorSync(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoLanguages return language stats of a repo
|
||||||
|
func (c *Client) GetRepoLanguages(owner, repo string) (map[string]int64, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
langMap := make(map[string]int64)
|
||||||
|
|
||||||
|
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/languages", owner, repo), jsonHeader, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(data, &langMap); err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return langMap, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArchiveType represent supported archive formats by gitea
|
||||||
|
type ArchiveType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ZipArchive represent zip format
|
||||||
|
ZipArchive ArchiveType = ".zip"
|
||||||
|
// TarGZArchive represent tar.gz format
|
||||||
|
TarGZArchive ArchiveType = ".tar.gz"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetArchive get an archive of a repository by git reference
|
||||||
|
// e.g.: ref -> master, 70b7c74b33, v1.2.1, ...
|
||||||
|
func (c *Client) GetArchive(owner, repo, ref string, ext ArchiveType) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetArchiveReader gets a `git archive` for a particular tree-ish git reference
|
||||||
|
// such as a branch name (`master`), a commit hash (`70b7c74b33`), a tag
|
||||||
|
// (`v1.2.1`). The archive is returned as a byte stream in a ReadCloser. It is
|
||||||
|
// the responsibility of the client to close the reader.
|
||||||
|
func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io.ReadCloser, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
resp, err := c.doRequest("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := statusCodeToErr(resp); err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Body, resp, nil
|
||||||
|
}
|
143
vendor/code.gitea.io/sdk/gitea/repo_branch.go
generated
vendored
Normal file
143
vendor/code.gitea.io/sdk/gitea/repo_branch.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PayloadUser represents the author or committer of a commit
|
||||||
|
type PayloadUser struct {
|
||||||
|
// Full name of the commit author
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
UserName string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayloadCommit represents a commit
|
||||||
|
type PayloadCommit struct {
|
||||||
|
// sha1 hash of the commit
|
||||||
|
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"`
|
||||||
|
Added []string `json:"added"`
|
||||||
|
Removed []string `json:"removed"`
|
||||||
|
Modified []string `json:"modified"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayloadCommitVerification represents the GPG verification of a commit
|
||||||
|
type PayloadCommitVerification struct {
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch represents a repository branch
|
||||||
|
type Branch struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Commit *PayloadCommit `json:"commit"`
|
||||||
|
Protected bool `json:"protected"`
|
||||||
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
UserCanPush bool `json:"user_can_push"`
|
||||||
|
UserCanMerge bool `json:"user_can_merge"`
|
||||||
|
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoBranchesOptions options for listing a repository's branches
|
||||||
|
type ListRepoBranchesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoBranches list all the branches of one repository
|
||||||
|
func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
branches := make([]*Branch, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches)
|
||||||
|
return branches, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoBranch get one branch's information of one repository
|
||||||
|
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
b := new(Branch)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return b, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoBranch delete a branch in a repository
|
||||||
|
func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
return status == 204, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchOption options when creating a branch in a repository
|
||||||
|
type CreateBranchOption struct {
|
||||||
|
// Name of the branch to create
|
||||||
|
BranchName string `json:"new_branch_name"`
|
||||||
|
// Name of the old branch to create from (optional)
|
||||||
|
OldBranchName string `json:"old_branch_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateBranchOption struct
|
||||||
|
func (opt CreateBranchOption) Validate() error {
|
||||||
|
if len(opt.BranchName) == 0 {
|
||||||
|
return fmt.Errorf("BranchName is empty")
|
||||||
|
}
|
||||||
|
if len(opt.BranchName) > 100 {
|
||||||
|
return fmt.Errorf("BranchName to long")
|
||||||
|
}
|
||||||
|
if len(opt.OldBranchName) > 100 {
|
||||||
|
return fmt.Errorf("OldBranchName to long")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranch creates a branch for a user's repository
|
||||||
|
func (c *Client) CreateBranch(owner, repo string, opt CreateBranchOption) (*Branch, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
branch := new(Branch)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branches", owner, repo), jsonHeader, bytes.NewReader(body), branch)
|
||||||
|
return branch, resp, err
|
||||||
|
}
|
168
vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
generated
vendored
Normal file
168
vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BranchProtection represents a branch protection for a repository
|
||||||
|
type BranchProtection struct {
|
||||||
|
BranchName string `json:"branch_name"`
|
||||||
|
EnablePush bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
|
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||||
|
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||||
|
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
|
||||||
|
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||||
|
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||||
|
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchProtectionOption options for creating a branch protection
|
||||||
|
type CreateBranchProtectionOption struct {
|
||||||
|
BranchName string `json:"branch_name"`
|
||||||
|
EnablePush bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
|
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||||
|
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||||
|
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
|
||||||
|
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||||
|
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||||
|
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditBranchProtectionOption options for editing a branch protection
|
||||||
|
type EditBranchProtectionOption struct {
|
||||||
|
EnablePush *bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist *bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
EnableStatusCheck *bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
RequiredApprovals *int64 `json:"required_approvals"`
|
||||||
|
EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"`
|
||||||
|
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"`
|
||||||
|
BlockOnOfficialReviewRequests *bool `json:"block_on_official_review_requests"`
|
||||||
|
BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"`
|
||||||
|
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits *bool `json:"require_signed_commits"`
|
||||||
|
ProtectedFilePatterns *string `json:"protected_file_patterns"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBranchProtectionsOptions list branch protection options
|
||||||
|
type ListBranchProtectionsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBranchProtections list branch protections for a repo
|
||||||
|
func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bps := make([]*BranchProtection, 0, opt.PageSize)
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo))
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &bps)
|
||||||
|
return bps, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBranchProtection gets a branch protection
|
||||||
|
func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bp := new(BranchProtection)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil, bp)
|
||||||
|
return bp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchProtection creates a branch protection for a repo
|
||||||
|
func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bp := new(BranchProtection)
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo), jsonHeader, bytes.NewReader(body), bp)
|
||||||
|
return bp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditBranchProtection edits a branch protection for a repo
|
||||||
|
func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bp := new(BranchProtection)
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), bp)
|
||||||
|
return bp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBranchProtection deletes a branch protection for a repo
|
||||||
|
func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
136
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go
generated
vendored
Normal file
136
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListCollaboratorsOptions options for listing a repository's collaborators
|
||||||
|
type ListCollaboratorsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCollaborators list a repository's collaborators
|
||||||
|
func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
collaborators := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/collaborators?%s", user, repo, opt.getURLQuery().Encode()),
|
||||||
|
nil, nil, &collaborators)
|
||||||
|
return collaborators, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCollaborator check if a user is a collaborator of a repository
|
||||||
|
func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
if status == 204 {
|
||||||
|
return true, resp, nil
|
||||||
|
}
|
||||||
|
return false, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCollaboratorOption options when adding a user as a collaborator of a repository
|
||||||
|
type AddCollaboratorOption struct {
|
||||||
|
Permission *AccessMode `json:"permission"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessMode represent the grade of access you have to something
|
||||||
|
type AccessMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AccessModeNone no access
|
||||||
|
AccessModeNone AccessMode = "none"
|
||||||
|
// AccessModeRead read access
|
||||||
|
AccessModeRead AccessMode = "read"
|
||||||
|
// AccessModeWrite write access
|
||||||
|
AccessModeWrite AccessMode = "write"
|
||||||
|
// AccessModeAdmin admin access
|
||||||
|
AccessModeAdmin AccessMode = "admin"
|
||||||
|
// AccessModeOwner owner
|
||||||
|
AccessModeOwner AccessMode = "owner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Validate the AddCollaboratorOption struct
|
||||||
|
func (opt AddCollaboratorOption) Validate() error {
|
||||||
|
if opt.Permission != nil {
|
||||||
|
if *opt.Permission == AccessModeOwner {
|
||||||
|
*opt.Permission = AccessModeAdmin
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if *opt.Permission == AccessModeNone {
|
||||||
|
opt.Permission = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if *opt.Permission != AccessModeRead && *opt.Permission != AccessModeWrite && *opt.Permission != AccessModeAdmin {
|
||||||
|
return fmt.Errorf("permission mode invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCollaborator add some user as a collaborator of a repository
|
||||||
|
func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCollaborator remove a collaborator from a repository
|
||||||
|
func (c *Client) DeleteCollaborator(user, repo, collaborator string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReviewers return all users that can be requested to review in this repo
|
||||||
|
func (c *Client) GetReviewers(user, repo string) ([]*User, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reviewers := make([]*User, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/reviewers", user, repo), nil, nil, &reviewers)
|
||||||
|
return reviewers, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssignees return all users that have write access and can be assigned to issues
|
||||||
|
func (c *Client) GetAssignees(user, repo string) ([]*User, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
assignees := make([]*User, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/assignees", user, repo), nil, nil, &assignees)
|
||||||
|
return assignees, resp, err
|
||||||
|
}
|
101
vendor/code.gitea.io/sdk/gitea/repo_commit.go
generated
vendored
Normal file
101
vendor/code.gitea.io/sdk/gitea/repo_commit.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2018 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Identity for a person's identity like an author or committer
|
||||||
|
type Identity struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitMeta contains meta information of a commit in terms of API.
|
||||||
|
type CommitMeta struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitUser contains information of a user in the context of a commit.
|
||||||
|
type CommitUser struct {
|
||||||
|
Identity
|
||||||
|
Date string `json:"date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoCommit contains information of a commit in the context of a repository.
|
||||||
|
type RepoCommit struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
Author *CommitUser `json:"author"`
|
||||||
|
Committer *CommitUser `json:"committer"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tree *CommitMeta `json:"tree"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit contains information generated from a Git commit.
|
||||||
|
type Commit struct {
|
||||||
|
*CommitMeta
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
RepoCommit *RepoCommit `json:"commit"`
|
||||||
|
Author *User `json:"author"`
|
||||||
|
Committer *User `json:"committer"`
|
||||||
|
Parents []*CommitMeta `json:"parents"`
|
||||||
|
Files []*CommitAffectedFiles `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
|
||||||
|
type CommitDateOptions struct {
|
||||||
|
Author time.Time `json:"author"`
|
||||||
|
Committer time.Time `json:"committer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitAffectedFiles store information about files affected by the commit
|
||||||
|
type CommitAffectedFiles struct {
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleCommit returns a single commit
|
||||||
|
func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &commitID); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
commit := new(Commit)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit)
|
||||||
|
return commit, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCommitOptions list commit options
|
||||||
|
type ListCommitOptions struct {
|
||||||
|
ListOptions
|
||||||
|
//SHA or branch to start listing commits from (usually 'master')
|
||||||
|
SHA string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListCommitOptions) QueryEncode() string {
|
||||||
|
query := opt.ListOptions.getURLQuery()
|
||||||
|
if opt.SHA != "" {
|
||||||
|
query.Add("sha", opt.SHA)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoCommits return list of commits from a repo
|
||||||
|
func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/commits", user, repo))
|
||||||
|
opt.setDefaults()
|
||||||
|
commits := make([]*Commit, 0, opt.PageSize)
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
|
||||||
|
return commits, resp, err
|
||||||
|
}
|
247
vendor/code.gitea.io/sdk/gitea/repo_file.go
generated
vendored
Normal file
247
vendor/code.gitea.io/sdk/gitea/repo_file.go
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileOptions options for all file APIs
|
||||||
|
type FileOptions struct {
|
||||||
|
// message (optional) for the commit of this file. if not supplied, a default message will be used
|
||||||
|
Message string `json:"message"`
|
||||||
|
// branch (optional) to base this file from. if not given, the default branch is used
|
||||||
|
BranchName string `json:"branch"`
|
||||||
|
// new_branch (optional) will make a new branch from `branch` before creating the file
|
||||||
|
NewBranchName string `json:"new_branch"`
|
||||||
|
// `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
Author Identity `json:"author"`
|
||||||
|
Committer Identity `json:"committer"`
|
||||||
|
Dates CommitDateOptions `json:"dates"`
|
||||||
|
// Add a Signed-off-by trailer by the committer at the end of the commit log message.
|
||||||
|
Signoff bool `json:"signoff"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFileOptions options for creating files
|
||||||
|
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
type CreateFileOptions struct {
|
||||||
|
FileOptions
|
||||||
|
// content must be base64 encoded
|
||||||
|
// required: true
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFileOptions options for deleting files (used for other File structs below)
|
||||||
|
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
type DeleteFileOptions struct {
|
||||||
|
FileOptions
|
||||||
|
// sha is the SHA for the file that already exists
|
||||||
|
// required: true
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFileOptions options for updating files
|
||||||
|
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
type UpdateFileOptions struct {
|
||||||
|
FileOptions
|
||||||
|
// sha is the SHA for the file that already exists
|
||||||
|
// required: true
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
// content must be base64 encoded
|
||||||
|
// required: true
|
||||||
|
Content string `json:"content"`
|
||||||
|
// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL
|
||||||
|
FromPath string `json:"from_path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileLinksResponse contains the links for a repo's file
|
||||||
|
type FileLinksResponse struct {
|
||||||
|
Self *string `json:"self"`
|
||||||
|
GitURL *string `json:"git"`
|
||||||
|
HTMLURL *string `json:"html"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content
|
||||||
|
type ContentsResponse struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
// `type` will be `file`, `dir`, `symlink`, or `submodule`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
// `encoding` is populated when `type` is `file`, otherwise null
|
||||||
|
Encoding *string `json:"encoding"`
|
||||||
|
// `content` is populated when `type` is `file`, otherwise null
|
||||||
|
Content *string `json:"content"`
|
||||||
|
// `target` is populated when `type` is `symlink`, otherwise null
|
||||||
|
Target *string `json:"target"`
|
||||||
|
URL *string `json:"url"`
|
||||||
|
HTMLURL *string `json:"html_url"`
|
||||||
|
GitURL *string `json:"git_url"`
|
||||||
|
DownloadURL *string `json:"download_url"`
|
||||||
|
// `submodule_git_url` is populated when `type` is `submodule`, otherwise null
|
||||||
|
SubmoduleGitURL *string `json:"submodule_git_url"`
|
||||||
|
Links *FileLinksResponse `json:"_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileCommitResponse contains information generated from a Git commit for a repo's file.
|
||||||
|
type FileCommitResponse struct {
|
||||||
|
CommitMeta
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
Author *CommitUser `json:"author"`
|
||||||
|
Committer *CommitUser `json:"committer"`
|
||||||
|
Parents []*CommitMeta `json:"parents"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tree *CommitMeta `json:"tree"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileResponse contains information about a repo's file
|
||||||
|
type FileResponse struct {
|
||||||
|
Content *ContentsResponse `json:"content"`
|
||||||
|
Commit *FileCommitResponse `json:"commit"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileDeleteResponse contains information about a repo's file that was deleted
|
||||||
|
type FileDeleteResponse struct {
|
||||||
|
Content interface{} `json:"content"` // to be set to nil
|
||||||
|
Commit *FileCommitResponse `json:"commit"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFile downloads a file of repository, ref can be branch/tag/commit.
|
||||||
|
// e.g.: ref -> master, filepath -> README.md (no leading slash)
|
||||||
|
func (c *Client) GetFile(owner, repo, ref, filepath string) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", owner, repo, ref, filepath), nil, nil)
|
||||||
|
}
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContents get the metadata and contents of a file in a repository
|
||||||
|
// ref is optional
|
||||||
|
func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, *Response, error) {
|
||||||
|
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
cr := new(ContentsResponse)
|
||||||
|
if json.Unmarshal(data, &cr) != nil {
|
||||||
|
return nil, resp, fmt.Errorf("expect file, got directory")
|
||||||
|
}
|
||||||
|
return cr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListContents gets a list of entries in a dir
|
||||||
|
// ref is optional
|
||||||
|
func (c *Client) ListContents(owner, repo, ref, filepath string) ([]*ContentsResponse, *Response, error) {
|
||||||
|
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
crl := make([]*ContentsResponse, 0)
|
||||||
|
if json.Unmarshal(data, &crl) != nil {
|
||||||
|
return nil, resp, fmt.Errorf("expect directory, got file")
|
||||||
|
}
|
||||||
|
return crl, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getDirOrFileContents(owner, repo, ref, filepath string) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(strings.TrimPrefix(filepath, "/"))
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), jsonHeader, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFile create a file in a repository
|
||||||
|
func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, *Response, error) {
|
||||||
|
var err error
|
||||||
|
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
fr := new(FileResponse)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
|
||||||
|
return fr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFile update a file in a repository
|
||||||
|
func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, *Response, error) {
|
||||||
|
var err error
|
||||||
|
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
fr := new(FileResponse)
|
||||||
|
resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
|
||||||
|
return fr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFile delete a file from repository
|
||||||
|
func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) (*Response, error) {
|
||||||
|
var err error
|
||||||
|
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status != 200 && status != 204 {
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) setDefaultBranchForOldVersions(owner, repo, branch string) (string, error) {
|
||||||
|
if len(branch) == 0 {
|
||||||
|
// Gitea >= 1.12.0 Use DefaultBranch on "", mimic this for older versions
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
|
||||||
|
r, _, err := c.GetRepo(owner, repo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.DefaultBranch, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return branch, nil
|
||||||
|
}
|
91
vendor/code.gitea.io/sdk/gitea/repo_key.go
generated
vendored
Normal file
91
vendor/code.gitea.io/sdk/gitea/repo_key.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// 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"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeployKey a deploy key
|
||||||
|
type DeployKey struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
KeyID int64 `json:"key_id"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Fingerprint string `json:"fingerprint"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
ReadOnly bool `json:"read_only"`
|
||||||
|
Repository *Repository `json:"repository,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDeployKeysOptions options for listing a repository's deploy keys
|
||||||
|
type ListDeployKeysOptions struct {
|
||||||
|
ListOptions
|
||||||
|
KeyID int64
|
||||||
|
Fingerprint string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListDeployKeysOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if opt.KeyID > 0 {
|
||||||
|
query.Add("key_id", fmt.Sprintf("%d", opt.KeyID))
|
||||||
|
}
|
||||||
|
if len(opt.Fingerprint) > 0 {
|
||||||
|
query.Add("fingerprint", opt.Fingerprint)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDeployKeys list all the deploy keys of one repository
|
||||||
|
func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/keys", user, repo))
|
||||||
|
opt.setDefaults()
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
keys := make([]*DeployKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDeployKey get one deploy key with key id
|
||||||
|
func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(DeployKey)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDeployKey options when create one deploy key
|
||||||
|
func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(DeployKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDeployKey delete deploy key with key id
|
||||||
|
func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
132
vendor/code.gitea.io/sdk/gitea/repo_migrate.go
generated
vendored
Normal file
132
vendor/code.gitea.io/sdk/gitea/repo_migrate.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitServiceType represents a git service
|
||||||
|
type GitServiceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// GitServicePlain represents a plain git service
|
||||||
|
GitServicePlain GitServiceType = "git"
|
||||||
|
//GitServiceGithub represents github.com
|
||||||
|
GitServiceGithub GitServiceType = "github"
|
||||||
|
// GitServiceGitlab represents a gitlab service
|
||||||
|
GitServiceGitlab GitServiceType = "gitlab"
|
||||||
|
// GitServiceGitea represents a gitea service
|
||||||
|
GitServiceGitea GitServiceType = "gitea"
|
||||||
|
// GitServiceGogs represents a gogs service
|
||||||
|
GitServiceGogs GitServiceType = "gogs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateRepoOption options for migrating a repository from an external service
|
||||||
|
type MigrateRepoOption struct {
|
||||||
|
RepoName string `json:"repo_name"`
|
||||||
|
RepoOwner string `json:"repo_owner"`
|
||||||
|
// deprecated use RepoOwner
|
||||||
|
RepoOwnerID int64 `json:"uid"`
|
||||||
|
CloneAddr string `json:"clone_addr"`
|
||||||
|
Service GitServiceType `json:"service"`
|
||||||
|
AuthUsername string `json:"auth_username"`
|
||||||
|
AuthPassword string `json:"auth_password"`
|
||||||
|
AuthToken string `json:"auth_token"`
|
||||||
|
Mirror bool `json:"mirror"`
|
||||||
|
Private bool `json:"private"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Wiki bool `json:"wiki"`
|
||||||
|
Milestones bool `json:"milestones"`
|
||||||
|
Labels bool `json:"labels"`
|
||||||
|
Issues bool `json:"issues"`
|
||||||
|
PullRequests bool `json:"pull_requests"`
|
||||||
|
Releases bool `json:"releases"`
|
||||||
|
MirrorInterval string `json:"mirror_interval"`
|
||||||
|
LFS bool `json:"lfs"`
|
||||||
|
LFSEndpoint string `json:"lfs_endpoint"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the MigrateRepoOption struct
|
||||||
|
func (opt *MigrateRepoOption) Validate(c *Client) error {
|
||||||
|
// check user options
|
||||||
|
if len(opt.CloneAddr) == 0 {
|
||||||
|
return fmt.Errorf("CloneAddr required")
|
||||||
|
}
|
||||||
|
if len(opt.RepoName) == 0 {
|
||||||
|
return fmt.Errorf("RepoName required")
|
||||||
|
} else if len(opt.RepoName) > 100 {
|
||||||
|
return fmt.Errorf("RepoName to long")
|
||||||
|
}
|
||||||
|
if len(opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("Description to long")
|
||||||
|
}
|
||||||
|
switch opt.Service {
|
||||||
|
case GitServiceGithub:
|
||||||
|
if len(opt.AuthToken) == 0 {
|
||||||
|
return fmt.Errorf("github requires token authentication")
|
||||||
|
}
|
||||||
|
case GitServiceGitlab, GitServiceGitea:
|
||||||
|
if len(opt.AuthToken) == 0 {
|
||||||
|
return fmt.Errorf("%s requires token authentication", opt.Service)
|
||||||
|
}
|
||||||
|
// Gitlab is supported since 1.12.0 but api cant handle it until 1.13.0
|
||||||
|
// https://github.com/go-gitea/gitea/pull/12672
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
return fmt.Errorf("migrate from service %s need gitea >= 1.13.0", opt.Service)
|
||||||
|
}
|
||||||
|
case GitServiceGogs:
|
||||||
|
if len(opt.AuthToken) == 0 {
|
||||||
|
return fmt.Errorf("gogs requires token authentication")
|
||||||
|
}
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
return fmt.Errorf("migrate from service gogs need gitea >= 1.14.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, *Response, error) {
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
if len(opt.AuthToken) != 0 {
|
||||||
|
// gitea <= 1.12 dont understand AuthToken
|
||||||
|
opt.AuthUsername = opt.AuthToken
|
||||||
|
opt.AuthPassword, opt.AuthToken = "", ""
|
||||||
|
}
|
||||||
|
if len(opt.RepoOwner) != 0 {
|
||||||
|
// gitea <= 1.12 dont understand RepoOwner
|
||||||
|
u, _, err := c.GetUserInfo(opt.RepoOwner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.RepoOwnerID = u.ID
|
||||||
|
} else if opt.RepoOwnerID == 0 {
|
||||||
|
// gitea <= 1.12 require RepoOwnerID
|
||||||
|
u, _, err := c.GetMyUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.RepoOwnerID = u.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
78
vendor/code.gitea.io/sdk/gitea/repo_refs.go
generated
vendored
Normal file
78
vendor/code.gitea.io/sdk/gitea/repo_refs.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2018 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 (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference represents a Git reference.
|
||||||
|
type Reference struct {
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Object *GitObject `json:"object"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitObject represents a Git object.
|
||||||
|
type GitObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoRef get one ref's information of one repository
|
||||||
|
func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = strings.TrimPrefix(ref, "refs/")
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
r := new(Reference)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil, &r)
|
||||||
|
if _, ok := err.(*json.UnmarshalTypeError); ok {
|
||||||
|
// Multiple refs
|
||||||
|
return nil, resp, errors.New("no exact match found for this ref")
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoRefs get list of ref's information of one repository
|
||||||
|
func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = strings.TrimPrefix(ref, "refs/")
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
|
||||||
|
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to unmarshal single returned ref.
|
||||||
|
r := new(Reference)
|
||||||
|
refErr := json.Unmarshal(data, r)
|
||||||
|
if refErr == nil {
|
||||||
|
return []*Reference{r}, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to unmarshal multiple refs.
|
||||||
|
var rs []*Reference
|
||||||
|
refsErr := json.Unmarshal(data, &rs)
|
||||||
|
if refsErr == nil {
|
||||||
|
if len(rs) == 0 {
|
||||||
|
return nil, resp, errors.New("unexpected response: an array of refs with length 0")
|
||||||
|
}
|
||||||
|
return rs, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", refErr, refsErr)
|
||||||
|
}
|
96
vendor/code.gitea.io/sdk/gitea/repo_stars.go
generated
vendored
Normal file
96
vendor/code.gitea.io/sdk/gitea/repo_stars.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2021 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListStargazersOptions options for listing a repository's stargazers
|
||||||
|
type ListStargazersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoStargazers list a repository's stargazers
|
||||||
|
func (c *Client) ListRepoStargazers(user, repo string, opt ListStargazersOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
stargazers := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/stargazers?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &stargazers)
|
||||||
|
return stargazers, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStarredRepos returns the repos that the given user has starred
|
||||||
|
func (c *Client) GetStarredRepos(user string) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/starred", user), jsonHeader, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyStarredRepos returns the repos that the authenticated user has starred
|
||||||
|
func (c *Client) GetMyStarredRepos() ([]*Repository, *Response, error) {
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/starred", jsonHeader, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRepoStarring returns whether the authenticated user has starred the repo or not
|
||||||
|
func (c *Client) IsRepoStarring(user, repo string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||||
|
if resp != nil {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return true, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StarRepo star specified repo as the authenticated user
|
||||||
|
func (c *Client) StarRepo(user, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||||
|
if resp != nil {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return resp, nil
|
||||||
|
default:
|
||||||
|
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnStarRepo remove star to specified repo as the authenticated user
|
||||||
|
func (c *Client) UnStarRepo(user, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||||
|
if resp != nil {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return resp, nil
|
||||||
|
default:
|
||||||
|
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
130
vendor/code.gitea.io/sdk/gitea/repo_tag.go
generated
vendored
Normal file
130
vendor/code.gitea.io/sdk/gitea/repo_tag.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tag represents a repository tag
|
||||||
|
type Tag struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
Commit *CommitMeta `json:"commit"`
|
||||||
|
ZipballURL string `json:"zipball_url"`
|
||||||
|
TarballURL string `json:"tarball_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedTag represents an annotated tag
|
||||||
|
type AnnotatedTag struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tagger *CommitUser `json:"tagger"`
|
||||||
|
Object *AnnotatedTagObject `json:"object"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedTagObject contains meta information of the tag object
|
||||||
|
type AnnotatedTagObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTagsOptions options for listing a repository's tags
|
||||||
|
type ListRepoTagsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTags list all the branches of one repository
|
||||||
|
func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
tags := make([]*Tag, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags)
|
||||||
|
return tags, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTag get the tag of a repository
|
||||||
|
func (c *Client) GetTag(user, repo, tag string) (*Tag, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Tag)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag), nil, nil, &t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAnnotatedTag get the tag object of an annotated tag (not lightweight tags) of a repository
|
||||||
|
func (c *Client) GetAnnotatedTag(user, repo, sha string) (*AnnotatedTag, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(AnnotatedTag)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/tags/%s", user, repo, sha), nil, nil, &t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTagOption options when creating a tag
|
||||||
|
type CreateTagOption struct {
|
||||||
|
TagName string `json:"tag_name"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Target string `json:"target"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates CreateTagOption
|
||||||
|
func (opt CreateTagOption) Validate() error {
|
||||||
|
if len(opt.TagName) == 0 {
|
||||||
|
return fmt.Errorf("TagName is required")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTag create a new git tag in a repository
|
||||||
|
func (c *Client) CreateTag(user, repo string, opt CreateTagOption) (*Tag, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Tag)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/tags", user, repo), jsonHeader, bytes.NewReader(body), &t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteTag deletes a tag from a repository, if no release refers to it
|
||||||
|
func (c *Client) DeleteTag(user, repo, tag string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag),
|
||||||
|
nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
65
vendor/code.gitea.io/sdk/gitea/repo_team.go
generated
vendored
Normal file
65
vendor/code.gitea.io/sdk/gitea/repo_team.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2021 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRepoTeams return teams from a repository
|
||||||
|
func (c *Client) GetRepoTeams(user, repo string) ([]*Team, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
teams := make([]*Team, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams", user, repo), nil, nil, &teams)
|
||||||
|
return teams, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRepoTeam add a team to a repository
|
||||||
|
func (c *Client) AddRepoTeam(user, repo, team string) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveRepoTeam delete a team from a repository
|
||||||
|
func (c *Client) RemoveRepoTeam(user, repo, team string) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckRepoTeam check if team is assigned to repo by name and return it.
|
||||||
|
// If not assigned, it will return nil.
|
||||||
|
func (c *Client) CheckRepoTeam(user, repo, team string) (*Team, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Team)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil, &t)
|
||||||
|
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||||
|
// if not found it's not an error, it indicates it's not assigned
|
||||||
|
return nil, resp, nil
|
||||||
|
}
|
||||||
|
return t, resp, err
|
||||||
|
}
|
65
vendor/code.gitea.io/sdk/gitea/repo_template.go
generated
vendored
Normal file
65
vendor/code.gitea.io/sdk/gitea/repo_template.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2021 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateRepoFromTemplateOption options when creating repository using a template
|
||||||
|
type CreateRepoFromTemplateOption struct {
|
||||||
|
// Owner is the organization or person who will own the new repository
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
// Name of the repository to create
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Description of the repository to create
|
||||||
|
Description string `json:"description"`
|
||||||
|
// Private is whether the repository is private
|
||||||
|
Private bool `json:"private"`
|
||||||
|
// GitContent include git content of default branch in template repo
|
||||||
|
GitContent bool `json:"git_content"`
|
||||||
|
// Topics include topics of template repo
|
||||||
|
Topics bool `json:"topics"`
|
||||||
|
// GitHooks include git hooks of template repo
|
||||||
|
GitHooks bool `json:"git_hooks"`
|
||||||
|
// Webhooks include webhooks of template repo
|
||||||
|
Webhooks bool `json:"webhooks"`
|
||||||
|
// Avatar include avatar of the template repo
|
||||||
|
Avatar bool `json:"avatar"`
|
||||||
|
// Labels include labels of template repo
|
||||||
|
Labels bool `json:"labels"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates CreateRepoFromTemplateOption
|
||||||
|
func (opt CreateRepoFromTemplateOption) Validate() error {
|
||||||
|
if len(opt.Owner) == 0 {
|
||||||
|
return fmt.Errorf("field Owner is required")
|
||||||
|
}
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("field Name is required")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepoFromTemplate create a repository using a template
|
||||||
|
func (c *Client) CreateRepoFromTemplate(templateOwner, templateRepo string, opt CreateRepoFromTemplateOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&templateOwner, &templateRepo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/generate", templateOwner, templateRepo), jsonHeader, bytes.NewReader(body), &repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
68
vendor/code.gitea.io/sdk/gitea/repo_topics.go
generated
vendored
Normal file
68
vendor/code.gitea.io/sdk/gitea/repo_topics.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2019 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListRepoTopicsOptions options for listing repo's topics
|
||||||
|
type ListRepoTopicsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// topicsList represents a list of repo's topics
|
||||||
|
type topicsList struct {
|
||||||
|
Topics []string `json:"topics"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTopics list all repository's topics
|
||||||
|
func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
|
||||||
|
list := new(topicsList)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return list.Topics, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRepoTopics replaces the list of repo's topics
|
||||||
|
func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l := topicsList{Topics: list}
|
||||||
|
body, err := json.Marshal(&l)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRepoTopic adds a topic to a repo's topics list
|
||||||
|
func (c *Client) AddRepoTopic(user, repo, topic string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoTopic deletes a topic from repo's topics list
|
||||||
|
func (c *Client) DeleteRepoTopic(user, repo, topic string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
36
vendor/code.gitea.io/sdk/gitea/repo_transfer.go
generated
vendored
Normal file
36
vendor/code.gitea.io/sdk/gitea/repo_transfer.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TransferRepoOption options when transfer a repository's ownership
|
||||||
|
type TransferRepoOption struct {
|
||||||
|
// required: true
|
||||||
|
NewOwner string `json:"new_owner"`
|
||||||
|
// ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.
|
||||||
|
TeamIDs *[]int64 `json:"team_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransferRepo transfers the ownership of a repository
|
||||||
|
func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
44
vendor/code.gitea.io/sdk/gitea/repo_tree.go
generated
vendored
Normal file
44
vendor/code.gitea.io/sdk/gitea/repo_tree.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2018 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitEntry represents a git tree
|
||||||
|
type GitEntry struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Mode string `json:"mode"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitTreeResponse returns a git tree
|
||||||
|
type GitTreeResponse struct {
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Entries []GitEntry `json:"tree"`
|
||||||
|
Truncated bool `json:"truncated"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
TotalCount int `json:"total_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTrees downloads a file of repository, ref can be branch/tag/commit.
|
||||||
|
// e.g.: ref -> master, tree -> macaron.go(no leading slash)
|
||||||
|
func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &ref); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
trees := new(GitTreeResponse)
|
||||||
|
var path = fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref)
|
||||||
|
if recursive {
|
||||||
|
path += "?recursive=1"
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("GET", path, nil, nil, trees)
|
||||||
|
return trees, resp, err
|
||||||
|
}
|
87
vendor/code.gitea.io/sdk/gitea/repo_watch.go
generated
vendored
Normal file
87
vendor/code.gitea.io/sdk/gitea/repo_watch.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// 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 an API watch status of one repository
|
||||||
|
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 string) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyWatchedRepos list repositories watched by the authenticated user
|
||||||
|
func (c *Client) GetMyWatchedRepos() ([]*Repository, *Response, error) {
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/subscriptions"), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckRepoWatch check if the current user is watching a repo
|
||||||
|
func (c *Client) CheckRepoWatch(owner, repo string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
case http.StatusOK:
|
||||||
|
return true, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchRepo start to watch a repository
|
||||||
|
func (c *Client) WatchRepo(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusOK {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnWatchRepo stop to watch a repository
|
||||||
|
func (c *Client) UnWatchRepo(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusNoContent {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
78
vendor/code.gitea.io/sdk/gitea/settings.go
generated
vendored
Normal file
78
vendor/code.gitea.io/sdk/gitea/settings.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2020 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
|
||||||
|
|
||||||
|
// GlobalUISettings represent the global ui settings of a gitea instance witch is exposed by API
|
||||||
|
type GlobalUISettings struct {
|
||||||
|
DefaultTheme string `json:"default_theme"`
|
||||||
|
AllowedReactions []string `json:"allowed_reactions"`
|
||||||
|
CustomEmojis []string `json:"custom_emojis"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalRepoSettings represent the global repository settings of a gitea instance witch is exposed by API
|
||||||
|
type GlobalRepoSettings struct {
|
||||||
|
MirrorsDisabled bool `json:"mirrors_disabled"`
|
||||||
|
HTTPGitDisabled bool `json:"http_git_disabled"`
|
||||||
|
MigrationsDisabled bool `json:"migrations_disabled"`
|
||||||
|
StarsDisabled bool `json:"stars_disabled"`
|
||||||
|
TimeTrackingDisabled bool `json:"time_tracking_disabled"`
|
||||||
|
LFSDisabled bool `json:"lfs_disabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalAPISettings contains global api settings exposed by it
|
||||||
|
type GlobalAPISettings struct {
|
||||||
|
MaxResponseItems int `json:"max_response_items"`
|
||||||
|
DefaultPagingNum int `json:"default_paging_num"`
|
||||||
|
DefaultGitTreesPerPage int `json:"default_git_trees_per_page"`
|
||||||
|
DefaultMaxBlobSize int64 `json:"default_max_blob_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalAttachmentSettings contains global Attachment settings exposed by API
|
||||||
|
type GlobalAttachmentSettings struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
AllowedTypes string `json:"allowed_types"`
|
||||||
|
MaxSize int64 `json:"max_size"`
|
||||||
|
MaxFiles int `json:"max_files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalUISettings get global ui settings witch are exposed by API
|
||||||
|
func (c *Client) GetGlobalUISettings() (*GlobalUISettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalUISettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/ui", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalRepoSettings get global repository settings witch are exposed by API
|
||||||
|
func (c *Client) GetGlobalRepoSettings() (*GlobalRepoSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalRepoSettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/repository", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalAPISettings get global api settings witch are exposed by it
|
||||||
|
func (c *Client) GetGlobalAPISettings() (*GlobalAPISettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalAPISettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/api", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalAttachmentSettings get global repository settings witch are exposed by API
|
||||||
|
func (c *Client) GetGlobalAttachmentSettings() (*GlobalAttachmentSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalAttachmentSettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/attachment", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
108
vendor/code.gitea.io/sdk/gitea/status.go
generated
vendored
Normal file
108
vendor/code.gitea.io/sdk/gitea/status.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// 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"
|
||||||
|
"net/url"
|
||||||
|
"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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStatus creates a new Status for a given Commit
|
||||||
|
func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
status := new(Status)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, url.QueryEscape(sha)), jsonHeader, bytes.NewReader(body), status)
|
||||||
|
return status, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListStatusesOption options for listing a repository's commit's statuses
|
||||||
|
type ListStatusesOption struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListStatuses returns all statuses for a given Commit by ref
|
||||||
|
func (c *Client) ListStatuses(owner, repo, ref string, opt ListStatusesOption) ([]*Status, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &ref); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
statuses := make([]*Status, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, ref, opt.getURLQuery().Encode()), jsonHeader, nil, &statuses)
|
||||||
|
return statuses, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCombinedStatus returns the CombinedStatus for a given Commit
|
||||||
|
func (c *Client) GetCombinedStatus(owner, repo, ref string) (*CombinedStatus, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &ref); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
status := new(CombinedStatus)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, ref), jsonHeader, nil, status)
|
||||||
|
|
||||||
|
// gitea api return empty body if nothing here jet
|
||||||
|
if resp != nil && resp.StatusCode == 200 && err != nil {
|
||||||
|
return status, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, resp, err
|
||||||
|
}
|
90
vendor/code.gitea.io/sdk/gitea/user.go
generated
vendored
Normal file
90
vendor/code.gitea.io/sdk/gitea/user.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// 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"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// User represents a user
|
||||||
|
type User struct {
|
||||||
|
// the user's id
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
// the user's username
|
||||||
|
UserName string `json:"login"`
|
||||||
|
// the user's full name
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
// URL to the user's avatar
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
// User locale
|
||||||
|
Language string `json:"language"`
|
||||||
|
// Is the user an administrator
|
||||||
|
IsAdmin bool `json:"is_admin"`
|
||||||
|
// Date and Time of last login
|
||||||
|
LastLogin time.Time `json:"last_login"`
|
||||||
|
// Date and Time of user creation
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
// Is user restricted
|
||||||
|
Restricted bool `json:"restricted"`
|
||||||
|
// Is user active
|
||||||
|
IsActive bool `json:"active"`
|
||||||
|
// Is user login prohibited
|
||||||
|
ProhibitLogin bool `json:"prohibit_login"`
|
||||||
|
// the user's location
|
||||||
|
Location string `json:"location"`
|
||||||
|
// the user's website
|
||||||
|
Website string `json:"website"`
|
||||||
|
// the user's description
|
||||||
|
Description string `json:"description"`
|
||||||
|
// User visibility level option
|
||||||
|
Visibility VisibleType `json:"visibility"`
|
||||||
|
|
||||||
|
// user counts
|
||||||
|
FollowerCount int `json:"followers_count"`
|
||||||
|
FollowingCount int `json:"following_count"`
|
||||||
|
StarredRepoCount int `json:"starred_repos_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserInfo get user info by user's name
|
||||||
|
func (c *Client) GetUserInfo(user string) (*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
u := new(User)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
|
||||||
|
return u, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyUserInfo get user info of current user
|
||||||
|
func (c *Client) GetMyUserInfo() (*User, *Response, error) {
|
||||||
|
u := new(User)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user", nil, nil, u)
|
||||||
|
return u, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID returns user by a given user ID
|
||||||
|
func (c *Client) GetUserByID(id int64) (*User, *Response, error) {
|
||||||
|
if id < 0 {
|
||||||
|
return nil, nil, fmt.Errorf("invalid user id %d", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := make(url.Values)
|
||||||
|
query.Add("uid", strconv.FormatInt(id, 10))
|
||||||
|
users, resp, err := c.searchUsers(query.Encode())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(users) == 1 {
|
||||||
|
return users[0], resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, resp, fmt.Errorf("user not found with id %d", id)
|
||||||
|
}
|
90
vendor/code.gitea.io/sdk/gitea/user_app.go
generated
vendored
Normal file
90
vendor/code.gitea.io/sdk/gitea/user_app.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 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"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AccessToken represents an API access token.
|
||||||
|
type AccessToken struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Token string `json:"sha1"`
|
||||||
|
TokenLastEight string `json:"token_last_eight"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAccessTokensOptions options for listing a users's access tokens
|
||||||
|
type ListAccessTokensOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAccessTokens lists all the access tokens of user
|
||||||
|
func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, *Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
username := c.username
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
if len(username) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||||
|
}
|
||||||
|
opts.setDefaults()
|
||||||
|
tokens := make([]*AccessToken, 0, opts.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", url.PathEscape(username), opts.getURLQuery().Encode()), jsonHeader, nil, &tokens)
|
||||||
|
return tokens, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAccessTokenOption options when create access token
|
||||||
|
type CreateAccessTokenOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAccessToken create one access token with options
|
||||||
|
func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, *Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
username := c.username
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
if len(username) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(AccessToken)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", url.PathEscape(username)), jsonHeader, bytes.NewReader(body), t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAccessToken delete token, identified by ID and if not available by name
|
||||||
|
func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
username := c.username
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
if len(username) == 0 {
|
||||||
|
return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = ""
|
||||||
|
|
||||||
|
switch reflect.ValueOf(value).Kind() {
|
||||||
|
case reflect.Int64:
|
||||||
|
token = fmt.Sprintf("%d", value.(int64))
|
||||||
|
case reflect.String:
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
token = value.(string)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("only string and int64 supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", url.PathEscape(username), url.PathEscape(token)), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
64
vendor/code.gitea.io/sdk/gitea/user_email.go
generated
vendored
Normal file
64
vendor/code.gitea.io/sdk/gitea/user_email.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Email an email address belonging to a user
|
||||||
|
type Email struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
Primary bool `json:"primary"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailsOptions options for listing current's user emails
|
||||||
|
type ListEmailsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmails all the email addresses of user
|
||||||
|
func (c *Client) ListEmails(opt ListEmailsOptions) ([]*Email, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
emails := make([]*Email, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/emails?%s", opt.getURLQuery().Encode()), nil, nil, &emails)
|
||||||
|
return emails, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateEmailOption options when creating email addresses
|
||||||
|
type CreateEmailOption struct {
|
||||||
|
// email addresses to add
|
||||||
|
Emails []string `json:"emails"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEmail add one email to current user with options
|
||||||
|
func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, *Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
emails := make([]*Email, 0, 3)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), &emails)
|
||||||
|
return emails, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailOption options when deleting email addresses
|
||||||
|
type DeleteEmailOption struct {
|
||||||
|
// email addresses to delete
|
||||||
|
Emails []string `json:"emails"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmail delete one email of current users'
|
||||||
|
func (c *Client) DeleteEmail(opt DeleteEmailOption) (*Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
93
vendor/code.gitea.io/sdk/gitea/user_follow.go
generated
vendored
Normal file
93
vendor/code.gitea.io/sdk/gitea/user_follow.go
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
// ListFollowersOptions options for listing followers
|
||||||
|
type ListFollowersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyFollowers list all the followers of current user
|
||||||
|
func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/followers?%s", opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFollowers list all the followers of one user
|
||||||
|
func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFollowingOptions options for listing a user's users being followed
|
||||||
|
type ListFollowingOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyFollowing list all the users current user followed
|
||||||
|
func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/following?%s", opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFollowing list all the users the user followed
|
||||||
|
func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFollowing if current user followed the target
|
||||||
|
func (c *Client) IsFollowing(target string) (bool, *Response) {
|
||||||
|
if err := escapeValidatePathSegments(&target); err != nil {
|
||||||
|
// ToDo return err
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||||
|
return err == nil, resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUserFollowing if the user followed the target
|
||||||
|
func (c *Client) IsUserFollowing(user, target string) (bool, *Response) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &target); err != nil {
|
||||||
|
// ToDo return err
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil)
|
||||||
|
return err == nil, resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Follow set current user follow the target
|
||||||
|
func (c *Client) Follow(target string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&target); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfollow set current user unfollow the target
|
||||||
|
func (c *Client) Unfollow(target string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&target); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
89
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go
generated
vendored
Normal file
89
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GPGKey a user GPG key to sign commit and tag in repository
|
||||||
|
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 an email attached to a GPGKey
|
||||||
|
type GPGKeyEmail struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListGPGKeysOptions options for listing a user's GPGKeys
|
||||||
|
type ListGPGKeysOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListGPGKeys list all the GPG keys of the user
|
||||||
|
func (c *Client) ListGPGKeys(user string, opt ListGPGKeysOptions) ([]*GPGKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*GPGKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyGPGKeys list all the GPG keys of current user
|
||||||
|
func (c *Client) ListMyGPGKeys(opt *ListGPGKeysOptions) ([]*GPGKey, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*GPGKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGPGKey get current user's GPG key by key id
|
||||||
|
func (c *Client) GetGPGKey(keyID int64) (*GPGKey, *Response, error) {
|
||||||
|
key := new(GPGKey)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil, &key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateGPGKeyOption options create user GPG key
|
||||||
|
type CreateGPGKeyOption struct {
|
||||||
|
// An armored GPG key to add
|
||||||
|
//
|
||||||
|
ArmoredKey string `json:"armored_public_key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateGPGKey create GPG key with options
|
||||||
|
func (c *Client) CreateGPGKey(opt CreateGPGKeyOption) (*GPGKey, *Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(GPGKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/gpg_keys", jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteGPGKey delete GPG key with key id
|
||||||
|
func (c *Client) DeleteGPGKey(keyID int64) (*Response, error) {
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
83
vendor/code.gitea.io/sdk/gitea/user_key.go
generated
vendored
Normal file
83
vendor/code.gitea.io/sdk/gitea/user_key.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicKey publickey is a user key to push code to repository
|
||||||
|
type PublicKey struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
Fingerprint string `json:"fingerprint,omitempty"`
|
||||||
|
Created time.Time `json:"created_at,omitempty"`
|
||||||
|
Owner *User `json:"user,omitempty"`
|
||||||
|
ReadOnly bool `json:"read_only,omitempty"`
|
||||||
|
KeyType string `json:"key_type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPublicKeysOptions options for listing a user's PublicKeys
|
||||||
|
type ListPublicKeysOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPublicKeys list all the public keys of the user
|
||||||
|
func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*PublicKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyPublicKeys list all the public keys of current user
|
||||||
|
func (c *Client) ListMyPublicKeys(opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*PublicKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublicKey get current user's public key by key id
|
||||||
|
func (c *Client) GetPublicKey(keyID int64) (*PublicKey, *Response, error) {
|
||||||
|
key := new(PublicKey)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateKeyOption options when creating a key
|
||||||
|
type CreateKeyOption struct {
|
||||||
|
// Title of the key to add
|
||||||
|
Title string `json:"title"`
|
||||||
|
// An armored SSH key to add
|
||||||
|
Key string `json:"key"`
|
||||||
|
// Describe if the key has only read access or read/write
|
||||||
|
ReadOnly bool `json:"read_only"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePublicKey create public key with options
|
||||||
|
func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, *Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(PublicKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePublicKey delete public key with key id
|
||||||
|
func (c *Client) DeletePublicKey(keyID int64) (*Response, error) {
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
48
vendor/code.gitea.io/sdk/gitea/user_search.go
generated
vendored
Normal file
48
vendor/code.gitea.io/sdk/gitea/user_search.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2020 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/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type searchUsersResponse struct {
|
||||||
|
Users []*User `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchUsersOption options for SearchUsers
|
||||||
|
type SearchUsersOption struct {
|
||||||
|
ListOptions
|
||||||
|
KeyWord string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *SearchUsersOption) QueryEncode() string {
|
||||||
|
query := make(url.Values)
|
||||||
|
if opt.Page > 0 {
|
||||||
|
query.Add("page", fmt.Sprintf("%d", opt.Page))
|
||||||
|
}
|
||||||
|
if opt.PageSize > 0 {
|
||||||
|
query.Add("limit", fmt.Sprintf("%d", opt.PageSize))
|
||||||
|
}
|
||||||
|
if len(opt.KeyWord) > 0 {
|
||||||
|
query.Add("q", opt.KeyWord)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) searchUsers(rawQuery string) ([]*User, *Response, error) {
|
||||||
|
link, _ := url.Parse("/users/search")
|
||||||
|
link.RawQuery = rawQuery
|
||||||
|
userResp := new(searchUsersResponse)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &userResp)
|
||||||
|
return userResp.Users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchUsers finds users by query
|
||||||
|
func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, *Response, error) {
|
||||||
|
return c.searchUsers(opt.QueryEncode())
|
||||||
|
}
|
62
vendor/code.gitea.io/sdk/gitea/user_settings.go
generated
vendored
Normal file
62
vendor/code.gitea.io/sdk/gitea/user_settings.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2021 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UserSettings represents user settings
|
||||||
|
type UserSettings struct {
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Theme string `json:"theme"`
|
||||||
|
DiffViewStyle string `json:"diff_view_style"`
|
||||||
|
// Privacy
|
||||||
|
HideEmail bool `json:"hide_email"`
|
||||||
|
HideActivity bool `json:"hide_activity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserSettingsOptions represents options to change user settings
|
||||||
|
type UserSettingsOptions struct {
|
||||||
|
FullName *string `json:"full_name,omitempty"`
|
||||||
|
Website *string `json:"website,omitempty"`
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
Location *string `json:"location,omitempty"`
|
||||||
|
Language *string `json:"language,omitempty"`
|
||||||
|
Theme *string `json:"theme,omitempty"`
|
||||||
|
DiffViewStyle *string `json:"diff_view_style,omitempty"`
|
||||||
|
// Privacy
|
||||||
|
HideEmail *bool `json:"hide_email,omitempty"`
|
||||||
|
HideActivity *bool `json:"hide_activity,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserSettings returns user settings
|
||||||
|
func (c *Client) GetUserSettings() (*UserSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
userConfig := new(UserSettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/settings", nil, nil, userConfig)
|
||||||
|
return userConfig, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserSettings returns user settings
|
||||||
|
func (c *Client) UpdateUserSettings(opt UserSettingsOptions) (*UserSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
userConfig := new(UserSettings)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", "/user/settings", jsonHeader, bytes.NewReader(body), userConfig)
|
||||||
|
return userConfig, resp, err
|
||||||
|
}
|
101
vendor/code.gitea.io/sdk/gitea/version.go
generated
vendored
Normal file
101
vendor/code.gitea.io/sdk/gitea/version.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2020 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"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServerVersion returns the version of the server
|
||||||
|
func (c *Client) ServerVersion() (string, *Response, error) {
|
||||||
|
var v = struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
}{}
|
||||||
|
resp, err := c.getParsedResponse("GET", "/version", nil, nil, &v)
|
||||||
|
return v.Version, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckServerVersionConstraint validates that the login's server satisfies a
|
||||||
|
// given version constraint such as ">= 1.11.0+dev"
|
||||||
|
func (c *Client) CheckServerVersionConstraint(constraint string) error {
|
||||||
|
if err := c.loadServerVersion(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
check, err := version.NewConstraint(constraint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !check.Check(c.serverVersion) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
url := c.url
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return fmt.Errorf("gitea server at %s does not satisfy version constraint %s", url, constraint)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGiteaVersion configures the Client to assume the given version of the
|
||||||
|
// Gitea server, instead of querying the server for it when initializing.
|
||||||
|
// Use "" to skip all canonical ways in the SDK to check for versions
|
||||||
|
func SetGiteaVersion(v string) ClientOption {
|
||||||
|
if v == "" {
|
||||||
|
return func(c *Client) error {
|
||||||
|
c.ignoreVersion = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func(c *Client) (err error) {
|
||||||
|
c.getVersionOnce.Do(func() {
|
||||||
|
c.serverVersion, err = version.NewVersion(v)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// predefined versions only have to be parsed by library once
|
||||||
|
var (
|
||||||
|
version1_11_0, _ = version.NewVersion("1.11.0")
|
||||||
|
version1_12_0, _ = version.NewVersion("1.12.0")
|
||||||
|
version1_13_0, _ = version.NewVersion("1.13.0")
|
||||||
|
version1_14_0, _ = version.NewVersion("1.14.0")
|
||||||
|
version1_15_0, _ = version.NewVersion("1.15.0")
|
||||||
|
)
|
||||||
|
|
||||||
|
// checkServerVersionGreaterThanOrEqual is the canonical way in the SDK to check for versions for API compatibility reasons
|
||||||
|
func (c *Client) checkServerVersionGreaterThanOrEqual(v *version.Version) error {
|
||||||
|
if c.ignoreVersion {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := c.loadServerVersion(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.serverVersion.GreaterThanOrEqual(v) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
url := c.url
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return fmt.Errorf("gitea server at %s is older than %s", url, v.Original())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadServerVersion init the serverVersion variable
|
||||||
|
func (c *Client) loadServerVersion() (err error) {
|
||||||
|
c.getVersionOnce.Do(func() {
|
||||||
|
raw, _, err2 := c.ServerVersion()
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.serverVersion, err = version.NewVersion(raw); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
354
vendor/github.com/hashicorp/go-version/LICENSE
generated
vendored
Normal file
354
vendor/github.com/hashicorp/go-version/LICENSE
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
1.1. “Contributor”
|
||||||
|
|
||||||
|
means each individual or legal entity that creates, contributes to the
|
||||||
|
creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. “Contributor Version”
|
||||||
|
|
||||||
|
means the combination of the Contributions of others (if any) used by a
|
||||||
|
Contributor and that particular Contributor’s Contribution.
|
||||||
|
|
||||||
|
1.3. “Contribution”
|
||||||
|
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. “Covered Software”
|
||||||
|
|
||||||
|
means Source Code Form to which the initial Contributor has attached the
|
||||||
|
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||||
|
Modifications of such Source Code Form, in each case including portions
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
1.5. “Incompatible With Secondary Licenses”
|
||||||
|
means
|
||||||
|
|
||||||
|
a. that the initial Contributor has attached the notice described in
|
||||||
|
Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
b. that the Covered Software was made available under the terms of version
|
||||||
|
1.1 or earlier of the License, but not also under the terms of a
|
||||||
|
Secondary License.
|
||||||
|
|
||||||
|
1.6. “Executable Form”
|
||||||
|
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. “Larger Work”
|
||||||
|
|
||||||
|
means a work that combines Covered Software with other material, in a separate
|
||||||
|
file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. “License”
|
||||||
|
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. “Licensable”
|
||||||
|
|
||||||
|
means having the right to grant, to the maximum extent possible, whether at the
|
||||||
|
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||||
|
this License.
|
||||||
|
|
||||||
|
1.10. “Modifications”
|
||||||
|
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
a. any file in Source Code Form that results from an addition to, deletion
|
||||||
|
from, or modification of the contents of Covered Software; or
|
||||||
|
|
||||||
|
b. any new file in Source Code Form that contains any Covered Software.
|
||||||
|
|
||||||
|
1.11. “Patent Claims” of a Contributor
|
||||||
|
|
||||||
|
means any patent claim(s), including without limitation, method, process,
|
||||||
|
and apparatus claims, in any patent Licensable by such Contributor that
|
||||||
|
would be infringed, but for the grant of the License, by the making,
|
||||||
|
using, selling, offering for sale, having made, import, or transfer of
|
||||||
|
either its Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
1.12. “Secondary License”
|
||||||
|
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||||
|
General Public License, Version 2.1, the GNU Affero General Public
|
||||||
|
License, Version 3.0, or any later versions of those licenses.
|
||||||
|
|
||||||
|
1.13. “Source Code Form”
|
||||||
|
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. “You” (or “Your”)
|
||||||
|
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, “You” includes any entity that controls, is
|
||||||
|
controlled by, or is under common control with You. For purposes of this
|
||||||
|
definition, “control” means (a) the power, direct or indirect, to cause
|
||||||
|
the direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||||
|
outstanding shares or beneficial ownership of such entity.
|
||||||
|
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
a. under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or as
|
||||||
|
part of a Larger Work; and
|
||||||
|
|
||||||
|
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||||
|
sale, have made, import, and otherwise transfer either its Contributions
|
||||||
|
or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||||
|
effective for each Contribution on the date the Contributor first distributes
|
||||||
|
such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under this
|
||||||
|
License. No additional rights or licenses will be implied from the distribution
|
||||||
|
or licensing of Covered Software under this License. Notwithstanding Section
|
||||||
|
2.1(b) above, no patent license is granted by a Contributor:
|
||||||
|
|
||||||
|
a. for any code that a Contributor has removed from Covered Software; or
|
||||||
|
|
||||||
|
b. for infringements caused by: (i) Your and any other third party’s
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks, or
|
||||||
|
logos of any Contributor (except as may be necessary to comply with the
|
||||||
|
notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this License
|
||||||
|
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||||
|
under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its Contributions
|
||||||
|
are its original creation(s) or it has sufficient rights to grant the
|
||||||
|
rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under applicable
|
||||||
|
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||||
|
Section 2.1.
|
||||||
|
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under the
|
||||||
|
terms of this License. You must inform recipients that the Source Code Form
|
||||||
|
of the Covered Software is governed by the terms of this License, and how
|
||||||
|
they can obtain a copy of this License. You may not attempt to alter or
|
||||||
|
restrict the recipients’ rights in the Source Code Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
a. such Covered Software must also be made available in Source Code Form,
|
||||||
|
as described in Section 3.1, and You must inform recipients of the
|
||||||
|
Executable Form how they can obtain a copy of such Source Code Form by
|
||||||
|
reasonable means in a timely manner, at a charge no more than the cost
|
||||||
|
of distribution to the recipient; and
|
||||||
|
|
||||||
|
b. You may distribute such Executable Form under the terms of this License,
|
||||||
|
or sublicense it under different terms, provided that the license for
|
||||||
|
the Executable Form does not attempt to limit or alter the recipients’
|
||||||
|
rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for the
|
||||||
|
Covered Software. If the Larger Work is a combination of Covered Software
|
||||||
|
with a work governed by one or more Secondary Licenses, and the Covered
|
||||||
|
Software is not Incompatible With Secondary Licenses, this License permits
|
||||||
|
You to additionally distribute such Covered Software under the terms of
|
||||||
|
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||||
|
their option, further distribute the Covered Software under the terms of
|
||||||
|
either this License or such Secondary License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices (including
|
||||||
|
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||||
|
of liability) contained within the Source Code Form of the Covered
|
||||||
|
Software, except that You may alter any license notices to the extent
|
||||||
|
required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||||
|
of any Contributor. You must make it absolutely clear that any such
|
||||||
|
warranty, support, indemnity, or liability obligation is offered by You
|
||||||
|
alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this License
|
||||||
|
with respect to some or all of the Covered Software due to statute, judicial
|
||||||
|
order, or regulation then You must: (a) comply with the terms of this License
|
||||||
|
to the maximum extent possible; and (b) describe the limitations and the code
|
||||||
|
they affect. Such description must be placed in a text file included with all
|
||||||
|
distributions of the Covered Software under this License. Except to the
|
||||||
|
extent prohibited by statute or regulation, such description must be
|
||||||
|
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||||
|
understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically if You
|
||||||
|
fail to comply with any of its terms. However, if You become compliant,
|
||||||
|
then the rights granted under this License from a particular Contributor
|
||||||
|
are reinstated (a) provisionally, unless and until such Contributor
|
||||||
|
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||||
|
if such Contributor fails to notify You of the non-compliance by some
|
||||||
|
reasonable means prior to 60 days after You have come back into compliance.
|
||||||
|
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||||
|
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||||
|
some reasonable means, this is the first time You have received notice of
|
||||||
|
non-compliance with this License from such Contributor, and You become
|
||||||
|
compliant prior to 30 days after Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||||
|
and cross-claims) alleging that a Contributor Version directly or
|
||||||
|
indirectly infringes any patent, then the rights granted to You by any and
|
||||||
|
all Contributors for the Covered Software under Section 2.1 of this License
|
||||||
|
shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||||
|
license agreements (excluding distributors and resellers) which have been
|
||||||
|
validly granted by You or Your distributors under this License prior to
|
||||||
|
termination shall survive termination.
|
||||||
|
|
||||||
|
6. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Covered Software is provided under this License on an “as is” basis, without
|
||||||
|
warranty of any kind, either expressed, implied, or statutory, including,
|
||||||
|
without limitation, warranties that the Covered Software is free of defects,
|
||||||
|
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||||
|
risk as to the quality and performance of the Covered Software is with You.
|
||||||
|
Should any Covered Software prove defective in any respect, You (not any
|
||||||
|
Contributor) assume the cost of any necessary servicing, repair, or
|
||||||
|
correction. This disclaimer of warranty constitutes an essential part of this
|
||||||
|
License. No use of any Covered Software is authorized under this License
|
||||||
|
except under this disclaimer.
|
||||||
|
|
||||||
|
7. Limitation of Liability
|
||||||
|
|
||||||
|
Under no circumstances and under no legal theory, whether tort (including
|
||||||
|
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||||
|
distributes Covered Software as permitted above, be liable to You for any
|
||||||
|
direct, indirect, special, incidental, or consequential damages of any
|
||||||
|
character including, without limitation, damages for lost profits, loss of
|
||||||
|
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses, even if such party shall have been
|
||||||
|
informed of the possibility of such damages. This limitation of liability
|
||||||
|
shall not apply to liability for death or personal injury resulting from such
|
||||||
|
party’s negligence to the extent applicable law prohibits such limitation.
|
||||||
|
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||||
|
consequential damages, so this exclusion and limitation may not apply to You.
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the courts of
|
||||||
|
a jurisdiction where the defendant maintains its principal place of business
|
||||||
|
and such litigation shall be governed by laws of that jurisdiction, without
|
||||||
|
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||||
|
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject matter
|
||||||
|
hereof. If any provision of this License is held to be unenforceable, such
|
||||||
|
provision shall be reformed only to the extent necessary to make it
|
||||||
|
enforceable. Any law or regulation which provides that the language of a
|
||||||
|
contract shall be construed against the drafter shall not be used to construe
|
||||||
|
this License against a Contributor.
|
||||||
|
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version of
|
||||||
|
the License under which You originally received the Covered Software, or
|
||||||
|
under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a modified
|
||||||
|
version of this License if you rename the license and remove any
|
||||||
|
references to the name of the license steward (except to note that such
|
||||||
|
modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular file, then
|
||||||
|
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||||
|
directory) where a recipient would be likely to look for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||||
|
|
||||||
|
This Source Code Form is “Incompatible
|
||||||
|
With Secondary Licenses”, as defined by
|
||||||
|
the Mozilla Public License, v. 2.0.
|
||||||
|
|
66
vendor/github.com/hashicorp/go-version/README.md
generated
vendored
Normal file
66
vendor/github.com/hashicorp/go-version/README.md
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Versioning Library for Go
|
||||||
|
[![Build Status](https://circleci.com/gh/hashicorp/go-version/tree/master.svg?style=svg)](https://circleci.com/gh/hashicorp/go-version/tree/master)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/hashicorp/go-version?status.svg)](https://godoc.org/github.com/hashicorp/go-version)
|
||||||
|
|
||||||
|
go-version is a library for parsing versions and version constraints,
|
||||||
|
and verifying versions against a set of constraints. go-version
|
||||||
|
can sort a collection of versions properly, handles prerelease/beta
|
||||||
|
versions, can increment versions, etc.
|
||||||
|
|
||||||
|
Versions used with go-version must follow [SemVer](http://semver.org/).
|
||||||
|
|
||||||
|
## Installation and Usage
|
||||||
|
|
||||||
|
Package documentation can be found on
|
||||||
|
[GoDoc](http://godoc.org/github.com/hashicorp/go-version).
|
||||||
|
|
||||||
|
Installation can be done with a normal `go get`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get github.com/hashicorp/go-version
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Version Parsing and Comparison
|
||||||
|
|
||||||
|
```go
|
||||||
|
v1, err := version.NewVersion("1.2")
|
||||||
|
v2, err := version.NewVersion("1.5+metadata")
|
||||||
|
|
||||||
|
// Comparison example. There is also GreaterThan, Equal, and just
|
||||||
|
// a simple Compare that returns an int allowing easy >=, <=, etc.
|
||||||
|
if v1.LessThan(v2) {
|
||||||
|
fmt.Printf("%s is less than %s", v1, v2)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Version Constraints
|
||||||
|
|
||||||
|
```go
|
||||||
|
v1, err := version.NewVersion("1.2")
|
||||||
|
|
||||||
|
// Constraints example.
|
||||||
|
constraints, err := version.NewConstraint(">= 1.0, < 1.4")
|
||||||
|
if constraints.Check(v1) {
|
||||||
|
fmt.Printf("%s satisfies constraints %s", v1, constraints)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Version Sorting
|
||||||
|
|
||||||
|
```go
|
||||||
|
versionsRaw := []string{"1.1", "0.7.1", "1.4-beta", "1.4", "2"}
|
||||||
|
versions := make([]*version.Version, len(versionsRaw))
|
||||||
|
for i, raw := range versionsRaw {
|
||||||
|
v, _ := version.NewVersion(raw)
|
||||||
|
versions[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// After this, the versions are properly sorted
|
||||||
|
sort.Sort(version.Collection(versions))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Issues and Contributing
|
||||||
|
|
||||||
|
If you find an issue with this library, please report an issue. If you'd
|
||||||
|
like, we welcome any contributions. Fork this library and submit a pull
|
||||||
|
request.
|
204
vendor/github.com/hashicorp/go-version/constraint.go
generated
vendored
Normal file
204
vendor/github.com/hashicorp/go-version/constraint.go
generated
vendored
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constraint represents a single constraint for a version, such as
|
||||||
|
// ">= 1.0".
|
||||||
|
type Constraint struct {
|
||||||
|
f constraintFunc
|
||||||
|
check *Version
|
||||||
|
original string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraints is a slice of constraints. We make a custom type so that
|
||||||
|
// we can add methods to it.
|
||||||
|
type Constraints []*Constraint
|
||||||
|
|
||||||
|
type constraintFunc func(v, c *Version) bool
|
||||||
|
|
||||||
|
var constraintOperators map[string]constraintFunc
|
||||||
|
|
||||||
|
var constraintRegexp *regexp.Regexp
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
constraintOperators = map[string]constraintFunc{
|
||||||
|
"": constraintEqual,
|
||||||
|
"=": constraintEqual,
|
||||||
|
"!=": constraintNotEqual,
|
||||||
|
">": constraintGreaterThan,
|
||||||
|
"<": constraintLessThan,
|
||||||
|
">=": constraintGreaterThanEqual,
|
||||||
|
"<=": constraintLessThanEqual,
|
||||||
|
"~>": constraintPessimistic,
|
||||||
|
}
|
||||||
|
|
||||||
|
ops := make([]string, 0, len(constraintOperators))
|
||||||
|
for k := range constraintOperators {
|
||||||
|
ops = append(ops, regexp.QuoteMeta(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
constraintRegexp = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`^\s*(%s)\s*(%s)\s*$`,
|
||||||
|
strings.Join(ops, "|"),
|
||||||
|
VersionRegexpRaw))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConstraint will parse one or more constraints from the given
|
||||||
|
// constraint string. The string must be a comma-separated list of
|
||||||
|
// constraints.
|
||||||
|
func NewConstraint(v string) (Constraints, error) {
|
||||||
|
vs := strings.Split(v, ",")
|
||||||
|
result := make([]*Constraint, len(vs))
|
||||||
|
for i, single := range vs {
|
||||||
|
c, err := parseSingle(single)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
return Constraints(result), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tests if a version satisfies all the constraints.
|
||||||
|
func (cs Constraints) Check(v *Version) bool {
|
||||||
|
for _, c := range cs {
|
||||||
|
if !c.Check(v) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the string format of the constraints
|
||||||
|
func (cs Constraints) String() string {
|
||||||
|
csStr := make([]string, len(cs))
|
||||||
|
for i, c := range cs {
|
||||||
|
csStr[i] = c.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(csStr, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tests if a constraint is validated by the given version.
|
||||||
|
func (c *Constraint) Check(v *Version) bool {
|
||||||
|
return c.f(v, c.check)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Constraint) String() string {
|
||||||
|
return c.original
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSingle(v string) (*Constraint, error) {
|
||||||
|
matches := constraintRegexp.FindStringSubmatch(v)
|
||||||
|
if matches == nil {
|
||||||
|
return nil, fmt.Errorf("Malformed constraint: %s", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
check, err := NewVersion(matches[2])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Constraint{
|
||||||
|
f: constraintOperators[matches[1]],
|
||||||
|
check: check,
|
||||||
|
original: v,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func prereleaseCheck(v, c *Version) bool {
|
||||||
|
switch vPre, cPre := v.Prerelease() != "", c.Prerelease() != ""; {
|
||||||
|
case cPre && vPre:
|
||||||
|
// A constraint with a pre-release can only match a pre-release version
|
||||||
|
// with the same base segments.
|
||||||
|
return reflect.DeepEqual(c.Segments64(), v.Segments64())
|
||||||
|
|
||||||
|
case !cPre && vPre:
|
||||||
|
// A constraint without a pre-release can only match a version without a
|
||||||
|
// pre-release.
|
||||||
|
return false
|
||||||
|
|
||||||
|
case cPre && !vPre:
|
||||||
|
// OK, except with the pessimistic operator
|
||||||
|
case !cPre && !vPre:
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
// Constraint functions
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
func constraintEqual(v, c *Version) bool {
|
||||||
|
return v.Equal(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintNotEqual(v, c *Version) bool {
|
||||||
|
return !v.Equal(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintGreaterThan(v, c *Version) bool {
|
||||||
|
return prereleaseCheck(v, c) && v.Compare(c) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintLessThan(v, c *Version) bool {
|
||||||
|
return prereleaseCheck(v, c) && v.Compare(c) == -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintGreaterThanEqual(v, c *Version) bool {
|
||||||
|
return prereleaseCheck(v, c) && v.Compare(c) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintLessThanEqual(v, c *Version) bool {
|
||||||
|
return prereleaseCheck(v, c) && v.Compare(c) <= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintPessimistic(v, c *Version) bool {
|
||||||
|
// Using a pessimistic constraint with a pre-release, restricts versions to pre-releases
|
||||||
|
if !prereleaseCheck(v, c) || (c.Prerelease() != "" && v.Prerelease() == "") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the version being checked is naturally less than the constraint, then there
|
||||||
|
// is no way for the version to be valid against the constraint
|
||||||
|
if v.LessThan(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// We'll use this more than once, so grab the length now so it's a little cleaner
|
||||||
|
// to write the later checks
|
||||||
|
cs := len(c.segments)
|
||||||
|
|
||||||
|
// If the version being checked has less specificity than the constraint, then there
|
||||||
|
// is no way for the version to be valid against the constraint
|
||||||
|
if cs > len(v.segments) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the segments in the constraint against those in the version. If the version
|
||||||
|
// being checked, at any point, does not have the same values in each index of the
|
||||||
|
// constraints segments, then it cannot be valid against the constraint.
|
||||||
|
for i := 0; i < c.si-1; i++ {
|
||||||
|
if v.segments[i] != c.segments[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the last part of the segment in the constraint. If the version segment at
|
||||||
|
// this index is less than the constraints segment at this index, then it cannot
|
||||||
|
// be valid against the constraint
|
||||||
|
if c.segments[cs-1] > v.segments[cs-1] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing has rejected the version by now, it's valid
|
||||||
|
return true
|
||||||
|
}
|
384
vendor/github.com/hashicorp/go-version/version.go
generated
vendored
Normal file
384
vendor/github.com/hashicorp/go-version/version.go
generated
vendored
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The compiled regular expression used to test the validity of a version.
|
||||||
|
var (
|
||||||
|
versionRegexp *regexp.Regexp
|
||||||
|
semverRegexp *regexp.Regexp
|
||||||
|
)
|
||||||
|
|
||||||
|
// The raw regular expression string used for testing the validity
|
||||||
|
// of a version.
|
||||||
|
const (
|
||||||
|
VersionRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
|
||||||
|
`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
|
||||||
|
`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
|
||||||
|
`?`
|
||||||
|
|
||||||
|
// SemverRegexpRaw requires a separator between version and prerelease
|
||||||
|
SemverRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
|
||||||
|
`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
|
||||||
|
`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
|
||||||
|
`?`
|
||||||
|
)
|
||||||
|
|
||||||
|
// Version represents a single version.
|
||||||
|
type Version struct {
|
||||||
|
metadata string
|
||||||
|
pre string
|
||||||
|
segments []int64
|
||||||
|
si int
|
||||||
|
original string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$")
|
||||||
|
semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVersion parses the given version and returns a new
|
||||||
|
// Version.
|
||||||
|
func NewVersion(v string) (*Version, error) {
|
||||||
|
return newVersion(v, versionRegexp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSemver parses the given version and returns a new
|
||||||
|
// Version that adheres strictly to SemVer specs
|
||||||
|
// https://semver.org/
|
||||||
|
func NewSemver(v string) (*Version, error) {
|
||||||
|
return newVersion(v, semverRegexp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newVersion(v string, pattern *regexp.Regexp) (*Version, error) {
|
||||||
|
matches := pattern.FindStringSubmatch(v)
|
||||||
|
if matches == nil {
|
||||||
|
return nil, fmt.Errorf("Malformed version: %s", v)
|
||||||
|
}
|
||||||
|
segmentsStr := strings.Split(matches[1], ".")
|
||||||
|
segments := make([]int64, len(segmentsStr))
|
||||||
|
si := 0
|
||||||
|
for i, str := range segmentsStr {
|
||||||
|
val, err := strconv.ParseInt(str, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error parsing version: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
segments[i] = int64(val)
|
||||||
|
si++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even though we could support more than three segments, if we
|
||||||
|
// got less than three, pad it with 0s. This is to cover the basic
|
||||||
|
// default usecase of semver, which is MAJOR.MINOR.PATCH at the minimum
|
||||||
|
for i := len(segments); i < 3; i++ {
|
||||||
|
segments = append(segments, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pre := matches[7]
|
||||||
|
if pre == "" {
|
||||||
|
pre = matches[4]
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Version{
|
||||||
|
metadata: matches[10],
|
||||||
|
pre: pre,
|
||||||
|
segments: segments,
|
||||||
|
si: si,
|
||||||
|
original: v,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must is a helper that wraps a call to a function returning (*Version, error)
|
||||||
|
// and panics if error is non-nil.
|
||||||
|
func Must(v *Version, err error) *Version {
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare compares this version to another version. This
|
||||||
|
// returns -1, 0, or 1 if this version is smaller, equal,
|
||||||
|
// or larger than the other version, respectively.
|
||||||
|
//
|
||||||
|
// If you want boolean results, use the LessThan, Equal,
|
||||||
|
// GreaterThan, GreaterThanOrEqual or LessThanOrEqual methods.
|
||||||
|
func (v *Version) Compare(other *Version) int {
|
||||||
|
// A quick, efficient equality check
|
||||||
|
if v.String() == other.String() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
segmentsSelf := v.Segments64()
|
||||||
|
segmentsOther := other.Segments64()
|
||||||
|
|
||||||
|
// If the segments are the same, we must compare on prerelease info
|
||||||
|
if reflect.DeepEqual(segmentsSelf, segmentsOther) {
|
||||||
|
preSelf := v.Prerelease()
|
||||||
|
preOther := other.Prerelease()
|
||||||
|
if preSelf == "" && preOther == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if preSelf == "" {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if preOther == "" {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return comparePrereleases(preSelf, preOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the highest specificity (hS), or if they're equal, just use segmentSelf length
|
||||||
|
lenSelf := len(segmentsSelf)
|
||||||
|
lenOther := len(segmentsOther)
|
||||||
|
hS := lenSelf
|
||||||
|
if lenSelf < lenOther {
|
||||||
|
hS = lenOther
|
||||||
|
}
|
||||||
|
// Compare the segments
|
||||||
|
// Because a constraint could have more/less specificity than the version it's
|
||||||
|
// checking, we need to account for a lopsided or jagged comparison
|
||||||
|
for i := 0; i < hS; i++ {
|
||||||
|
if i > lenSelf-1 {
|
||||||
|
// This means Self had the lower specificity
|
||||||
|
// Check to see if the remaining segments in Other are all zeros
|
||||||
|
if !allZero(segmentsOther[i:]) {
|
||||||
|
// if not, it means that Other has to be greater than Self
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
break
|
||||||
|
} else if i > lenOther-1 {
|
||||||
|
// this means Other had the lower specificity
|
||||||
|
// Check to see if the remaining segments in Self are all zeros -
|
||||||
|
if !allZero(segmentsSelf[i:]) {
|
||||||
|
//if not, it means that Self has to be greater than Other
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
lhs := segmentsSelf[i]
|
||||||
|
rhs := segmentsOther[i]
|
||||||
|
if lhs == rhs {
|
||||||
|
continue
|
||||||
|
} else if lhs < rhs {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
// Otherwis, rhs was > lhs, they're not equal
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we got this far, they're equal
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func allZero(segs []int64) bool {
|
||||||
|
for _, s := range segs {
|
||||||
|
if s != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func comparePart(preSelf string, preOther string) int {
|
||||||
|
if preSelf == preOther {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var selfInt int64
|
||||||
|
selfNumeric := true
|
||||||
|
selfInt, err := strconv.ParseInt(preSelf, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
selfNumeric = false
|
||||||
|
}
|
||||||
|
|
||||||
|
var otherInt int64
|
||||||
|
otherNumeric := true
|
||||||
|
otherInt, err = strconv.ParseInt(preOther, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
otherNumeric = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a part is empty, we use the other to decide
|
||||||
|
if preSelf == "" {
|
||||||
|
if otherNumeric {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if preOther == "" {
|
||||||
|
if selfNumeric {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if selfNumeric && !otherNumeric {
|
||||||
|
return -1
|
||||||
|
} else if !selfNumeric && otherNumeric {
|
||||||
|
return 1
|
||||||
|
} else if !selfNumeric && !otherNumeric && preSelf > preOther {
|
||||||
|
return 1
|
||||||
|
} else if selfInt > otherInt {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func comparePrereleases(v string, other string) int {
|
||||||
|
// the same pre release!
|
||||||
|
if v == other {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// split both pre releases for analyse their parts
|
||||||
|
selfPreReleaseMeta := strings.Split(v, ".")
|
||||||
|
otherPreReleaseMeta := strings.Split(other, ".")
|
||||||
|
|
||||||
|
selfPreReleaseLen := len(selfPreReleaseMeta)
|
||||||
|
otherPreReleaseLen := len(otherPreReleaseMeta)
|
||||||
|
|
||||||
|
biggestLen := otherPreReleaseLen
|
||||||
|
if selfPreReleaseLen > otherPreReleaseLen {
|
||||||
|
biggestLen = selfPreReleaseLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop for parts to find the first difference
|
||||||
|
for i := 0; i < biggestLen; i = i + 1 {
|
||||||
|
partSelfPre := ""
|
||||||
|
if i < selfPreReleaseLen {
|
||||||
|
partSelfPre = selfPreReleaseMeta[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
partOtherPre := ""
|
||||||
|
if i < otherPreReleaseLen {
|
||||||
|
partOtherPre = otherPreReleaseMeta[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
compare := comparePart(partSelfPre, partOtherPre)
|
||||||
|
// if parts are equals, continue the loop
|
||||||
|
if compare != 0 {
|
||||||
|
return compare
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal tests if two versions are equal.
|
||||||
|
func (v *Version) Equal(o *Version) bool {
|
||||||
|
if v == nil || o == nil {
|
||||||
|
return v == o
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Compare(o) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterThan tests if this version is greater than another version.
|
||||||
|
func (v *Version) GreaterThan(o *Version) bool {
|
||||||
|
return v.Compare(o) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterThanOrEqual tests if this version is greater than or equal to another version.
|
||||||
|
func (v *Version) GreaterThanOrEqual(o *Version) bool {
|
||||||
|
return v.Compare(o) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessThan tests if this version is less than another version.
|
||||||
|
func (v *Version) LessThan(o *Version) bool {
|
||||||
|
return v.Compare(o) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessThanOrEqual tests if this version is less than or equal to another version.
|
||||||
|
func (v *Version) LessThanOrEqual(o *Version) bool {
|
||||||
|
return v.Compare(o) <= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata returns any metadata that was part of the version
|
||||||
|
// string.
|
||||||
|
//
|
||||||
|
// Metadata is anything that comes after the "+" in the version.
|
||||||
|
// For example, with "1.2.3+beta", the metadata is "beta".
|
||||||
|
func (v *Version) Metadata() string {
|
||||||
|
return v.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prerelease returns any prerelease data that is part of the version,
|
||||||
|
// or blank if there is no prerelease data.
|
||||||
|
//
|
||||||
|
// Prerelease information is anything that comes after the "-" in the
|
||||||
|
// version (but before any metadata). For example, with "1.2.3-beta",
|
||||||
|
// the prerelease information is "beta".
|
||||||
|
func (v *Version) Prerelease() string {
|
||||||
|
return v.pre
|
||||||
|
}
|
||||||
|
|
||||||
|
// Segments returns the numeric segments of the version as a slice of ints.
|
||||||
|
//
|
||||||
|
// This excludes any metadata or pre-release information. For example,
|
||||||
|
// for a version "1.2.3-beta", segments will return a slice of
|
||||||
|
// 1, 2, 3.
|
||||||
|
func (v *Version) Segments() []int {
|
||||||
|
segmentSlice := make([]int, len(v.segments))
|
||||||
|
for i, v := range v.segments {
|
||||||
|
segmentSlice[i] = int(v)
|
||||||
|
}
|
||||||
|
return segmentSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// Segments64 returns the numeric segments of the version as a slice of int64s.
|
||||||
|
//
|
||||||
|
// This excludes any metadata or pre-release information. For example,
|
||||||
|
// for a version "1.2.3-beta", segments will return a slice of
|
||||||
|
// 1, 2, 3.
|
||||||
|
func (v *Version) Segments64() []int64 {
|
||||||
|
result := make([]int64, len(v.segments))
|
||||||
|
copy(result, v.segments)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the full version string included pre-release
|
||||||
|
// and metadata information.
|
||||||
|
//
|
||||||
|
// This value is rebuilt according to the parsed segments and other
|
||||||
|
// information. Therefore, ambiguities in the version string such as
|
||||||
|
// prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and
|
||||||
|
// missing parts (1.0 => 1.0.0) will be made into a canonicalized form
|
||||||
|
// as shown in the parenthesized examples.
|
||||||
|
func (v *Version) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fmtParts := make([]string, len(v.segments))
|
||||||
|
for i, s := range v.segments {
|
||||||
|
// We can ignore err here since we've pre-parsed the values in segments
|
||||||
|
str := strconv.FormatInt(s, 10)
|
||||||
|
fmtParts[i] = str
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&buf, strings.Join(fmtParts, "."))
|
||||||
|
if v.pre != "" {
|
||||||
|
fmt.Fprintf(&buf, "-%s", v.pre)
|
||||||
|
}
|
||||||
|
if v.metadata != "" {
|
||||||
|
fmt.Fprintf(&buf, "+%s", v.metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original returns the original parsed version as-is, including any
|
||||||
|
// potential whitespace, `v` prefix, etc.
|
||||||
|
func (v *Version) Original() string {
|
||||||
|
return v.original
|
||||||
|
}
|
17
vendor/github.com/hashicorp/go-version/version_collection.go
generated
vendored
Normal file
17
vendor/github.com/hashicorp/go-version/version_collection.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
// Collection is a type that implements the sort.Interface interface
|
||||||
|
// so that versions can be sorted.
|
||||||
|
type Collection []*Version
|
||||||
|
|
||||||
|
func (v Collection) Len() int {
|
||||||
|
return len(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Collection) Less(i, j int) bool {
|
||||||
|
return v[i].LessThan(v[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Collection) Swap(i, j int) {
|
||||||
|
v[i], v[j] = v[j], v[i]
|
||||||
|
}
|
8
vendor/github.com/sethvargo/go-envconfig/AUTHORS
generated
vendored
Normal file
8
vendor/github.com/sethvargo/go-envconfig/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# This is the list of envconfig authors for copyright purposes.
|
||||||
|
#
|
||||||
|
# This does not necessarily list everyone who has contributed code, since in
|
||||||
|
# some cases, their employer may be the copyright holder. To see the full list
|
||||||
|
# of contributors, see the revision history in source control.
|
||||||
|
|
||||||
|
Google LLC
|
||||||
|
Seth Vargo
|
202
vendor/github.com/sethvargo/go-envconfig/LICENSE
generated
vendored
Normal file
202
vendor/github.com/sethvargo/go-envconfig/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
32
vendor/github.com/sethvargo/go-envconfig/Makefile
generated
vendored
Normal file
32
vendor/github.com/sethvargo/go-envconfig/Makefile
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright The envconfig Authors
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
test:
|
||||||
|
@go test \
|
||||||
|
-count=1 \
|
||||||
|
-short \
|
||||||
|
-timeout=5m \
|
||||||
|
-vet="${VETTERS}" \
|
||||||
|
./...
|
||||||
|
.PHONY: test
|
||||||
|
|
||||||
|
test-acc:
|
||||||
|
@go test \
|
||||||
|
-count=1 \
|
||||||
|
-race \
|
||||||
|
-shuffle=on \
|
||||||
|
-timeout=10m \
|
||||||
|
-vet="${VETTERS}" \
|
||||||
|
./...
|
||||||
|
.PHONY: test-acc
|
405
vendor/github.com/sethvargo/go-envconfig/README.md
generated
vendored
Normal file
405
vendor/github.com/sethvargo/go-envconfig/README.md
generated
vendored
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
# Envconfig
|
||||||
|
|
||||||
|
[![GoDoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/mod/github.com/sethvargo/go-envconfig)
|
||||||
|
[![GitHub Actions](https://img.shields.io/github/workflow/status/sethvargo/go-envconfig/unit/main?style=flat-square)](https://github.com/sethvargo/go-envconfig/actions?query=branch%3Amain+-event%3Aschedule)
|
||||||
|
|
||||||
|
Envconfig populates struct field values based on environment variables or
|
||||||
|
arbitrary lookup functions. It supports pre-setting mutations, which is useful
|
||||||
|
for things like converting values to uppercase, trimming whitespace, or looking
|
||||||
|
up secrets.
|
||||||
|
|
||||||
|
**Note:** Versions prior to v0.2 used a different import path. This README and
|
||||||
|
examples are for v0.2+.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Define a struct with fields using the `env` tag:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyConfig struct {
|
||||||
|
Port int `env:"PORT"`
|
||||||
|
Username string `env:"USERNAME"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Set some environment variables:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export PORT=5555
|
||||||
|
export USERNAME=yoyo
|
||||||
|
```
|
||||||
|
|
||||||
|
Process it using envconfig:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/sethvargo/go-envconfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
var c MyConfig
|
||||||
|
if err := envconfig.Process(ctx, &c); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// c.Port = 5555
|
||||||
|
// c.Username = "yoyo"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use nested structs, just remember that any fields you want to
|
||||||
|
process must be public:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyConfig struct {
|
||||||
|
Database *DatabaseConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type DatabaseConfig struct {
|
||||||
|
Port int `env:"PORT"`
|
||||||
|
Username string `env:"USERNAME"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Use the `env` struct tag to define configuration.
|
||||||
|
|
||||||
|
### Overwrite
|
||||||
|
|
||||||
|
If overwrite is set, the value will be overwritten if there is an
|
||||||
|
environment variable match regardless if the value is non-zero.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
Port int `env:"PORT,overwrite"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
If a field is required, processing will error if the environment variable is
|
||||||
|
unset.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
Port int `env:"PORT,required"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It is invalid to have a field as both `required` and `default`.
|
||||||
|
|
||||||
|
### Default
|
||||||
|
|
||||||
|
If an environment variable is not set, the field will be set to the default
|
||||||
|
value. Note that the environment variable must not be set (e.g. `unset PORT`).
|
||||||
|
If the environment variable is the empty string, that counts as a "value" and
|
||||||
|
the default will not be used.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
Port int `env:"PORT,default=5555"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set the default value to another field or value from the
|
||||||
|
environment, for example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
DefaultPort int `env:"DEFAULT_PORT,default=5555"`
|
||||||
|
Port int `env:"OVERRIDE_PORT,default=$DEFAULT_PORT"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The value for `Port` will default to the value of `DEFAULT_PORT`.
|
||||||
|
|
||||||
|
It is invalid to have a field as both `required` and `default`.
|
||||||
|
|
||||||
|
### Prefix
|
||||||
|
|
||||||
|
For shared, embedded structs, you can define a prefix to use when processing
|
||||||
|
struct values for that embed.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type SharedConfig struct {
|
||||||
|
Port int `env:"PORT,default=5555"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server1 struct {
|
||||||
|
// This processes Port from $FOO_PORT.
|
||||||
|
*SharedConfig `env:",prefix=FOO_"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server2 struct {
|
||||||
|
// This processes Port from $BAR_PORT.
|
||||||
|
*SharedConfig `env:",prefix=BAR_"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It is invalid to specify a prefix on non-struct fields.
|
||||||
|
|
||||||
|
### Delimiter
|
||||||
|
|
||||||
|
When parsing maps and slices, a comma (`,`) is the default element delimiter.
|
||||||
|
Define a custom delimiter with `delimiter`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
MyVar map[string]string `env:"MYVAR,delimiter=;"`
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="a:1;b:2"
|
||||||
|
# map[string]string{"a":"1", "b":"2"}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is especially helpful when your values include the default delimiter
|
||||||
|
character.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="a:1,2,3;b:4,5"
|
||||||
|
# map[string]string{"a":"1,2,3", "b":"4,5"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Separator
|
||||||
|
|
||||||
|
When parsing maps, a colon (`:`) is the default key-value separator. Define a
|
||||||
|
separator with `separator`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
MyVar map[string]string `env:"MYVAR,separator=="`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="a=b,c=d"
|
||||||
|
# map[string]string{"a":"b", "c":"d"}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is especially helpful when your keys or values include the default
|
||||||
|
separator character.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="client=abcd::1/128,backend=abcd::2/128"
|
||||||
|
# map[string]string{"client":"abcd::1/128", "backend":"abcd::2/128"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complex Types
|
||||||
|
|
||||||
|
### Durations
|
||||||
|
|
||||||
|
In the environment, `time.Duration` values are specified as a parsable Go
|
||||||
|
duration:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
MyVar time.Duration `env:"MYVAR"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="10m" # 10 * time.Minute
|
||||||
|
```
|
||||||
|
|
||||||
|
### TextUnmarshaler / BinaryUnmarshaler
|
||||||
|
|
||||||
|
Types that implement `TextUnmarshaler` or `BinaryUnmarshaler` are processed as such.
|
||||||
|
|
||||||
|
### json.Unmarshaler
|
||||||
|
|
||||||
|
Types that implement `json.Unmarshaler` are processed as such.
|
||||||
|
|
||||||
|
### gob.Decoder
|
||||||
|
|
||||||
|
Types that implement `gob.Decoder` are processed as such.
|
||||||
|
|
||||||
|
|
||||||
|
### Slices
|
||||||
|
|
||||||
|
Slices are specified as comma-separated values:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
MyVar []string `env:"MYVAR"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="a,b,c,d" # []string{"a", "b", "c", "d"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that byte slices are special cased and interpreted as strings from the
|
||||||
|
environment.
|
||||||
|
|
||||||
|
### Maps
|
||||||
|
|
||||||
|
Maps are specified as comma-separated key:value pairs:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
MyVar map[string]string `env:"MYVAR"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MYVAR="a:b,c:d" # map[string]string{"a":"b", "c":"d"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structs
|
||||||
|
|
||||||
|
Envconfig walks the entire struct, including nested structs, so deeply-nested
|
||||||
|
fields are also supported.
|
||||||
|
|
||||||
|
If a nested struct is a pointer type, it will automatically be instantianted to
|
||||||
|
the non-nil value. To change this behavior, see
|
||||||
|
(Initialization)[#Initialization].
|
||||||
|
|
||||||
|
|
||||||
|
### Custom
|
||||||
|
|
||||||
|
You can also define your own decoder for structs (see below).
|
||||||
|
|
||||||
|
|
||||||
|
## Prefixing
|
||||||
|
|
||||||
|
You can define a custom prefix using the `PrefixLookuper`. This will lookup
|
||||||
|
values in the environment by prefixing the keys with the provided value:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
MyVar string `env:"MYVAR"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Process variables, but look for the "APP_" prefix.
|
||||||
|
l := envconfig.PrefixLookuper("APP_", envconfig.OsLookuper())
|
||||||
|
if err := envconfig.ProcessWith(ctx, &c, l); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export APP_MYVAR="foo"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
By default, all pointer fields are initialized (allocated) so they are not
|
||||||
|
`nil`. To disable this behavior, use the tag the field as `noinit`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
// Without `noinit`, DeleteUser would be initialized to the default boolean
|
||||||
|
// value. With `noinit`, if the environment variable is not given, the value
|
||||||
|
// is kept as uninitialized (nil).
|
||||||
|
DeleteUser *bool `env:"DELETE_USER, noinit"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This also applies to nested fields in a struct:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type ParentConfig struct {
|
||||||
|
// Without `noinit` tag, `Child` would be set to `&ChildConfig{}` whether
|
||||||
|
// or not `FIELD` is set in the env var.
|
||||||
|
// With `noinit`, `Child` would stay nil if `FIELD` is not set in the env var.
|
||||||
|
Child *ChildConfig `env:",noinit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChildConfig struct {
|
||||||
|
Field string `env:"FIELD"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `noinit` tag is only applicable for pointer fields. Putting the tag on a
|
||||||
|
non-struct-pointer will return an error.
|
||||||
|
|
||||||
|
|
||||||
|
## Extension
|
||||||
|
|
||||||
|
All built-in types are supported except Func and Chan. If you need to define a
|
||||||
|
custom decoder, implement the `Decoder` interface:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type MyStruct struct {
|
||||||
|
field string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *MyStruct) EnvDecode(val string) error {
|
||||||
|
v.field = fmt.Sprintf("PREFIX-%s", val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ envconfig.Decoder = (*MyStruct)(nil) // interface check
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to modify environment variable values before processing, you can
|
||||||
|
specify a custom `Mutator`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Config struct {
|
||||||
|
Password `env:"PASSWORD"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveSecretFunc(ctx context.Context, key, value string) (string, error) {
|
||||||
|
if strings.HasPrefix(value, "secret://") {
|
||||||
|
return secretmanager.Resolve(ctx, value) // example
|
||||||
|
}
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
envconfig.ProcessWith(ctx, &config, envconfig.OsLookuper(), resolveSecretFunc)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Relying on the environment in tests can be troublesome because environment
|
||||||
|
variables are global, which makes it difficult to parallelize the tests.
|
||||||
|
Envconfig supports extracting data from anything that returns a value:
|
||||||
|
|
||||||
|
```go
|
||||||
|
lookuper := envconfig.MapLookuper(map[string]string{
|
||||||
|
"FOO": "bar",
|
||||||
|
"ZIP": "zap",
|
||||||
|
})
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
envconfig.ProcessWith(ctx, &config, lookuper)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can parallelize all your tests by providing a map for the lookup
|
||||||
|
function. In fact, that's how the tests in this repo work, so check there for an
|
||||||
|
example.
|
||||||
|
|
||||||
|
You can also combine multiple lookupers with `MultiLookuper`. See the GoDoc for
|
||||||
|
more information and examples.
|
||||||
|
|
||||||
|
|
||||||
|
## Inspiration
|
||||||
|
|
||||||
|
This library is conceptually similar to [kelseyhightower/envconfig](https://github.com/kelseyhightower/envconfig), with the following
|
||||||
|
major behavioral differences:
|
||||||
|
|
||||||
|
- Adds support for specifying a custom lookup function (such as a map), which
|
||||||
|
is useful for testing.
|
||||||
|
|
||||||
|
- Only populates fields if they contain zero or nil values if `overwrite` is unset.
|
||||||
|
This means you can pre-initialize a struct and any pre-populated fields will not
|
||||||
|
be overwritten during processing.
|
||||||
|
|
||||||
|
- Support for interpolation. The default value for a field can be the value of
|
||||||
|
another field.
|
||||||
|
|
||||||
|
- Support for arbitrary mutators that change/resolve data before type
|
||||||
|
conversion.
|
57
vendor/github.com/sethvargo/go-envconfig/decoding.go
generated
vendored
Normal file
57
vendor/github.com/sethvargo/go-envconfig/decoding.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright The envconfig Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package envconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Base64Bytes is a slice of bytes where the information is base64-encoded in
|
||||||
|
// the environment variable.
|
||||||
|
type Base64Bytes []byte
|
||||||
|
|
||||||
|
// EnvDecode implements env.Decoder.
|
||||||
|
func (b *Base64Bytes) EnvDecode(val string) error {
|
||||||
|
val = strings.ReplaceAll(val, "+", "-")
|
||||||
|
val = strings.ReplaceAll(val, "/", "_")
|
||||||
|
val = strings.TrimRight(val, "=")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
*b, err = base64.RawURLEncoding.DecodeString(val)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the underlying bytes.
|
||||||
|
func (b Base64Bytes) Bytes() []byte {
|
||||||
|
return []byte(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HexBytes is a slice of bytes where the information is hex-encoded in the
|
||||||
|
// environment variable.
|
||||||
|
type HexBytes []byte
|
||||||
|
|
||||||
|
// EnvDecode implements env.Decoder.
|
||||||
|
func (b *HexBytes) EnvDecode(val string) error {
|
||||||
|
var err error
|
||||||
|
*b, err = hex.DecodeString(val)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns the underlying bytes.
|
||||||
|
func (b HexBytes) Bytes() []byte {
|
||||||
|
return []byte(b)
|
||||||
|
}
|
691
vendor/github.com/sethvargo/go-envconfig/envconfig.go
generated
vendored
Normal file
691
vendor/github.com/sethvargo/go-envconfig/envconfig.go
generated
vendored
Normal file
@ -0,0 +1,691 @@
|
|||||||
|
// Copyright The envconfig Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package envconfig populates struct fields based on environment variable
|
||||||
|
// values (or anything that responds to "Lookup"). Structs declare their
|
||||||
|
// environment dependencies using the `env` tag with the key being the name of
|
||||||
|
// the environment variable, case sensitive.
|
||||||
|
//
|
||||||
|
// type MyStruct struct {
|
||||||
|
// A string `env:"A"` // resolves A to $A
|
||||||
|
// B string `env:"B,required"` // resolves B to $B, errors if $B is unset
|
||||||
|
// C string `env:"C,default=foo"` // resolves C to $C, defaults to "foo"
|
||||||
|
//
|
||||||
|
// D string `env:"D,required,default=foo"` // error, cannot be required and default
|
||||||
|
// E string `env:""` // error, must specify key
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// All built-in types are supported except Func and Chan. If you need to define
|
||||||
|
// a custom decoder, implement Decoder:
|
||||||
|
//
|
||||||
|
// type MyStruct struct {
|
||||||
|
// field string
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (v *MyStruct) EnvDecode(val string) error {
|
||||||
|
// v.field = fmt.Sprintf("PREFIX-%s", val)
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// In the environment, slices are specified as comma-separated values:
|
||||||
|
//
|
||||||
|
// export MYVAR="a,b,c,d" // []string{"a", "b", "c", "d"}
|
||||||
|
//
|
||||||
|
// In the environment, maps are specified as comma-separated key:value pairs:
|
||||||
|
//
|
||||||
|
// export MYVAR="a:b,c:d" // map[string]string{"a":"b", "c":"d"}
|
||||||
|
//
|
||||||
|
// If you need to modify environment variable values before processing, you can
|
||||||
|
// specify a custom mutator:
|
||||||
|
//
|
||||||
|
// type Config struct {
|
||||||
|
// Password `env:"PASSWORD_SECRET"`
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func resolveSecretFunc(ctx context.Context, key, value string) (string, error) {
|
||||||
|
// if strings.HasPrefix(value, "secret://") {
|
||||||
|
// return secretmanager.Resolve(ctx, value) // example
|
||||||
|
// }
|
||||||
|
// return value, nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var config Config
|
||||||
|
// ProcessWith(&config, OsLookuper(), resolveSecretFunc)
|
||||||
|
//
|
||||||
|
package envconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding"
|
||||||
|
"encoding/gob"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
envTag = "env"
|
||||||
|
|
||||||
|
optDefault = "default="
|
||||||
|
optDelimiter = "delimiter="
|
||||||
|
optNoInit = "noinit"
|
||||||
|
optOverwrite = "overwrite"
|
||||||
|
optPrefix = "prefix="
|
||||||
|
optRequired = "required"
|
||||||
|
optSeparator = "separator="
|
||||||
|
|
||||||
|
defaultDelimiter = ","
|
||||||
|
defaultSeparator = ":"
|
||||||
|
)
|
||||||
|
|
||||||
|
var envvarNameRe = regexp.MustCompile(`\A[a-zA-Z_][a-zA-Z0-9_]*\z`)
|
||||||
|
|
||||||
|
// Error is a custom error type for errors returned by envconfig.
|
||||||
|
type Error string
|
||||||
|
|
||||||
|
// Error implements error.
|
||||||
|
func (e Error) Error() string {
|
||||||
|
return string(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrInvalidEnvvarName = Error("invalid environment variable name")
|
||||||
|
ErrInvalidMapItem = Error("invalid map item")
|
||||||
|
ErrLookuperNil = Error("lookuper cannot be nil")
|
||||||
|
ErrMissingKey = Error("missing key")
|
||||||
|
ErrMissingRequired = Error("missing required value")
|
||||||
|
ErrNoInitNotPtr = Error("field must be a pointer to have noinit")
|
||||||
|
ErrNotPtr = Error("input must be a pointer")
|
||||||
|
ErrNotStruct = Error("input must be a struct")
|
||||||
|
ErrPrefixNotStruct = Error("prefix is only valid on struct types")
|
||||||
|
ErrPrivateField = Error("cannot parse private fields")
|
||||||
|
ErrRequiredAndDefault = Error("field cannot be required and have a default value")
|
||||||
|
ErrUnknownOption = Error("unknown option")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Lookuper is an interface that provides a lookup for a string-based key.
|
||||||
|
type Lookuper interface {
|
||||||
|
// Lookup searches for the given key and returns the corresponding string
|
||||||
|
// value. If a value is found, it returns the value and true. If a value is
|
||||||
|
// not found, it returns the empty string and false.
|
||||||
|
Lookup(key string) (string, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// osLookuper looks up environment configuration from the local environment.
|
||||||
|
type osLookuper struct{}
|
||||||
|
|
||||||
|
// Verify implements interface.
|
||||||
|
var _ Lookuper = (*osLookuper)(nil)
|
||||||
|
|
||||||
|
func (o *osLookuper) Lookup(key string) (string, bool) {
|
||||||
|
return os.LookupEnv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OsLookuper returns a lookuper that uses the environment (os.LookupEnv) to
|
||||||
|
// resolve values.
|
||||||
|
func OsLookuper() Lookuper {
|
||||||
|
return new(osLookuper)
|
||||||
|
}
|
||||||
|
|
||||||
|
type mapLookuper map[string]string
|
||||||
|
|
||||||
|
var _ Lookuper = (*mapLookuper)(nil)
|
||||||
|
|
||||||
|
func (m mapLookuper) Lookup(key string) (string, bool) {
|
||||||
|
v, ok := m[key]
|
||||||
|
return v, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapLookuper looks up environment configuration from a provided map. This is
|
||||||
|
// useful for testing, especially in parallel, since it does not require you to
|
||||||
|
// mutate the parent environment (which is stateful).
|
||||||
|
func MapLookuper(m map[string]string) Lookuper {
|
||||||
|
return mapLookuper(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
type multiLookuper struct {
|
||||||
|
ls []Lookuper
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Lookuper = (*multiLookuper)(nil)
|
||||||
|
|
||||||
|
func (m *multiLookuper) Lookup(key string) (string, bool) {
|
||||||
|
for _, l := range m.ls {
|
||||||
|
if v, ok := l.Lookup(key); ok {
|
||||||
|
return v, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrefixLookuper looks up environment configuration using the specified prefix.
|
||||||
|
// This is useful if you want all your variables to start with a particular
|
||||||
|
// prefix like "MY_APP_".
|
||||||
|
func PrefixLookuper(prefix string, l Lookuper) Lookuper {
|
||||||
|
if typ, ok := l.(*prefixLookuper); ok {
|
||||||
|
return &prefixLookuper{prefix: typ.prefix + prefix, l: typ.l}
|
||||||
|
}
|
||||||
|
return &prefixLookuper{prefix: prefix, l: l}
|
||||||
|
}
|
||||||
|
|
||||||
|
type prefixLookuper struct {
|
||||||
|
l Lookuper
|
||||||
|
prefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prefixLookuper) Lookup(key string) (string, bool) {
|
||||||
|
return p.l.Lookup(p.prefix + key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiLookuper wraps a collection of lookupers. It does not combine them, and
|
||||||
|
// lookups appear in the order in which they are provided to the initializer.
|
||||||
|
func MultiLookuper(lookupers ...Lookuper) Lookuper {
|
||||||
|
return &multiLookuper{ls: lookupers}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoder is an interface that custom types/fields can implement to control how
|
||||||
|
// decoding takes place. For example:
|
||||||
|
//
|
||||||
|
// type MyType string
|
||||||
|
//
|
||||||
|
// func (mt MyType) EnvDecode(val string) error {
|
||||||
|
// return "CUSTOM-"+val
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
type Decoder interface {
|
||||||
|
EnvDecode(val string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// MutatorFunc is a function that mutates a given value before it is passed
|
||||||
|
// along for processing. This is useful if you want to mutate the environment
|
||||||
|
// variable value before it's converted to the proper type.
|
||||||
|
type MutatorFunc func(ctx context.Context, k, v string) (string, error)
|
||||||
|
|
||||||
|
// options are internal options for decoding.
|
||||||
|
type options struct {
|
||||||
|
Default string
|
||||||
|
Delimiter string
|
||||||
|
Prefix string
|
||||||
|
Separator string
|
||||||
|
NoInit bool
|
||||||
|
Overwrite bool
|
||||||
|
Required bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process processes the struct using the environment. See ProcessWith for a
|
||||||
|
// more customizable version.
|
||||||
|
func Process(ctx context.Context, i interface{}) error {
|
||||||
|
return ProcessWith(ctx, i, OsLookuper())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessWith processes the given interface with the given lookuper. See the
|
||||||
|
// package-level documentation for specific examples and behaviors.
|
||||||
|
func ProcessWith(ctx context.Context, i interface{}, l Lookuper, fns ...MutatorFunc) error {
|
||||||
|
return processWith(ctx, i, l, false, fns...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// processWith is a helper that captures whether the parent wanted
|
||||||
|
// initialization.
|
||||||
|
func processWith(ctx context.Context, i interface{}, l Lookuper, parentNoInit bool, fns ...MutatorFunc) error {
|
||||||
|
if l == nil {
|
||||||
|
return ErrLookuperNil
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.ValueOf(i)
|
||||||
|
if v.Kind() != reflect.Ptr {
|
||||||
|
return ErrNotPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
e := v.Elem()
|
||||||
|
if e.Kind() != reflect.Struct {
|
||||||
|
return ErrNotStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
t := e.Type()
|
||||||
|
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
ef := e.Field(i)
|
||||||
|
tf := t.Field(i)
|
||||||
|
tag := tf.Tag.Get(envTag)
|
||||||
|
|
||||||
|
if !ef.CanSet() {
|
||||||
|
if tag != "" {
|
||||||
|
// There's an "env" tag on a private field, we can't alter it, and it's
|
||||||
|
// likely a mistake. Return an error so the user can handle.
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, ErrPrivateField)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise continue to the next field.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the key and options.
|
||||||
|
key, opts, err := keyAndOpts(tag)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoInit is only permitted on pointers.
|
||||||
|
if opts.NoInit && ef.Kind() != reflect.Ptr {
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, ErrNoInitNotPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
isNilStructPtr := false
|
||||||
|
setNilStruct := func(v reflect.Value) {
|
||||||
|
origin := e.Field(i)
|
||||||
|
if isNilStructPtr {
|
||||||
|
empty := reflect.New(origin.Type().Elem()).Interface()
|
||||||
|
// If a struct (after traversal) equals to the empty value, it means
|
||||||
|
// nothing was changed in any sub-fields. With the noinit opt, we skip
|
||||||
|
// setting the empty value to the original struct pointer (aka. keep it
|
||||||
|
// nil).
|
||||||
|
if !reflect.DeepEqual(v.Interface(), empty) || (!opts.NoInit && !parentNoInit) {
|
||||||
|
origin.Set(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize pointer structs.
|
||||||
|
for ef.Kind() == reflect.Ptr {
|
||||||
|
if ef.IsNil() {
|
||||||
|
if ef.Type().Elem().Kind() != reflect.Struct {
|
||||||
|
// This is a nil pointer to something that isn't a struct, like
|
||||||
|
// *string. Move along.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
isNilStructPtr = true
|
||||||
|
// Use an empty struct of the type so we can traverse.
|
||||||
|
ef = reflect.New(ef.Type().Elem()).Elem()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ef = ef.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case handle structs. This has to come after the value resolution in
|
||||||
|
// case the struct has a custom decoder.
|
||||||
|
if ef.Kind() == reflect.Struct {
|
||||||
|
for ef.CanAddr() {
|
||||||
|
ef = ef.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup the value, ignoring an error if the key isn't defined. This is
|
||||||
|
// required for nested structs that don't declare their own `env` keys,
|
||||||
|
// but have internal fields with an `env` defined.
|
||||||
|
val, found, usedDefault, err := lookup(key, opts, l)
|
||||||
|
if err != nil && !errors.Is(err, ErrMissingKey) {
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if found || usedDefault {
|
||||||
|
if ok, err := processAsDecoder(val, ef); ok {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
setNilStruct(ef)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plu := l
|
||||||
|
if opts.Prefix != "" {
|
||||||
|
plu = PrefixLookuper(opts.Prefix, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := processWith(ctx, ef.Interface(), plu, opts.NoInit, fns...); err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
setNilStruct(ef)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's invalid to have a prefix on a non-struct field.
|
||||||
|
if opts.Prefix != "" {
|
||||||
|
return ErrPrefixNotStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop processing if there's no env tag (this comes after nested parsing),
|
||||||
|
// in case there's an env tag in an embedded struct.
|
||||||
|
if tag == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// The field already has a non-zero value and overwrite is false, do not
|
||||||
|
// overwrite.
|
||||||
|
if !ef.IsZero() && !opts.Overwrite {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val, found, usedDefault, err := lookup(key, opts, l)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the field already has a non-zero value and there was no value directly
|
||||||
|
// specified, do not overwrite the existing field. We only want to overwrite
|
||||||
|
// when the envvar was provided directly.
|
||||||
|
if !ef.IsZero() && !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply any mutators. Mutators are applied after the lookup, but before any
|
||||||
|
// type conversions. They always resolve to a string (or error), so we don't
|
||||||
|
// call mutators when the environment variable was not set.
|
||||||
|
if found || usedDefault {
|
||||||
|
for _, fn := range fns {
|
||||||
|
if fn != nil {
|
||||||
|
val, err = fn(ctx, key, val)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", tf.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Delimiter is not defined set it to ","
|
||||||
|
if opts.Delimiter == "" {
|
||||||
|
opts.Delimiter = defaultDelimiter
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Separator is not defined set it to ":"
|
||||||
|
if opts.Separator == "" {
|
||||||
|
opts.Separator = defaultSeparator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set value.
|
||||||
|
if err := processField(val, ef, opts.Delimiter, opts.Separator, opts.NoInit); err != nil {
|
||||||
|
return fmt.Errorf("%s(%q): %w", tf.Name, val, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyAndOpts parses the given tag value (e.g. env:"foo,required") and
|
||||||
|
// returns the key name and options as a list.
|
||||||
|
func keyAndOpts(tag string) (string, *options, error) {
|
||||||
|
parts := strings.Split(tag, ",")
|
||||||
|
key, tagOpts := strings.TrimSpace(parts[0]), parts[1:]
|
||||||
|
|
||||||
|
if key != "" && !envvarNameRe.MatchString(key) {
|
||||||
|
return "", nil, fmt.Errorf("%q: %w ", key, ErrInvalidEnvvarName)
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts options
|
||||||
|
|
||||||
|
LOOP:
|
||||||
|
for i, o := range tagOpts {
|
||||||
|
o = strings.TrimSpace(o)
|
||||||
|
switch {
|
||||||
|
case o == optOverwrite:
|
||||||
|
opts.Overwrite = true
|
||||||
|
case o == optRequired:
|
||||||
|
opts.Required = true
|
||||||
|
case o == optNoInit:
|
||||||
|
opts.NoInit = true
|
||||||
|
case strings.HasPrefix(o, optPrefix):
|
||||||
|
opts.Prefix = strings.TrimPrefix(o, optPrefix)
|
||||||
|
case strings.HasPrefix(o, optDelimiter):
|
||||||
|
opts.Delimiter = strings.TrimPrefix(o, optDelimiter)
|
||||||
|
case strings.HasPrefix(o, optSeparator):
|
||||||
|
opts.Separator = strings.TrimPrefix(o, optSeparator)
|
||||||
|
case strings.HasPrefix(o, optDefault):
|
||||||
|
// If a default value was given, assume everything after is the provided
|
||||||
|
// value, including comma-seprated items.
|
||||||
|
o = strings.TrimLeft(strings.Join(tagOpts[i:], ","), " ")
|
||||||
|
opts.Default = strings.TrimPrefix(o, optDefault)
|
||||||
|
break LOOP
|
||||||
|
default:
|
||||||
|
return "", nil, fmt.Errorf("%q: %w", o, ErrUnknownOption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, &opts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup looks up the given key using the provided Lookuper and options. The
|
||||||
|
// first boolean parameter indicates whether the value was found in the
|
||||||
|
// lookuper. The second boolean parameter indicates whether the default value
|
||||||
|
// was used.
|
||||||
|
func lookup(key string, opts *options, l Lookuper) (string, bool, bool, error) {
|
||||||
|
if key == "" {
|
||||||
|
// The struct has something like `env:",required"`, which is likely a
|
||||||
|
// mistake. We could try to infer the envvar from the field name, but that
|
||||||
|
// feels too magical.
|
||||||
|
return "", false, false, ErrMissingKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Required && opts.Default != "" {
|
||||||
|
// Having a default value on a required value doesn't make sense.
|
||||||
|
return "", false, false, ErrRequiredAndDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup value.
|
||||||
|
val, found := l.Lookup(key)
|
||||||
|
if !found {
|
||||||
|
if opts.Required {
|
||||||
|
if pl, ok := l.(*prefixLookuper); ok {
|
||||||
|
key = pl.prefix + key
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", false, false, fmt.Errorf("%w: %s", ErrMissingRequired, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Default != "" {
|
||||||
|
// Expand the default value. This allows for a default value that maps to
|
||||||
|
// a different variable.
|
||||||
|
val = os.Expand(opts.Default, func(i string) string {
|
||||||
|
s, ok := l.Lookup(i)
|
||||||
|
if ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
})
|
||||||
|
|
||||||
|
return val, false, true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return val, found, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// processAsDecoder processes the given value as a decoder or custom
|
||||||
|
// unmarshaller.
|
||||||
|
func processAsDecoder(v string, ef reflect.Value) (bool, error) {
|
||||||
|
// Keep a running error. It's possible that a property might implement
|
||||||
|
// multiple decoders, and we don't know *which* decoder will succeed. If we
|
||||||
|
// get through all of them, we'll return the most recent error.
|
||||||
|
var imp bool
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Resolve any pointers.
|
||||||
|
for ef.CanAddr() {
|
||||||
|
ef = ef.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ef.CanInterface() {
|
||||||
|
iface := ef.Interface()
|
||||||
|
|
||||||
|
// If a developer chooses to implement the Decoder interface on a type,
|
||||||
|
// never attempt to use other decoders in case of failure. EnvDecode's
|
||||||
|
// decoding logic is "the right one", and the error returned (if any)
|
||||||
|
// is the most specific we can get.
|
||||||
|
if dec, ok := iface.(Decoder); ok {
|
||||||
|
imp = true
|
||||||
|
err = dec.EnvDecode(v)
|
||||||
|
return imp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tu, ok := iface.(encoding.TextUnmarshaler); ok {
|
||||||
|
imp = true
|
||||||
|
if err = tu.UnmarshalText([]byte(v)); err == nil {
|
||||||
|
return imp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tu, ok := iface.(json.Unmarshaler); ok {
|
||||||
|
imp = true
|
||||||
|
if err = tu.UnmarshalJSON([]byte(v)); err == nil {
|
||||||
|
return imp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tu, ok := iface.(encoding.BinaryUnmarshaler); ok {
|
||||||
|
imp = true
|
||||||
|
if err = tu.UnmarshalBinary([]byte(v)); err == nil {
|
||||||
|
return imp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tu, ok := iface.(gob.GobDecoder); ok {
|
||||||
|
imp = true
|
||||||
|
if err = tu.GobDecode([]byte(v)); err == nil {
|
||||||
|
return imp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return imp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func processField(v string, ef reflect.Value, delimiter, separator string, noInit bool) error {
|
||||||
|
// If the input value is empty and initialization is skipped, do nothing.
|
||||||
|
if v == "" && noInit {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle pointers and uninitialized pointers.
|
||||||
|
for ef.Type().Kind() == reflect.Ptr {
|
||||||
|
if ef.IsNil() {
|
||||||
|
ef.Set(reflect.New(ef.Type().Elem()))
|
||||||
|
}
|
||||||
|
ef = ef.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
tf := ef.Type()
|
||||||
|
tk := tf.Kind()
|
||||||
|
|
||||||
|
// Handle existing decoders.
|
||||||
|
if ok, err := processAsDecoder(v, ef); ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't check if the value is empty earlier, because the user might want
|
||||||
|
// to define a custom decoder and treat the empty variable as a special case.
|
||||||
|
// However, if we got this far, none of the remaining parsers will succeed, so
|
||||||
|
// bail out now.
|
||||||
|
if v == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch tk {
|
||||||
|
case reflect.Bool:
|
||||||
|
b, err := strconv.ParseBool(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ef.SetBool(b)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
f, err := strconv.ParseFloat(v, tf.Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ef.SetFloat(f)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
|
||||||
|
i, err := strconv.ParseInt(v, 0, tf.Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ef.SetInt(i)
|
||||||
|
case reflect.Int64:
|
||||||
|
// Special case time.Duration values.
|
||||||
|
if tf.PkgPath() == "time" && tf.Name() == "Duration" {
|
||||||
|
d, err := time.ParseDuration(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ef.SetInt(int64(d))
|
||||||
|
} else {
|
||||||
|
i, err := strconv.ParseInt(v, 0, tf.Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ef.SetInt(i)
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
ef.SetString(v)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
i, err := strconv.ParseUint(v, 0, tf.Bits())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ef.SetUint(i)
|
||||||
|
|
||||||
|
case reflect.Interface:
|
||||||
|
return fmt.Errorf("cannot decode into interfaces")
|
||||||
|
|
||||||
|
// Maps
|
||||||
|
case reflect.Map:
|
||||||
|
vals := strings.Split(v, delimiter)
|
||||||
|
mp := reflect.MakeMapWithSize(tf, len(vals))
|
||||||
|
for _, val := range vals {
|
||||||
|
pair := strings.SplitN(val, separator, 2)
|
||||||
|
if len(pair) < 2 {
|
||||||
|
return fmt.Errorf("%s: %w", val, ErrInvalidMapItem)
|
||||||
|
}
|
||||||
|
mKey, mVal := strings.TrimSpace(pair[0]), strings.TrimSpace(pair[1])
|
||||||
|
|
||||||
|
k := reflect.New(tf.Key()).Elem()
|
||||||
|
if err := processField(mKey, k, delimiter, separator, noInit); err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", mKey, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.New(tf.Elem()).Elem()
|
||||||
|
if err := processField(mVal, v, delimiter, separator, noInit); err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", mVal, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mp.SetMapIndex(k, v)
|
||||||
|
}
|
||||||
|
ef.Set(mp)
|
||||||
|
|
||||||
|
// Slices
|
||||||
|
case reflect.Slice:
|
||||||
|
// Special case: []byte
|
||||||
|
if tf.Elem().Kind() == reflect.Uint8 {
|
||||||
|
ef.Set(reflect.ValueOf([]byte(v)))
|
||||||
|
} else {
|
||||||
|
vals := strings.Split(v, delimiter)
|
||||||
|
s := reflect.MakeSlice(tf, len(vals), len(vals))
|
||||||
|
for i, val := range vals {
|
||||||
|
val = strings.TrimSpace(val)
|
||||||
|
if err := processField(val, s.Index(i), delimiter, separator, noInit); err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", val, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ef.Set(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
1
vendor/github.com/sethvargo/go-githubactions/.gitignore
generated
vendored
Normal file
1
vendor/github.com/sethvargo/go-githubactions/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
coverage.out
|
7
vendor/github.com/sethvargo/go-githubactions/AUTHORS
generated
vendored
Normal file
7
vendor/github.com/sethvargo/go-githubactions/AUTHORS
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This is the list of authors for copyright purposes.
|
||||||
|
#
|
||||||
|
# This does not necessarily list everyone who has contributed code, since in
|
||||||
|
# some cases, their employer may be the copyright holder. To see the full list
|
||||||
|
# of contributors, see the revision history in source control.
|
||||||
|
|
||||||
|
Seth Vargo
|
202
vendor/github.com/sethvargo/go-githubactions/LICENSE
generated
vendored
Normal file
202
vendor/github.com/sethvargo/go-githubactions/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
29
vendor/github.com/sethvargo/go-githubactions/Makefile
generated
vendored
Normal file
29
vendor/github.com/sethvargo/go-githubactions/Makefile
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Copyright 2020 The Authors
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
test:
|
||||||
|
@go test \
|
||||||
|
-count=1 \
|
||||||
|
-short \
|
||||||
|
-timeout=5m \
|
||||||
|
./...
|
||||||
|
.PHONY: test
|
||||||
|
|
||||||
|
test-acc:
|
||||||
|
@go test \
|
||||||
|
-count=1 \
|
||||||
|
-race \
|
||||||
|
-timeout=10m \
|
||||||
|
./...
|
||||||
|
.PHONY: test-acc
|
150
vendor/github.com/sethvargo/go-githubactions/README.md
generated
vendored
Normal file
150
vendor/github.com/sethvargo/go-githubactions/README.md
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# GitHub Actions SDK (Go)
|
||||||
|
|
||||||
|
[![GoDoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/sethvargo/go-githubactions)
|
||||||
|
[![GitHub Actions](https://img.shields.io/github/workflow/status/sethvargo/go-githubactions/Test?style=flat-square)](https://github.com/sethvargo/go-githubactions/actions?query=workflow%3ATest)
|
||||||
|
|
||||||
|
This library provides an SDK for authoring [GitHub Actions][gh-actions] in Go. It has no external dependencies and provides a Go-like interface for interacting with GitHub Actions' build system.
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Download the library:
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ go get -u github.com/sethvargo/go-githubactions/...
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The easiest way to use the library is by importing it and invoking the functions
|
||||||
|
at the root:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/sethvargo/go-githubactions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
val := githubactions.GetInput("val")
|
||||||
|
if val == "" {
|
||||||
|
githubactions.Fatalf("missing 'val'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also create an instance with custom fields that will be included in log messages:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/sethvargo/go-githubactions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
actions := githubactions.WithFieldsMap(map[string]string{
|
||||||
|
"file": "myfile.js",
|
||||||
|
"line": "100",
|
||||||
|
})
|
||||||
|
|
||||||
|
val := actions.GetInput("val")
|
||||||
|
if val == "" {
|
||||||
|
actions.Fatalf("missing 'val'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more examples and API documentation, please see the [Go docs][godoc].
|
||||||
|
|
||||||
|
|
||||||
|
## Publishing
|
||||||
|
|
||||||
|
There are multiple ways to publish GitHub Actions written in Go:
|
||||||
|
|
||||||
|
- [Composite actions](https://github.com/FerretDB/github-actions/blob/2ae30fd2cdb635d8aefdaf9f770257e156c9f77b/extract-docker-tag/action.yml)
|
||||||
|
- [Pre-compiled binaries with a shim](https://full-stack.blend.com/how-we-write-github-actions-in-go.html)
|
||||||
|
- Docker containers (see below)
|
||||||
|
|
||||||
|
By default, GitHub Actions expects actions to be written in Node.js. For other languages like Go, you need to provide a `Dockerfile` and entrypoint instructions in an `action.yml` file:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# your-repo/Dockerfile
|
||||||
|
FROM golang:1.18
|
||||||
|
RUN go build -o /bin/app .
|
||||||
|
ENTRYPOINT ["/bin/app"]
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# your-repo/action.yml
|
||||||
|
name: My action
|
||||||
|
author: My name
|
||||||
|
description: My description
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: docker
|
||||||
|
image: Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
And then users can import your action by the repository name:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# their-repo/.github/workflows/thing.yml
|
||||||
|
steps:
|
||||||
|
- name: My action
|
||||||
|
uses: username/repo@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
However, this will clone the entire repo and compile the Go code each time the action runs. Worse, it uses the Go base container which is a few hundred MBs and includes a ton of unnecessary things.
|
||||||
|
|
||||||
|
Fortunately, GitHub Actions can also source from a Docker container directly from Docker Hub:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- name: My action
|
||||||
|
uses: docker://username/repo:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Now we can precompile and publish our Go Action as a Docker container, but we need to make it much, much smaller first. This can be achieved using multi-stage Docker builds:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM golang:1.18 AS builder
|
||||||
|
|
||||||
|
ENV GO111MODULE=on \
|
||||||
|
CGO_ENABLED=0 \
|
||||||
|
GOOS=linux \
|
||||||
|
GOARCH=amd64
|
||||||
|
|
||||||
|
RUN apt-get -qq update && \
|
||||||
|
apt-get -yqq install upx
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go build \
|
||||||
|
-ldflags "-s -w -extldflags '-static'" \
|
||||||
|
-o /bin/app \
|
||||||
|
. \
|
||||||
|
&& strip /bin/app \
|
||||||
|
&& upx -q -9 /bin/app
|
||||||
|
|
||||||
|
RUN echo "nobody:x:65534:65534:Nobody:/:" > /etc_passwd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
|
COPY --from=builder /etc_passwd /etc/passwd
|
||||||
|
COPY --from=builder --chown=65534:0 /bin/app /app
|
||||||
|
|
||||||
|
USER nobody
|
||||||
|
ENTRYPOINT ["/app"]
|
||||||
|
```
|
||||||
|
|
||||||
|
The first step, uses a fat container to build, strip, and compress the compiled Go binary. Then, in the second step, the compiled and compressed binary is copied into a scratch (bare) container along with some SSL certificates and a `nobody` user in which to execute the container.
|
||||||
|
|
||||||
|
This will usually produce an image that is less than 10MB in size, making for
|
||||||
|
much faster builds.
|
||||||
|
|
||||||
|
|
||||||
|
[gh-actions]: https://github.com/features/actions
|
||||||
|
[godoc]: https://godoc.org/github.com/sethvargo/go-githubactions
|
576
vendor/github.com/sethvargo/go-githubactions/actions.go
generated
vendored
Normal file
576
vendor/github.com/sethvargo/go-githubactions/actions.go
generated
vendored
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
// Copyright 2020 The Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package githubactions provides an SDK for authoring GitHub Actions in Go. It
|
||||||
|
// has no external dependencies and provides a Go-like interface for interacting
|
||||||
|
// with GitHub Actions' build system.
|
||||||
|
package githubactions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sethvargo/go-envconfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// osExit allows `os.Exit()` to be stubbed during testing.
|
||||||
|
osExit = os.Exit
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
addMaskCmd = "add-mask"
|
||||||
|
|
||||||
|
envCmd = "env"
|
||||||
|
outputCmd = "output"
|
||||||
|
pathCmd = "path"
|
||||||
|
stateCmd = "state"
|
||||||
|
|
||||||
|
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
|
||||||
|
multiLineFileDelim = "_GitHubActionsFileCommandDelimeter_"
|
||||||
|
multilineFileCmd = "%s<<" + multiLineFileDelim + EOF + "%s" + EOF + multiLineFileDelim // ${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}
|
||||||
|
|
||||||
|
addMatcherCmd = "add-matcher"
|
||||||
|
removeMatcherCmd = "remove-matcher"
|
||||||
|
|
||||||
|
groupCmd = "group"
|
||||||
|
endGroupCmd = "endgroup"
|
||||||
|
|
||||||
|
stepSummaryCmd = "step-summary"
|
||||||
|
|
||||||
|
debugCmd = "debug"
|
||||||
|
noticeCmd = "notice"
|
||||||
|
warningCmd = "warning"
|
||||||
|
errorCmd = "error"
|
||||||
|
|
||||||
|
errFileCmdFmt = "unable to write command to the environment file: %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New creates a new wrapper with helpers for outputting information in GitHub
|
||||||
|
// actions format.
|
||||||
|
func New(opts ...Option) *Action {
|
||||||
|
a := &Action{
|
||||||
|
w: os.Stdout,
|
||||||
|
getenv: os.Getenv,
|
||||||
|
httpClient: &http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
a = opt(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action is an internal wrapper around GitHub Actions' output and magic
|
||||||
|
// strings.
|
||||||
|
type Action struct {
|
||||||
|
w io.Writer
|
||||||
|
fields CommandProperties
|
||||||
|
getenv GetenvFunc
|
||||||
|
httpClient *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueCommand issues a new GitHub actions Command. It panics if it cannot
|
||||||
|
// write to the output stream.
|
||||||
|
func (c *Action) IssueCommand(cmd *Command) {
|
||||||
|
if _, err := fmt.Fprint(c.w, cmd.String()+EOF); err != nil {
|
||||||
|
panic(fmt.Errorf("failed to issue command: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueFileCommand issues a new GitHub actions Command using environment files.
|
||||||
|
// It panics if writing to the file fails.
|
||||||
|
//
|
||||||
|
// https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#environment-files
|
||||||
|
//
|
||||||
|
// The TypeScript equivalent function:
|
||||||
|
//
|
||||||
|
// https://github.com/actions/toolkit/blob/4f7fb6513a355689f69f0849edeb369a4dc81729/packages/core/src/file-command.ts#L10-L23
|
||||||
|
//
|
||||||
|
// IssueFileCommand currently ignores the 'CommandProperties' field provided
|
||||||
|
// with the 'Command' argument as it's scope is unclear in the current
|
||||||
|
// TypeScript implementation.
|
||||||
|
func (c *Action) IssueFileCommand(cmd *Command) {
|
||||||
|
if err := c.issueFileCommand(cmd); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// issueFileCommand is an internal-only helper that issues the command and
|
||||||
|
// returns an error to make testing easier.
|
||||||
|
func (c *Action) issueFileCommand(cmd *Command) (retErr error) {
|
||||||
|
e := strings.ReplaceAll(cmd.Name, "-", "_")
|
||||||
|
e = strings.ToUpper(e)
|
||||||
|
e = "GITHUB_" + e
|
||||||
|
|
||||||
|
filepath := c.getenv(e)
|
||||||
|
msg := []byte(cmd.Message + EOF)
|
||||||
|
f, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
retErr = fmt.Errorf(errFileCmdFmt, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := f.Close(); err != nil && retErr == nil {
|
||||||
|
retErr = err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if _, err := f.Write(msg); err != nil {
|
||||||
|
retErr = fmt.Errorf(errFileCmdFmt, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMask adds a new field mask for the given string "p". After called, future
|
||||||
|
// attempts to log "p" will be replaced with "***" in log output. It panics if
|
||||||
|
// it cannot write to the output stream.
|
||||||
|
func (c *Action) AddMask(p string) {
|
||||||
|
// ::add-mask::<p>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: addMaskCmd,
|
||||||
|
Message: p,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMatcher adds a new matcher with the given file path. It panics if it
|
||||||
|
// cannot write to the output stream.
|
||||||
|
func (c *Action) AddMatcher(p string) {
|
||||||
|
// ::add-matcher::<p>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: addMatcherCmd,
|
||||||
|
Message: p,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMatcher removes a matcher with the given owner name. It panics if it
|
||||||
|
// cannot write to the output stream.
|
||||||
|
func (c *Action) RemoveMatcher(o string) {
|
||||||
|
// ::remove-matcher owner=<o>::
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: removeMatcherCmd,
|
||||||
|
Properties: CommandProperties{
|
||||||
|
"owner": o,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPath adds the string "p" to the path for the invocation. It panics if it
|
||||||
|
// cannot write to the output file.
|
||||||
|
//
|
||||||
|
// https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#adding-a-system-path
|
||||||
|
// https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
|
||||||
|
func (c *Action) AddPath(p string) {
|
||||||
|
c.IssueFileCommand(&Command{
|
||||||
|
Name: pathCmd,
|
||||||
|
Message: p,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveState saves state to be used in the "finally" post job entry point. It
|
||||||
|
// panics if it cannot write to the output stream.
|
||||||
|
//
|
||||||
|
// On 2022-10-11, GitHub deprecated "::save-state name=<k>::<v>" in favor of
|
||||||
|
// [environment files].
|
||||||
|
//
|
||||||
|
// [environment files]: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
|
||||||
|
func (c *Action) SaveState(k, v string) {
|
||||||
|
c.IssueFileCommand(&Command{
|
||||||
|
Name: stateCmd,
|
||||||
|
Message: fmt.Sprintf(multilineFileCmd, k, v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInput gets the input by the given name. It returns the empty string if the
|
||||||
|
// input is not defined.
|
||||||
|
func (c *Action) GetInput(i string) string {
|
||||||
|
e := strings.ReplaceAll(i, " ", "_")
|
||||||
|
e = strings.ToUpper(e)
|
||||||
|
e = "INPUT_" + e
|
||||||
|
return strings.TrimSpace(c.getenv(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group starts a new collapsable region up to the next ungroup invocation. It
|
||||||
|
// panics if it cannot write to the output stream.
|
||||||
|
func (c *Action) Group(t string) {
|
||||||
|
// ::group::<t>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: groupCmd,
|
||||||
|
Message: t,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndGroup ends the current group. It panics if it cannot write to the output
|
||||||
|
// stream.
|
||||||
|
func (c *Action) EndGroup() {
|
||||||
|
// ::endgroup::
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: endGroupCmd,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStepSummary writes the given markdown to the job summary. If a job summary
|
||||||
|
// already exists, this value is appended.
|
||||||
|
//
|
||||||
|
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary
|
||||||
|
// https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/
|
||||||
|
func (c *Action) AddStepSummary(markdown string) {
|
||||||
|
c.IssueFileCommand(&Command{
|
||||||
|
Name: stepSummaryCmd,
|
||||||
|
Message: markdown,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStepSummaryTemplate adds a summary template by parsing the given Go
|
||||||
|
// template using html/template with the given input data. See AddStepSummary
|
||||||
|
// for caveats.
|
||||||
|
//
|
||||||
|
// This primarily exists as a convenience function that renders a template.
|
||||||
|
func (c *Action) AddStepSummaryTemplate(tmpl string, data any) error {
|
||||||
|
t, err := template.New("").Parse(tmpl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse template: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
if err := t.Execute(&b, data); err != nil {
|
||||||
|
return fmt.Errorf("failed to execute template: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AddStepSummary(b.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEnv sets an environment variable. It panics if it cannot write to the
|
||||||
|
// output file.
|
||||||
|
//
|
||||||
|
// https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
|
||||||
|
// https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
|
||||||
|
func (c *Action) SetEnv(k, v string) {
|
||||||
|
c.IssueFileCommand(&Command{
|
||||||
|
Name: envCmd,
|
||||||
|
Message: fmt.Sprintf(multilineFileCmd, k, v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOutput sets an output parameter. It panics if it cannot write to the
|
||||||
|
// output stream.
|
||||||
|
//
|
||||||
|
// On 2022-10-11, GitHub deprecated "::set-output name=<k>::<v>" in favor of
|
||||||
|
// [environment files].
|
||||||
|
//
|
||||||
|
// [environment files]: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
|
||||||
|
func (c *Action) SetOutput(k, v string) {
|
||||||
|
c.IssueFileCommand(&Command{
|
||||||
|
Name: outputCmd,
|
||||||
|
Message: fmt.Sprintf(multilineFileCmd, k, v),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf prints a debug-level message. It follows the standard fmt.Printf
|
||||||
|
// arguments, appending an OS-specific line break to the end of the message. It
|
||||||
|
// panics if it cannot write to the output stream.
|
||||||
|
func (c *Action) Debugf(msg string, args ...any) {
|
||||||
|
// ::debug <c.fields>::<msg, args>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: debugCmd,
|
||||||
|
Message: fmt.Sprintf(msg, args...),
|
||||||
|
Properties: c.fields,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Noticef prints a notice-level message. It follows the standard fmt.Printf
|
||||||
|
// arguments, appending an OS-specific line break to the end of the message. It
|
||||||
|
// panics if it cannot write to the output stream.
|
||||||
|
func (c *Action) Noticef(msg string, args ...any) {
|
||||||
|
// ::notice <c.fields>::<msg, args>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: noticeCmd,
|
||||||
|
Message: fmt.Sprintf(msg, args...),
|
||||||
|
Properties: c.fields,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warningf prints a warning-level message. It follows the standard fmt.Printf
|
||||||
|
// arguments, appending an OS-specific line break to the end of the message. It
|
||||||
|
// panics if it cannot write to the output stream.
|
||||||
|
func (c *Action) Warningf(msg string, args ...any) {
|
||||||
|
// ::warning <c.fields>::<msg, args>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: warningCmd,
|
||||||
|
Message: fmt.Sprintf(msg, args...),
|
||||||
|
Properties: c.fields,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf prints a error-level message. It follows the standard fmt.Printf
|
||||||
|
// arguments, appending an OS-specific line break to the end of the message. It
|
||||||
|
// panics if it cannot write to the output stream.
|
||||||
|
func (c *Action) Errorf(msg string, args ...any) {
|
||||||
|
// ::error <c.fields>::<msg, args>
|
||||||
|
c.IssueCommand(&Command{
|
||||||
|
Name: errorCmd,
|
||||||
|
Message: fmt.Sprintf(msg, args...),
|
||||||
|
Properties: c.fields,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf prints a error-level message and exits. This is equivalent to Errorf
|
||||||
|
// followed by os.Exit(1).
|
||||||
|
func (c *Action) Fatalf(msg string, args ...any) {
|
||||||
|
c.Errorf(msg, args...)
|
||||||
|
osExit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof prints message to stdout without any level annotations. It follows the
|
||||||
|
// standard fmt.Printf arguments, appending an OS-specific line break to the end
|
||||||
|
// of the message. It panics if it cannot write to the output stream.
|
||||||
|
func (c *Action) Infof(msg string, args ...any) {
|
||||||
|
if _, err := fmt.Fprintf(c.w, msg+EOF, args...); err != nil {
|
||||||
|
panic(fmt.Errorf("failed to write info command: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFieldsSlice includes the provided fields in log output. "f" must be a
|
||||||
|
// slice of k=v pairs. The given slice will be sorted. It panics if any of the
|
||||||
|
// string in the given slice does not construct a valid 'key=value' pair.
|
||||||
|
func (c *Action) WithFieldsSlice(f []string) *Action {
|
||||||
|
m := make(CommandProperties)
|
||||||
|
for _, s := range f {
|
||||||
|
pair := strings.SplitN(s, "=", 2)
|
||||||
|
if len(pair) < 2 {
|
||||||
|
panic(fmt.Sprintf("%q is not a proper k=v pair!", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
m[pair[0]] = pair[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.WithFieldsMap(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFieldsMap includes the provided fields in log output. The fields in "m"
|
||||||
|
// are automatically converted to k=v pairs and sorted.
|
||||||
|
func (c *Action) WithFieldsMap(m map[string]string) *Action {
|
||||||
|
return &Action{
|
||||||
|
w: c.w,
|
||||||
|
fields: m,
|
||||||
|
getenv: c.getenv,
|
||||||
|
httpClient: c.httpClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// idTokenResponse is the response from minting an ID token.
|
||||||
|
type idTokenResponse struct {
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIDToken returns the GitHub OIDC token from the GitHub Actions runtime.
|
||||||
|
func (c *Action) GetIDToken(ctx context.Context, audience string) (string, error) {
|
||||||
|
requestURL := c.getenv("ACTIONS_ID_TOKEN_REQUEST_URL")
|
||||||
|
if requestURL == "" {
|
||||||
|
return "", fmt.Errorf("missing ACTIONS_ID_TOKEN_REQUEST_URL in environment")
|
||||||
|
}
|
||||||
|
|
||||||
|
requestToken := c.getenv("ACTIONS_ID_TOKEN_REQUEST_TOKEN")
|
||||||
|
if requestToken == "" {
|
||||||
|
return "", fmt.Errorf("missing ACTIONS_ID_TOKEN_REQUEST_TOKEN in environment")
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(requestURL)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to parse request URL: %w", err)
|
||||||
|
}
|
||||||
|
if audience != "" {
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("audience", audience)
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create HTTP request: %w", err)
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+requestToken)
|
||||||
|
|
||||||
|
resp, err := c.httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to make HTTP request: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// This has moved to the io package in Go 1.16, but we still support up to Go
|
||||||
|
// 1.13 for now.
|
||||||
|
body, err := io.ReadAll(io.LimitReader(resp.Body, 64*1000))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to read response body: %w", err)
|
||||||
|
}
|
||||||
|
body = bytes.TrimSpace(body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return "", fmt.Errorf("non-successful response from minting OIDC token: %s", body)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenResp idTokenResponse
|
||||||
|
if err := json.Unmarshal(body, &tokenResp); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to process response as JSON: %w", err)
|
||||||
|
}
|
||||||
|
return tokenResp.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getenv retrieves the value of the environment variable named by the key.
|
||||||
|
// It uses an internal function that can be set with `WithGetenv`.
|
||||||
|
func (c *Action) Getenv(key string) string {
|
||||||
|
return c.getenv(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetenvFunc is an abstraction to make tests feasible for commands that
|
||||||
|
// interact with environment variables.
|
||||||
|
type GetenvFunc func(key string) string
|
||||||
|
|
||||||
|
// GitHubContext of current workflow.
|
||||||
|
//
|
||||||
|
// See: https://docs.github.com/en/actions/learn-github-actions/environment-variables
|
||||||
|
type GitHubContext struct {
|
||||||
|
Action string `env:"GITHUB_ACTION"`
|
||||||
|
ActionPath string `env:"GITHUB_ACTION_PATH"`
|
||||||
|
ActionRepository string `env:"GITHUB_ACTION_REPOSITORY"`
|
||||||
|
Actions bool `env:"GITHUB_ACTIONS"`
|
||||||
|
Actor string `env:"GITHUB_ACTOR"`
|
||||||
|
APIURL string `env:"GITHUB_API_URL,default=https://api.github.com"`
|
||||||
|
BaseRef string `env:"GITHUB_BASE_REF"`
|
||||||
|
Env string `env:"GITHUB_ENV"`
|
||||||
|
EventName string `env:"GITHUB_EVENT_NAME"`
|
||||||
|
EventPath string `env:"GITHUB_EVENT_PATH"`
|
||||||
|
GraphqlURL string `env:"GITHUB_GRAPHQL_URL,default=https://api.github.com/graphql"`
|
||||||
|
HeadRef string `env:"GITHUB_HEAD_REF"`
|
||||||
|
Job string `env:"GITHUB_JOB"`
|
||||||
|
Path string `env:"GITHUB_PATH"`
|
||||||
|
Ref string `env:"GITHUB_REF"`
|
||||||
|
RefName string `env:"GITHUB_REF_NAME"`
|
||||||
|
RefProtected bool `env:"GITHUB_REF_PROTECTED"`
|
||||||
|
RefType string `env:"GITHUB_REF_TYPE"`
|
||||||
|
|
||||||
|
// Repository is the owner and repository name. For example, octocat/Hello-World
|
||||||
|
// It is not recommended to use this field to acquire the repository name
|
||||||
|
// but to use the Repo method instead.
|
||||||
|
Repository string `env:"GITHUB_REPOSITORY"`
|
||||||
|
|
||||||
|
// RepositoryOwner is the repository owner. For example, octocat
|
||||||
|
// It is not recommended to use this field to acquire the repository owner
|
||||||
|
// but to use the Repo method instead.
|
||||||
|
RepositoryOwner string `env:"GITHUB_REPOSITORY_OWNER"`
|
||||||
|
|
||||||
|
RetentionDays int64 `env:"GITHUB_RETENTION_DAYS"`
|
||||||
|
RunAttempt int64 `env:"GITHUB_RUN_ATTEMPT"`
|
||||||
|
RunID int64 `env:"GITHUB_RUN_ID"`
|
||||||
|
RunNumber int64 `env:"GITHUB_RUN_NUMBER"`
|
||||||
|
ServerURL string `env:"GITHUB_SERVER_URL,default=https://github.com"`
|
||||||
|
SHA string `env:"GITHUB_SHA"`
|
||||||
|
StepSummary string `env:"GITHUB_STEP_SUMMARY"`
|
||||||
|
Workflow string `env:"GITHUB_WORKFLOW"`
|
||||||
|
Workspace string `env:"GITHUB_WORKSPACE"`
|
||||||
|
|
||||||
|
// Event is populated by parsing the file at EventPath, if it exists.
|
||||||
|
Event map[string]any
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repo returns the username of the repository owner and repository name.
|
||||||
|
func (c *GitHubContext) Repo() (string, string) {
|
||||||
|
if c == nil {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts
|
||||||
|
if c.Repository != "" {
|
||||||
|
parts := strings.SplitN(c.Repository, "/", 2)
|
||||||
|
if len(parts) == 1 {
|
||||||
|
return parts[0], ""
|
||||||
|
}
|
||||||
|
return parts[0], parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// If c.Repository is empty attempt to get the repo from the Event data.
|
||||||
|
var repoName string
|
||||||
|
// NOTE: differs from context.ts. Fall back to GITHUB_REPOSITORY_OWNER
|
||||||
|
ownerName := c.RepositoryOwner
|
||||||
|
if c.Event != nil {
|
||||||
|
if repo, ok := c.Event["repository"].(map[string]any); ok {
|
||||||
|
if name, ok := repo["name"].(string); ok {
|
||||||
|
repoName = name
|
||||||
|
}
|
||||||
|
if owner, ok := repo["owner"].(map[string]any); ok {
|
||||||
|
if name, ok := owner["name"].(string); ok {
|
||||||
|
ownerName = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ownerName, repoName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context returns the context of current action with the payload object
|
||||||
|
// that triggered the workflow
|
||||||
|
func (c *Action) Context() (*GitHubContext, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
lookuper := &wrappedLookuper{f: c.getenv}
|
||||||
|
|
||||||
|
var githubContext GitHubContext
|
||||||
|
if err := envconfig.ProcessWith(ctx, &githubContext, lookuper); err != nil {
|
||||||
|
return nil, fmt.Errorf("could not process github context variables: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if githubContext.EventPath != "" {
|
||||||
|
eventData, err := os.ReadFile(githubContext.EventPath)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return nil, fmt.Errorf("could not read event file: %w", err)
|
||||||
|
}
|
||||||
|
if eventData != nil {
|
||||||
|
if err := json.Unmarshal(eventData, &githubContext.Event); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal event payload: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &githubContext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrappedLookuper creates a lookuper that wraps a given getenv func.
|
||||||
|
type wrappedLookuper struct {
|
||||||
|
f GetenvFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup implements a custom lookuper.
|
||||||
|
func (w *wrappedLookuper) Lookup(key string) (string, bool) {
|
||||||
|
if v := w.f(key); v != "" {
|
||||||
|
return v, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
156
vendor/github.com/sethvargo/go-githubactions/actions_root.go
generated
vendored
Normal file
156
vendor/github.com/sethvargo/go-githubactions/actions_root.go
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
// Copyright 2020 The Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package githubactions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultAction = New()
|
||||||
|
)
|
||||||
|
|
||||||
|
// IssueCommand issues an arbitrary GitHub actions Command.
|
||||||
|
func IssueCommand(cmd *Command) {
|
||||||
|
defaultAction.IssueCommand(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueFileCommand issues a new GitHub actions Command using environment files.
|
||||||
|
func IssueFileCommand(cmd *Command) {
|
||||||
|
defaultAction.IssueFileCommand(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMask adds a new field mask for the given string "p". After called, future
|
||||||
|
// attempts to log "p" will be replaced with "***" in log output.
|
||||||
|
func AddMask(p string) {
|
||||||
|
defaultAction.AddMask(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMatcher adds a new matcher with the given file path.
|
||||||
|
func AddMatcher(p string) {
|
||||||
|
defaultAction.AddMatcher(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMatcher removes a matcher with the given owner name.
|
||||||
|
func RemoveMatcher(o string) {
|
||||||
|
defaultAction.RemoveMatcher(o)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPath adds the string "p" to the path for the invocation.
|
||||||
|
func AddPath(p string) {
|
||||||
|
defaultAction.AddPath(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveState saves state to be used in the "finally" post job entry point.
|
||||||
|
func SaveState(k, v string) {
|
||||||
|
defaultAction.SaveState(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInput gets the input by the given name.
|
||||||
|
func GetInput(i string) string {
|
||||||
|
return defaultAction.GetInput(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group starts a new collapsable region up to the next ungroup invocation.
|
||||||
|
func Group(t string) {
|
||||||
|
defaultAction.Group(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndGroup ends the current group.
|
||||||
|
func EndGroup() {
|
||||||
|
defaultAction.EndGroup()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStepSummary writes the given markdown to the job summary. If a job summary
|
||||||
|
// already exists, this value is appended.
|
||||||
|
func AddStepSummary(markdown string) {
|
||||||
|
defaultAction.AddStepSummary(markdown)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStepSummaryTemplate adds a summary template by parsing the given Go
|
||||||
|
// template using html/template with the given input data. See AddStepSummary
|
||||||
|
// for caveats.
|
||||||
|
//
|
||||||
|
// This primarily exists as a convenience function that renders a template.
|
||||||
|
func AddStepSummaryTemplate(tmpl string, data any) error {
|
||||||
|
return defaultAction.AddStepSummaryTemplate(tmpl, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEnv sets an environment variable.
|
||||||
|
func SetEnv(k, v string) {
|
||||||
|
defaultAction.SetEnv(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOutput sets an output parameter.
|
||||||
|
func SetOutput(k, v string) {
|
||||||
|
defaultAction.SetOutput(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf prints a debug-level message. The arguments follow the standard Printf
|
||||||
|
// arguments.
|
||||||
|
func Debugf(msg string, args ...any) {
|
||||||
|
defaultAction.Debugf(msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Noticef prints a notice-level message. The arguments follow the standard
|
||||||
|
// Printf arguments.
|
||||||
|
func Noticef(msg string, args ...any) {
|
||||||
|
defaultAction.Noticef(msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf prints a error-level message. The arguments follow the standard Printf
|
||||||
|
// arguments.
|
||||||
|
func Errorf(msg string, args ...any) {
|
||||||
|
defaultAction.Errorf(msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf prints a error-level message and exits. This is equivalent to Errorf
|
||||||
|
// followed by os.Exit(1).
|
||||||
|
func Fatalf(msg string, args ...any) {
|
||||||
|
defaultAction.Fatalf(msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof prints a info-level message. The arguments follow the standard Printf
|
||||||
|
// arguments.
|
||||||
|
func Infof(msg string, args ...any) {
|
||||||
|
defaultAction.Infof(msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warningf prints a warning-level message. The arguments follow the standard
|
||||||
|
// Printf arguments.
|
||||||
|
func Warningf(msg string, args ...any) {
|
||||||
|
defaultAction.Warningf(msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFieldsSlice includes the provided fields in log output. "f" must be a
|
||||||
|
// slice of k=v pairs. The given slice will be sorted.
|
||||||
|
func WithFieldsSlice(f []string) *Action {
|
||||||
|
return defaultAction.WithFieldsSlice(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFieldsMap includes the provided fields in log output. The fields in "m"
|
||||||
|
// are automatically converted to k=v pairs and sorted.
|
||||||
|
func WithFieldsMap(m map[string]string) *Action {
|
||||||
|
return defaultAction.WithFieldsMap(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIDToken returns the GitHub OIDC token from the GitHub Actions runtime.
|
||||||
|
func GetIDToken(ctx context.Context, audience string) (string, error) {
|
||||||
|
return defaultAction.GetIDToken(ctx, audience)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Context() (*GitHubContext, error) {
|
||||||
|
return defaultAction.Context()
|
||||||
|
}
|
112
vendor/github.com/sethvargo/go-githubactions/command.go
generated
vendored
Normal file
112
vendor/github.com/sethvargo/go-githubactions/command.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// Copyright 2020 The Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package githubactions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cmdSeparator = "::"
|
||||||
|
cmdPropertiesPrefix = " "
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommandProperties is a named "map[string]string" type to hold key-value pairs
|
||||||
|
// passed to an actions command.
|
||||||
|
type CommandProperties map[string]string
|
||||||
|
|
||||||
|
// String encodes the CommandProperties to a string as comma separated
|
||||||
|
// 'key=value' pairs. The pairs are joined in a chronological order.
|
||||||
|
func (props *CommandProperties) String() string {
|
||||||
|
l := make([]string, 0, len(*props))
|
||||||
|
for k, v := range *props {
|
||||||
|
l = append(l, fmt.Sprintf("%s=%s", k, escapeProperty(v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(l)
|
||||||
|
return strings.Join(l, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command can be issued by a GitHub action by writing to `stdout` with
|
||||||
|
// following format.
|
||||||
|
//
|
||||||
|
// ::name key=value,key=value::message
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// ::warning::This is the message
|
||||||
|
// ::set-env name=MY_VAR::some value
|
||||||
|
type Command struct {
|
||||||
|
Name string
|
||||||
|
Message string
|
||||||
|
Properties CommandProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// String encodes the Command to a string in the following format:
|
||||||
|
//
|
||||||
|
// ::name key=value,key=value::message
|
||||||
|
func (cmd *Command) String() string {
|
||||||
|
// https://github.com/actions/toolkit/blob/9ad01e4fd30025e8858650d38e95cfe9193a3222/packages/core/src/command.ts#L43-L45
|
||||||
|
if cmd.Name == "" {
|
||||||
|
cmd.Name = "missing.command"
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder strings.Builder
|
||||||
|
builder.WriteString(cmdSeparator)
|
||||||
|
builder.WriteString(cmd.Name)
|
||||||
|
if len(cmd.Properties) > 0 {
|
||||||
|
builder.WriteString(cmdPropertiesPrefix)
|
||||||
|
builder.WriteString(cmd.Properties.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteString(cmdSeparator)
|
||||||
|
builder.WriteString(escapeData(cmd.Message))
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// escapeData escapes string values for presentation in the output of a command.
|
||||||
|
// This is a not-so-well-documented requirement of commands that define a
|
||||||
|
// message:
|
||||||
|
//
|
||||||
|
// https://github.com/actions/toolkit/blob/9ad01e4fd30025e8858650d38e95cfe9193a3222/packages/core/src/command.ts#L74
|
||||||
|
//
|
||||||
|
// The equivalent toolkit function can be found here:
|
||||||
|
//
|
||||||
|
// https://github.com/actions/toolkit/blob/9ad01e4fd30025e8858650d38e95cfe9193a3222/packages/core/src/command.ts#L92
|
||||||
|
//
|
||||||
|
func escapeData(v string) string {
|
||||||
|
v = strings.ReplaceAll(v, "%", "%25")
|
||||||
|
v = strings.ReplaceAll(v, "\r", "%0D")
|
||||||
|
v = strings.ReplaceAll(v, "\n", "%0A")
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// escapeData escapes command property values for presentation in the output of
|
||||||
|
// a command.
|
||||||
|
//
|
||||||
|
// https://github.com/actions/toolkit/blob/9ad01e4fd30025e8858650d38e95cfe9193a3222/packages/core/src/command.ts#L68
|
||||||
|
//
|
||||||
|
// The equivalent toolkit function can be found here:
|
||||||
|
//
|
||||||
|
// https://github.com/actions/toolkit/blob/1cc56db0ff126f4d65aeb83798852e02a2c180c3/packages/core/src/command.ts#L99-L106
|
||||||
|
func escapeProperty(v string) string {
|
||||||
|
v = strings.ReplaceAll(v, "%", "%25")
|
||||||
|
v = strings.ReplaceAll(v, "\r", "%0D")
|
||||||
|
v = strings.ReplaceAll(v, "\n", "%0A")
|
||||||
|
v = strings.ReplaceAll(v, ":", "%3A")
|
||||||
|
v = strings.ReplaceAll(v, ",", "%2C")
|
||||||
|
return v
|
||||||
|
}
|
20
vendor/github.com/sethvargo/go-githubactions/eof_crlf.go
generated
vendored
Normal file
20
vendor/github.com/sethvargo/go-githubactions/eof_crlf.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2021 The Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package githubactions
|
||||||
|
|
||||||
|
const EOF = "\r\n"
|
20
vendor/github.com/sethvargo/go-githubactions/eof_lf.go
generated
vendored
Normal file
20
vendor/github.com/sethvargo/go-githubactions/eof_lf.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2021 The Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package githubactions
|
||||||
|
|
||||||
|
const EOF = "\n"
|
59
vendor/github.com/sethvargo/go-githubactions/options.go
generated
vendored
Normal file
59
vendor/github.com/sethvargo/go-githubactions/options.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2021 The Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package githubactions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option is a modifier for an Action.
|
||||||
|
type Option func(*Action) *Action
|
||||||
|
|
||||||
|
// WithWriter sets the writer function on an Action. By default, this will
|
||||||
|
// be `os.Stdout` from the standard library.
|
||||||
|
func WithWriter(w io.Writer) Option {
|
||||||
|
return func(a *Action) *Action {
|
||||||
|
a.w = w
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFields sets the extra command field on an Action.
|
||||||
|
func WithFields(fields CommandProperties) Option {
|
||||||
|
return func(a *Action) *Action {
|
||||||
|
a.fields = fields
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithGetenv sets the `Getenv` function on an Action. By default, this will
|
||||||
|
// be `os.Getenv` from the standard library.
|
||||||
|
func WithGetenv(getenv GetenvFunc) Option {
|
||||||
|
return func(a *Action) *Action {
|
||||||
|
a.getenv = getenv
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithHTTPClient sets a custom HTTP client on the action. This is only used
|
||||||
|
// when the action makes output HTTP requests (such as generating an OIDC
|
||||||
|
// token).
|
||||||
|
func WithHTTPClient(c *http.Client) Option {
|
||||||
|
return func(a *Action) *Action {
|
||||||
|
a.httpClient = c
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
12
vendor/modules.txt
vendored
Normal file
12
vendor/modules.txt
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# code.gitea.io/sdk/gitea v0.15.1
|
||||||
|
## explicit; go 1.13
|
||||||
|
code.gitea.io/sdk/gitea
|
||||||
|
# github.com/hashicorp/go-version v1.2.1
|
||||||
|
## explicit
|
||||||
|
github.com/hashicorp/go-version
|
||||||
|
# github.com/sethvargo/go-envconfig v0.8.0
|
||||||
|
## explicit; go 1.17
|
||||||
|
github.com/sethvargo/go-envconfig
|
||||||
|
# github.com/sethvargo/go-githubactions v1.1.0
|
||||||
|
## explicit; go 1.18
|
||||||
|
github.com/sethvargo/go-githubactions
|
Loading…
Reference in New Issue
Block a user