API clients to Gitea and Github #1

Merged
Sirherobrine23 merged 1 commits from github_gitea into main 2025-04-03 01:32:22 +00:00
69 changed files with 4805 additions and 7 deletions

69
gitea/apipaginator.go Normal file
View File

@ -0,0 +1,69 @@
package gitea
import (
"net/http"
"net/url"
"strconv"
"strings"
)
type githubPagination struct {
NextPage, PrevPage, FirstPage, LastPage int
NextPageToken, Cursor, Before, After string
}
func parsePaginator(he http.Header) *githubPagination {
r := &githubPagination{}
if links, ok := he["Link"]; ok && len(links) > 0 {
for link := range strings.SplitSeq(links[0], ",") {
segments := strings.Split(strings.TrimSpace(link), ";")
if len(segments) < 2 {
continue
}
if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") {
continue
}
url, err := url.Parse(segments[0][1 : len(segments[0])-1])
if err != nil {
continue
}
q := url.Query()
if cursor := q.Get("cursor"); cursor != "" {
for _, segment := range segments[1:] {
switch strings.TrimSpace(segment) {
case `rel="next"`:
r.Cursor = cursor
}
}
continue
}
page := q.Get("page")
since := q.Get("since")
before := q.Get("before")
after := q.Get("after")
if page == "" && before == "" && after == "" && since == "" {
continue
}
if since != "" && page == "" {
page = since
}
for _, segment := range segments[1:] {
switch strings.TrimSpace(segment) {
case `rel="next"`:
if r.NextPage, err = strconv.Atoi(page); err != nil {
r.NextPageToken = page
}
r.After = after
case `rel="prev"`:
r.PrevPage, _ = strconv.Atoi(page)
r.Before = before
case `rel="first"`:
r.FirstPage, _ = strconv.Atoi(page)
case `rel="last"`:
r.LastPage, _ = strconv.Atoi(page)
}
}
}
}
return r
}

126
gitea/gitea.go Normal file
View File

@ -0,0 +1,126 @@
// Client to Gitea API
package gitea
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"path"
"strconv"
"strings"
"time"
"sirherobrine23.com.br/go-bds/request/v2"
)
var (
ErrToken error = errors.New("require Token to request")
ErrBackend error = errors.New("catch 500 error in server api")
ErrNoExist error = errors.New("repository, organization or endpoint dont exists")
processCodes = request.MapCode{
500: errRes5xx("500 error"),
501: errRes5xx("501 error"),
401: func(res *http.Response) (*http.Response, error) {
if res.Body != nil {
res.Body.Close()
}
return nil, ErrToken
},
403: func(res *http.Response) (*http.Response, error) {
if res.Body != nil {
res.Body.Close()
}
return nil, errors.New("cannot process request, authorization or not have permission")
},
429: func(res *http.Response) (*http.Response, error) {
if res.Body != nil {
res.Body.Close()
}
// x-ratelimit-reset
if window, err := strconv.Atoi(res.Header.Get("x-ratelimit-reset")); err == nil {
<-time.After(time.Duration(window))
} else {
<-time.After(time.Second)
}
return request.ReRequest(res)
},
}
)
type giteaError struct {
Errors []string `json:"errors"`
TeaError string `json:"error"`
Message string `json:"message"`
Url string `json:"url"`
}
func errRes5xx(txt string) func(res *http.Response) (*http.Response, error) {
return func(res *http.Response) (*http.Response, error) {
if strings.Contains(res.Header.Get("Content-Type"), "application/json") {
var data giteaError
defer res.Body.Close()
bodyBuff, err := io.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf(txt, ErrBackend, err)
}
if err := json.Unmarshal(bodyBuff, &data); err != nil {
return nil, fmt.Errorf(txt, ErrBackend, ErrNoExist)
} else if len(data.Errors) > 0 {
return nil, fmt.Errorf(txt, ErrBackend, fmt.Errorf("gitea api, errors: %s, %s", data.Message, strings.Join(data.Errors, ", ")))
} else if data.Message != "" {
return nil, fmt.Errorf(txt, ErrBackend, fmt.Errorf("backed error: %s", data.Message))
}
}
return nil, fmt.Errorf(txt, ErrBackend)
}
}
// Make new gitea client to Make API requests, host example: "https://gitea.com/api"
func NewClient(giteaHost, Owner, Repository, Token string) (*Gitea, error) {
apiUrl, err := url.Parse(giteaHost)
if err != nil {
return nil, err
}
client := &Gitea{
Host: apiUrl,
Username: Owner,
Repository: Repository,
Token: Token,
}
// Check if API is OK
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, err := request.MakeRequestWithStatus(apiUrl.ResolveReference(&url.URL{Path: path.Join(apiUrl.Path, "v1/version")}), reqOptions)
if err != nil {
return nil, fmt.Errorf("cannot get gitea version: %s", err)
}
res.Body.Close()
return client, nil
}
// Gitea client
type Gitea struct {
Host *url.URL // Gitea api host
Username, Repository string // Repository and owner names
Token string // Gitea token
}
// Return escapated Owner+/+Repository
func (client Gitea) repoPath() string {
return fmt.Sprintf("%s/%s", url.PathEscape(client.Username), url.PathEscape(client.Repository))
}
// Set token to header
func (client Gitea) authHeader(header *request.Header) {
if client.Token != "" {
(*header)["Authorization"] = fmt.Sprintf("token %s", client.Token)
}
}

160
gitea/releases.go Normal file
View File

@ -0,0 +1,160 @@
package gitea
import (
"fmt"
"io"
"iter"
"mime/multipart"
"net/http"
"net/url"
"path"
"strconv"
gitea_api "sirherobrine23.com.br/go-bds/request/gitea/structs"
"sirherobrine23.com.br/go-bds/request/v2"
)
// Get release by tag name
func (client Gitea) ReleaseTag(tagName string) (*gitea_api.Release, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*gitea_api.Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases/tags", url.PathEscape(tagName))}).String(), reqOptions)
return res, err
}
// Get release by ID
func (client Gitea) Release(id int) (*gitea_api.Release, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*gitea_api.Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(id))}).String(), reqOptions)
return res, err
}
// List all release from gitea APIs
func (client Gitea) ReleasesSeq() iter.Seq2[*gitea_api.Release, error] {
releases, res, err := []*gitea_api.Release{}, (*http.Response)(nil), error(nil)
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
return func(yield func(*gitea_api.Release, error) bool) {
requestUrl := client.Host.ResolveReference(&url.URL{RawQuery: "limit=100", Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases")}).String()
for requestUrl != "" {
if len(releases) == 0 {
if releases, res, err = request.JSON[[]*gitea_api.Release](requestUrl, reqOptions); res != nil {
requestUrl = parsePaginator(res.Header).NextPageToken
} else {
requestUrl = ""
}
}
if err != nil {
yield(nil, err)
return
}
for len(releases) > 0 {
if !yield(releases[0], nil) {
return
}
releases = releases[1:]
}
}
}
}
// List all release Assets in [iter.Seq2]
func (client Gitea) AssetsSeq(releaseID int) iter.Seq2[*gitea_api.Attachment, error] {
asserts, res, err := []*gitea_api.Attachment{}, (*http.Response)(nil), error(nil)
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
return func(yield func(*gitea_api.Attachment, error) bool) {
requestUrl := client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}).String()
for requestUrl != "" {
if len(asserts) == 0 {
if asserts, res, err = request.JSON[[]*gitea_api.Attachment](requestUrl, reqOptions); res != nil {
requestUrl = parsePaginator(res.Header).NextPageToken
} else {
requestUrl = ""
}
}
if err != nil {
yield(nil, err)
return
}
for len(asserts) > 0 {
if !yield(asserts[0], nil) {
return
}
asserts = asserts[1:]
}
}
}
}
// Get all releases from Gitea APIs and return slice with all versions
func (client Gitea) Releases() ([]*gitea_api.Release, error) {
releases := []*gitea_api.Release{}
for release, err := range client.ReleasesSeq() {
if err != nil {
return nil, err
}
releases = append(releases, release)
}
return releases, nil
}
// List all release Assets in to slice
func (client Gitea) AllAssets(releaseID int) ([]*gitea_api.Attachment, error) {
asserts := []*gitea_api.Attachment{}
for assert, err := range client.AssetsSeq(releaseID) {
if err != nil {
return nil, err
}
asserts = append(asserts, assert)
}
return asserts, nil
}
// Delete assert file from Release
func (client Gitea) DeleteAsset(releaseID, assetID int) error {
reqOptions := &request.Options{Method: "DELETE", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, err := request.MakeRequestWithStatus(client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets", strconv.Itoa(assetID))}), reqOptions)
res.Body.Close()
return err
}
// Upload file to Release
func (client Gitea) UploadAsset(releaseID int, name string, file io.Reader) (fileInfo *gitea_api.Attachment, err error) {
defer func(err *error) {
if err2 := recover(); err2 != nil {
*err = fmt.Errorf("%s", err2)
}
}(&err)
r, w := io.Pipe()
mw := multipart.NewWriter(w)
go func(mw *multipart.Writer) {
part, err := mw.CreateFormFile("attachment", name)
if err != nil {
panic(err)
} else if _, err = io.Copy(part, file); err != nil {
panic(err)
} else if err = mw.Close(); err != nil {
panic(err)
}
}(mw)
reqOptions := &request.Options{
Method: "POST",
Body: r,
Header: request.Header{
"Content-Type": mw.FormDataContentType(),
},
CodeProcess: processCodes.Extends(request.MapCode{
201: func(res *http.Response) (*http.Response, error) { return res, nil },
422: func(res *http.Response) (*http.Response, error) {
return nil, fmt.Errorf("same filename exists in release: %s", name)
},
}),
}
client.authHeader(&reqOptions.Header)
_, err = request.DoJSON(client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}).String(), fileInfo, reqOptions)
return
}

25
gitea/structs/activity.go Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import "time"
type Activity struct {
ID int `json:"id"`
UserID int `json:"user_id"` // Receiver user
// the type of action
//
// enum: create_repo,rename_repo,star_repo,watch_repo,commit_repo,create_issue,create_pull_request,transfer_repo,push_tag,comment_issue,merge_pull_request,close_issue,reopen_issue,close_pull_request,reopen_pull_request,delete_tag,delete_branch,mirror_sync_push,mirror_sync_create,mirror_sync_delete,approve_pull_request,reject_pull_request,comment_pull,publish_release,pull_review_dismissed,pull_request_ready_for_review,auto_merge_pull_request
OpType string `json:"op_type"`
ActUserID int `json:"act_user_id"`
ActUser *User `json:"act_user"`
RepoID int `json:"repo_id"`
Repo *Repository `json:"repo"`
CommentID int `json:"comment_id"`
Comment *Comment `json:"comment"`
RefName string `json:"ref_name"`
IsPrivate bool `json:"is_private"`
Content string `json:"content"`
Created time.Time `json:"created"`
}

View File

@ -0,0 +1,9 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// ActivityPub type
type ActivityPub struct {
Context string `json:"@context"`
}

View File

@ -0,0 +1,50 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import "time"
// CreateUserOption create user options
type CreateUserOption struct {
SourceID int `json:"source_id"`
LoginName string `json:"login_name"`
// required: true
Username string `json:"username" binding:"Required;Username;MaxSize(40)"`
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
Password string `json:"password" binding:"MaxSize(255)"`
MustChangePassword *bool `json:"must_change_password"`
SendNotify bool `json:"send_notify"`
Restricted *bool `json:"restricted"`
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
// For explicitly setting the user creation timestamp. Useful when users are
// migrated from other systems. When omitted, the user's creation timestamp
// will be set to "now".
Created *time.Time `json:"created_at"`
}
// EditUserOption edit user options
type EditUserOption struct {
// required: true
SourceID int `json:"source_id"`
LoginName string `json:"login_name" binding:"Required"`
Email *string `json:"email" binding:"MaxSize(254)"`
FullName *string `json:"full_name" binding:"MaxSize(100)"`
Password string `json:"password" binding:"MaxSize(255)"`
MustChangePassword *bool `json:"must_change_password"`
Website *string `json:"website" binding:"OmitEmpty;ValidUrl;MaxSize(255)"`
Location *string `json:"location" binding:"MaxSize(50)"`
Description *string `json:"description" binding:"MaxSize(255)"`
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 string `json:"visibility" binding:"In(,public,limited,private)"`
}

View File

@ -0,0 +1,23 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs // import "code.gitea.io/gitea/modules/structs"
import (
"time"
)
// Attachment a generic attachment
type Attachment struct {
ID int `json:"id"`
Name string `json:"name"`
Size int `json:"size"`
DownloadCount int `json:"download_count"`
Created time.Time `json:"created_at"`
UUID string `json:"uuid"`
DownloadURL string `json:"browser_download_url"`
}
type EditAttachmentOptions struct {
Name string `json:"name"`
}

View File

@ -0,0 +1,73 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// CommitStatusState holds the state of a CommitStatus
// It can be "pending", "success", "error" and "failure"
type CommitStatusState string
const (
// CommitStatusPending is for when the CommitStatus is Pending
CommitStatusPending CommitStatusState = "pending"
// CommitStatusSuccess is for when the CommitStatus is Success
CommitStatusSuccess CommitStatusState = "success"
// CommitStatusError is for when the CommitStatus is Error
CommitStatusError CommitStatusState = "error"
// CommitStatusFailure is for when the CommitStatus is Failure
CommitStatusFailure CommitStatusState = "failure"
// CommitStatusWarning is for when the CommitStatus is Warning
CommitStatusWarning CommitStatusState = "warning"
)
var commitStatusPriorities = map[CommitStatusState]int{
CommitStatusError: 0,
CommitStatusFailure: 1,
CommitStatusWarning: 2,
CommitStatusPending: 3,
CommitStatusSuccess: 4,
}
func (css CommitStatusState) String() string {
return string(css)
}
// NoBetterThan returns true if this State is no better than the given State
// This function only handles the states defined in CommitStatusPriorities
func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool {
// NoBetterThan only handles the 5 states above
if _, exist := commitStatusPriorities[css]; !exist {
return false
}
if _, exist := commitStatusPriorities[css2]; !exist {
return false
}
return commitStatusPriorities[css] <= commitStatusPriorities[css2]
}
// IsPending represents if commit status state is pending
func (css CommitStatusState) IsPending() bool {
return css == CommitStatusPending
}
// IsSuccess represents if commit status state is success
func (css CommitStatusState) IsSuccess() bool {
return css == CommitStatusSuccess
}
// IsError represents if commit status state is error
func (css CommitStatusState) IsError() bool {
return css == CommitStatusError
}
// IsFailure represents if commit status state is failure
func (css CommitStatusState) IsFailure() bool {
return css == CommitStatusFailure
}
// IsWarning represents if commit status state is warning
func (css CommitStatusState) IsWarning() bool {
return css == CommitStatusWarning
}

View File

@ -0,0 +1,174 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNoBetterThan(t *testing.T) {
type args struct {
css CommitStatusState
css2 CommitStatusState
}
var unExpectedState CommitStatusState
tests := []struct {
name string
args args
want bool
}{
{
name: "success is no better than success",
args: args{
css: CommitStatusSuccess,
css2: CommitStatusSuccess,
},
want: true,
},
{
name: "success is no better than pending",
args: args{
css: CommitStatusSuccess,
css2: CommitStatusPending,
},
want: false,
},
{
name: "success is no better than failure",
args: args{
css: CommitStatusSuccess,
css2: CommitStatusFailure,
},
want: false,
},
{
name: "success is no better than error",
args: args{
css: CommitStatusSuccess,
css2: CommitStatusError,
},
want: false,
},
{
name: "pending is no better than success",
args: args{
css: CommitStatusPending,
css2: CommitStatusSuccess,
},
want: true,
},
{
name: "pending is no better than pending",
args: args{
css: CommitStatusPending,
css2: CommitStatusPending,
},
want: true,
},
{
name: "pending is no better than failure",
args: args{
css: CommitStatusPending,
css2: CommitStatusFailure,
},
want: false,
},
{
name: "pending is no better than error",
args: args{
css: CommitStatusPending,
css2: CommitStatusError,
},
want: false,
},
{
name: "failure is no better than success",
args: args{
css: CommitStatusFailure,
css2: CommitStatusSuccess,
},
want: true,
},
{
name: "failure is no better than pending",
args: args{
css: CommitStatusFailure,
css2: CommitStatusPending,
},
want: true,
},
{
name: "failure is no better than failure",
args: args{
css: CommitStatusFailure,
css2: CommitStatusFailure,
},
want: true,
},
{
name: "failure is no better than error",
args: args{
css: CommitStatusFailure,
css2: CommitStatusError,
},
want: false,
},
{
name: "error is no better than success",
args: args{
css: CommitStatusError,
css2: CommitStatusSuccess,
},
want: true,
},
{
name: "error is no better than pending",
args: args{
css: CommitStatusError,
css2: CommitStatusPending,
},
want: true,
},
{
name: "error is no better than failure",
args: args{
css: CommitStatusError,
css2: CommitStatusFailure,
},
want: true,
},
{
name: "error is no better than error",
args: args{
css: CommitStatusError,
css2: CommitStatusError,
},
want: true,
},
{
name: "unExpectedState is no better than success",
args: args{
css: unExpectedState,
css2: CommitStatusSuccess,
},
want: false,
},
{
name: "unExpectedState is no better than unExpectedState",
args: args{
css: unExpectedState,
css2: unExpectedState,
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.args.css.NoBetterThan(tt.args.css2)
assert.Equal(t, tt.want, result)
})
}
}

15
gitea/structs/cron.go Normal file
View File

@ -0,0 +1,15 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import "time"
// Cron represents a Cron task
type Cron struct {
Name string `json:"name"`
Schedule string `json:"schedule"`
Next time.Time `json:"next"`
Prev time.Time `json:"prev"`
ExecTimes int `json:"exec_times"`
}

4
gitea/structs/doc.go Normal file
View File

@ -0,0 +1,4 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs

12
gitea/structs/fork.go Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// CreateForkOption options for creating a fork
type CreateForkOption struct {
// organization name, if forking into an organization
Organization *string `json:"organization"`
// name of the forked repository
Name *string `json:"name"`
}

13
gitea/structs/git_blob.go Normal file
View File

@ -0,0 +1,13 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// 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 int `json:"size"`
}

19
gitea/structs/git_hook.go Normal file
View File

@ -0,0 +1,19 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// GitHook represents a Git repository hook
type GitHook struct {
Name string `json:"name"`
IsActive bool `json:"is_active"`
Content string `json:"content,omitempty"`
}
// GitHookList represents a list of Git hooks
type GitHookList []*GitHook
// EditGitHookOption options when modifying one Git hook
type EditGitHookOption struct {
Content string `json:"content"`
}

480
gitea/structs/hook.go Normal file
View File

@ -0,0 +1,480 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"errors"
"strings"
"time"
"code.gitea.io/gitea/modules/json"
)
// ErrInvalidReceiveHook FIXME
var ErrInvalidReceiveHook = errors.New("Invalid JSON payload received over webhook")
// Hook a hook is a web hook when one repository changed
type Hook struct {
ID int `json:"id"`
Type string `json:"type"`
BranchFilter string `json:"branch_filter"`
URL string `json:"-"`
Config map[string]string `json:"config"`
Events []string `json:"events"`
AuthorizationHeader string `json:"authorization_header"`
Active bool `json:"active"`
Updated time.Time `json:"updated_at"`
Created time.Time `json:"created_at"`
}
// HookList represents a list of API hook.
type HookList []*Hook
// CreateHookOptionConfig has all config options in it
// required are "content_type" and "url" Required
type CreateHookOptionConfig map[string]string
// CreateHookOption options when create a hook
type CreateHookOption struct {
// required: true
// enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
Type string `json:"type" binding:"Required"`
// required: true
Config CreateHookOptionConfig `json:"config" binding:"Required"`
Events []string `json:"events"`
BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
AuthorizationHeader string `json:"authorization_header"`
// default: false
Active bool `json:"active"`
}
// EditHookOption options when modify one hook
type EditHookOption struct {
Config map[string]string `json:"config"`
Events []string `json:"events"`
BranchFilter string `json:"branch_filter" binding:"GlobPattern"`
AuthorizationHeader string `json:"authorization_header"`
Active *bool `json:"active"`
}
// Payloader payload is some part of one hook
type Payloader interface {
JSONPayload() ([]byte, error)
}
// 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"`
}
// FIXME: consider using same format as API when commits API are added.
// applies to PayloadCommit and PayloadCommitVerification
// 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"`
Signer *PayloadUser `json:"signer"`
Payload string `json:"payload"`
}
var (
_ Payloader = &CreatePayload{}
_ Payloader = &DeletePayload{}
_ Payloader = &ForkPayload{}
_ Payloader = &PushPayload{}
_ Payloader = &IssuePayload{}
_ Payloader = &IssueCommentPayload{}
_ Payloader = &PullRequestPayload{}
_ Payloader = &RepositoryPayload{}
_ Payloader = &ReleasePayload{}
_ Payloader = &PackagePayload{}
)
// CreatePayload represents a payload information of create event.
type CreatePayload struct {
Sha string `json:"sha"`
Ref string `json:"ref"`
RefType string `json:"ref_type"`
Repo *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload return payload information
func (p *CreatePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ParseCreateHook parses create event hook content.
func ParseCreateHook(raw []byte) (*CreatePayload, error) {
hook := new(CreatePayload)
if err := json.Unmarshal(raw, hook); err != nil {
return nil, err
}
// it is possible the JSON was parsed, however,
// was not from Gogs (maybe was from Bitbucket)
// So we'll check to be sure certain key fields
// were populated
switch {
case hook.Repo == nil:
return nil, ErrInvalidReceiveHook
case len(hook.Ref) == 0:
return nil, ErrInvalidReceiveHook
}
return hook, nil
}
// PusherType define the type to push
type PusherType string
// describe all the PusherTypes
const (
PusherTypeUser PusherType = "user"
)
// DeletePayload represents delete payload
type DeletePayload struct {
Ref string `json:"ref"`
RefType string `json:"ref_type"`
PusherType PusherType `json:"pusher_type"`
Repo *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *DeletePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ForkPayload represents fork payload
type ForkPayload struct {
Forkee *Repository `json:"forkee"`
Repo *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *ForkPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// HookIssueCommentAction defines hook issue comment action
type HookIssueCommentAction string
// all issue comment actions
const (
HookIssueCommentCreated HookIssueCommentAction = "created"
HookIssueCommentEdited HookIssueCommentAction = "edited"
HookIssueCommentDeleted HookIssueCommentAction = "deleted"
)
// IssueCommentPayload represents a payload information of issue comment event.
type IssueCommentPayload struct {
Action HookIssueCommentAction `json:"action"`
Issue *Issue `json:"issue"`
PullRequest *PullRequest `json:"pull_request,omitempty"`
Comment *Comment `json:"comment"`
Changes *ChangesPayload `json:"changes,omitempty"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
IsPull bool `json:"is_pull"`
}
// JSONPayload implements Payload
func (p *IssueCommentPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// HookReleaseAction defines hook release action type
type HookReleaseAction string
// all release actions
const (
HookReleasePublished HookReleaseAction = "published"
HookReleaseUpdated HookReleaseAction = "updated"
HookReleaseDeleted HookReleaseAction = "deleted"
)
// ReleasePayload represents a payload information of release event.
type ReleasePayload struct {
Action HookReleaseAction `json:"action"`
Release *Release `json:"release"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *ReleasePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// PushPayload represents a payload information of push event.
type PushPayload struct {
Ref string `json:"ref"`
Before string `json:"before"`
After string `json:"after"`
CompareURL string `json:"compare_url"`
Commits []*PayloadCommit `json:"commits"`
TotalCommits int `json:"total_commits"`
HeadCommit *PayloadCommit `json:"head_commit"`
Repo *Repository `json:"repository"`
Pusher *User `json:"pusher"`
Sender *User `json:"sender"`
}
// JSONPayload FIXME
func (p *PushPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ParsePushHook parses push event hook content.
func ParsePushHook(raw []byte) (*PushPayload, error) {
hook := new(PushPayload)
if err := json.Unmarshal(raw, hook); err != nil {
return nil, err
}
switch {
case hook.Repo == nil:
return nil, ErrInvalidReceiveHook
case len(hook.Ref) == 0:
return nil, ErrInvalidReceiveHook
}
return hook, nil
}
// Branch returns branch name from a payload
func (p *PushPayload) Branch() string {
return strings.ReplaceAll(p.Ref, "refs/heads/", "")
}
// HookIssueAction FIXME
type HookIssueAction string
const (
// HookIssueOpened opened
HookIssueOpened HookIssueAction = "opened"
// HookIssueClosed closed
HookIssueClosed HookIssueAction = "closed"
// HookIssueReOpened reopened
HookIssueReOpened HookIssueAction = "reopened"
// HookIssueEdited edited
HookIssueEdited HookIssueAction = "edited"
// HookIssueAssigned assigned
HookIssueAssigned HookIssueAction = "assigned"
// HookIssueUnassigned unassigned
HookIssueUnassigned HookIssueAction = "unassigned"
// HookIssueLabelUpdated label_updated
HookIssueLabelUpdated HookIssueAction = "label_updated"
// HookIssueLabelCleared label_cleared
HookIssueLabelCleared HookIssueAction = "label_cleared"
// HookIssueSynchronized synchronized
HookIssueSynchronized HookIssueAction = "synchronized"
// HookIssueMilestoned is an issue action for when a milestone is set on an issue.
HookIssueMilestoned HookIssueAction = "milestoned"
// HookIssueDemilestoned is an issue action for when a milestone is cleared on an issue.
HookIssueDemilestoned HookIssueAction = "demilestoned"
// HookIssueReviewed is an issue action for when a pull request is reviewed
HookIssueReviewed HookIssueAction = "reviewed"
// HookIssueReviewRequested is an issue action for when a reviewer is requested for a pull request.
HookIssueReviewRequested HookIssueAction = "review_requested"
// HookIssueReviewRequestRemoved is an issue action for removing a review request to someone on a pull request.
HookIssueReviewRequestRemoved HookIssueAction = "review_request_removed"
)
// IssuePayload represents the payload information that is sent along with an issue event.
type IssuePayload struct {
Action HookIssueAction `json:"action"`
Index int `json:"number"`
Changes *ChangesPayload `json:"changes,omitempty"`
Issue *Issue `json:"issue"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
CommitID string `json:"commit_id"`
}
// JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces.
func (p *IssuePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ChangesFromPayload FIXME
type ChangesFromPayload struct {
From string `json:"from"`
}
// ChangesPayload represents the payload information of issue change
type ChangesPayload struct {
Title *ChangesFromPayload `json:"title,omitempty"`
Body *ChangesFromPayload `json:"body,omitempty"`
Ref *ChangesFromPayload `json:"ref,omitempty"`
}
// PullRequestPayload represents a payload information of pull request event.
type PullRequestPayload struct {
Action HookIssueAction `json:"action"`
Index int `json:"number"`
Changes *ChangesPayload `json:"changes,omitempty"`
PullRequest *PullRequest `json:"pull_request"`
RequestedReviewer *User `json:"requested_reviewer"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
CommitID string `json:"commit_id"`
Review *ReviewPayload `json:"review"`
}
// JSONPayload FIXME
func (p *PullRequestPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// ReviewPayload FIXME
type ReviewPayload struct {
Type string `json:"type"`
Content string `json:"content"`
}
// HookWikiAction an action that happens to a wiki page
type HookWikiAction string
const (
// HookWikiCreated created
HookWikiCreated HookWikiAction = "created"
// HookWikiEdited edited
HookWikiEdited HookWikiAction = "edited"
// HookWikiDeleted deleted
HookWikiDeleted HookWikiAction = "deleted"
)
// WikiPayload payload for repository webhooks
type WikiPayload struct {
Action HookWikiAction `json:"action"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
Page string `json:"page"`
Comment string `json:"comment"`
}
// JSONPayload JSON representation of the payload
func (p *WikiPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// HookRepoAction an action that happens to a repo
type HookRepoAction string
const (
// HookRepoCreated created
HookRepoCreated HookRepoAction = "created"
// HookRepoDeleted deleted
HookRepoDeleted HookRepoAction = "deleted"
)
// RepositoryPayload payload for repository webhooks
type RepositoryPayload struct {
Action HookRepoAction `json:"action"`
Repository *Repository `json:"repository"`
Organization *User `json:"organization"`
Sender *User `json:"sender"`
}
// JSONPayload JSON representation of the payload
func (p *RepositoryPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// HookPackageAction an action that happens to a package
type HookPackageAction string
const (
// HookPackageCreated created
HookPackageCreated HookPackageAction = "created"
// HookPackageDeleted deleted
HookPackageDeleted HookPackageAction = "deleted"
)
// PackagePayload represents a package payload
type PackagePayload struct {
Action HookPackageAction `json:"action"`
Repository *Repository `json:"repository"`
Package *Package `json:"package"`
Organization *Organization `json:"organization"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *PackagePayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// WorkflowDispatchPayload represents a workflow dispatch payload
type WorkflowDispatchPayload struct {
Workflow string `json:"workflow"`
Ref string `json:"ref"`
Inputs map[string]any `json:"inputs"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *WorkflowDispatchPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// CommitStatusPayload represents a payload information of commit status event.
type CommitStatusPayload struct {
// TODO: add Branches per https://docs.github.com/en/webhooks/webhook-events-and-payloads#status
Commit *PayloadCommit `json:"commit"`
Context string `json:"context"`
CreatedAt time.Time `json:"created_at"`
Description string `json:"description"`
ID int `json:"id"`
Repo *Repository `json:"repository"`
Sender *User `json:"sender"`
SHA string `json:"sha"`
State string `json:"state"`
TargetURL string `json:"target_url"`
UpdatedAt *time.Time `json:"updated_at"`
}
// JSONPayload implements Payload
func (p *CommitStatusPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}
// WorkflowJobPayload represents a payload information of workflow job event.
type WorkflowJobPayload struct {
Action string `json:"action"`
WorkflowJob *ActionWorkflowJob `json:"workflow_job"`
PullRequest *PullRequest `json:"pull_request,omitempty"`
Organization *Organization `json:"organization,omitempty"`
Repo *Repository `json:"repository"`
Sender *User `json:"sender"`
}
// JSONPayload implements Payload
func (p *WorkflowJobPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}

254
gitea/structs/issue.go Normal file
View File

@ -0,0 +1,254 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"fmt"
"path"
"slices"
"strings"
"time"
"gopkg.in/yaml.v3"
)
// StateType issue state type
type StateType string
const (
// StateOpen pr is opend
StateOpen StateType = "open"
// StateClosed pr is closed
StateClosed StateType = "closed"
// StateAll is all
StateAll StateType = "all"
)
// PullRequestMeta PR info if an issue is a PR
type PullRequestMeta struct {
HasMerged bool `json:"merged"`
Merged *time.Time `json:"merged_at"`
IsWorkInProgress bool `json:"draft"`
HTMLURL string `json:"html_url"`
}
// RepositoryMeta basic repository information
type RepositoryMeta struct {
ID int `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 int `json:"id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
Index int `json:"number"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int `json:"original_author_id"`
Title string `json:"title"`
Body string `json:"body"`
Ref string `json:"ref"`
Attachments []*Attachment `json:"assets"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
// deprecated
Assignee *User `json:"assignee"`
Assignees []*User `json:"assignees"`
// Whether the issue is open or closed
//
// type: string
// enum: open,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"`
Repo *RepositoryMeta `json:"repository"`
PinOrder int `json:"pin_order"`
}
// CreateIssueOption options to create one issue
type CreateIssueOption struct {
// required:true
Title string `json:"title" binding:"Required"`
Body string `json:"body"`
Ref string `json:"ref"`
// deprecated
Assignee string `json:"assignee"`
Assignees []string `json:"assignees"`
Deadline *time.Time `json:"due_date"`
// milestone id
Milestone int `json:"milestone"`
// list of label ids
Labels []int `json:"labels"`
Closed bool `json:"closed"`
}
// EditIssueOption options for editing an issue
type EditIssueOption struct {
Title string `json:"title"`
Body *string `json:"body"`
Ref *string `json:"ref"`
// deprecated
Assignee *string `json:"assignee"`
Assignees []string `json:"assignees"`
Milestone *int `json:"milestone"`
State *string `json:"state"`
Deadline *time.Time `json:"due_date"`
RemoveDeadline *bool `json:"unset_due_date"`
}
// EditDeadlineOption options for creating a deadline
type EditDeadlineOption struct {
// required:true
Deadline *time.Time `json:"due_date"`
}
// IssueDeadline represents an issue deadline
type IssueDeadline struct {
Deadline *time.Time `json:"due_date"`
}
// IssueFormFieldType defines issue form field type, can be "markdown", "textarea", "input", "dropdown" or "checkboxes"
type IssueFormFieldType string
const (
IssueFormFieldTypeMarkdown IssueFormFieldType = "markdown"
IssueFormFieldTypeTextarea IssueFormFieldType = "textarea"
IssueFormFieldTypeInput IssueFormFieldType = "input"
IssueFormFieldTypeDropdown IssueFormFieldType = "dropdown"
IssueFormFieldTypeCheckboxes IssueFormFieldType = "checkboxes"
)
// IssueFormField represents a form field
type IssueFormField struct {
Type IssueFormFieldType `json:"type" yaml:"type"`
ID string `json:"id" yaml:"id"`
Attributes map[string]any `json:"attributes" yaml:"attributes"`
Validations map[string]any `json:"validations" yaml:"validations"`
Visible []IssueFormFieldVisible `json:"visible,omitempty"`
}
func (iff IssueFormField) VisibleOnForm() bool {
if len(iff.Visible) == 0 {
return true
}
return slices.Contains(iff.Visible, IssueFormFieldVisibleForm)
}
func (iff IssueFormField) VisibleInContent() bool {
if len(iff.Visible) == 0 {
// we have our markdown exception
return iff.Type != IssueFormFieldTypeMarkdown
}
return slices.Contains(iff.Visible, IssueFormFieldVisibleContent)
}
// IssueFormFieldVisible defines issue form field visible
type IssueFormFieldVisible string
const (
IssueFormFieldVisibleForm IssueFormFieldVisible = "form"
IssueFormFieldVisibleContent IssueFormFieldVisible = "content"
)
// IssueTemplate represents an issue template for a repository
type IssueTemplate struct {
Name string `json:"name" yaml:"name"`
Title string `json:"title" yaml:"title"`
About string `json:"about" yaml:"about"` // Using "description" in a template file is compatible
Labels IssueTemplateStringSlice `json:"labels" yaml:"labels"`
Assignees IssueTemplateStringSlice `json:"assignees" yaml:"assignees"`
Ref string `json:"ref" yaml:"ref"`
Content string `json:"content" yaml:"-"`
Fields []*IssueFormField `json:"body" yaml:"body"`
FileName string `json:"file_name" yaml:"-"`
}
type IssueTemplateStringSlice []string
func (l *IssueTemplateStringSlice) UnmarshalYAML(value *yaml.Node) error {
var labels []string
if value.IsZero() {
*l = labels
return nil
}
switch value.Kind {
case yaml.ScalarNode:
str := ""
err := value.Decode(&str)
if err != nil {
return err
}
for _, v := range strings.Split(str, ",") {
if v = strings.TrimSpace(v); v == "" {
continue
}
labels = append(labels, v)
}
*l = labels
return nil
case yaml.SequenceNode:
if err := value.Decode(&labels); err != nil {
return err
}
*l = labels
return nil
}
return fmt.Errorf("line %d: cannot unmarshal %s into IssueTemplateStringSlice", value.Line, value.ShortTag())
}
type IssueConfigContactLink struct {
Name string `json:"name" yaml:"name"`
URL string `json:"url" yaml:"url"`
About string `json:"about" yaml:"about"`
}
type IssueConfig struct {
BlankIssuesEnabled bool `json:"blank_issues_enabled" yaml:"blank_issues_enabled"`
ContactLinks []IssueConfigContactLink `json:"contact_links" yaml:"contact_links"`
}
type IssueConfigValidation struct {
Valid bool `json:"valid"`
Message string `json:"message"`
}
// IssueTemplateType defines issue template type
type IssueTemplateType string
const (
IssueTemplateTypeMarkdown IssueTemplateType = "md"
IssueTemplateTypeYaml IssueTemplateType = "yaml"
)
// Type returns the type of IssueTemplate, can be "md", "yaml" or empty for known
func (it IssueTemplate) Type() IssueTemplateType {
if base := path.Base(it.FileName); base == "config.yaml" || base == "config.yml" {
// ignore config.yaml which is a special configuration file
return ""
}
if ext := path.Ext(it.FileName); ext == ".md" {
return IssueTemplateTypeMarkdown
} else if ext == ".yaml" || ext == ".yml" {
return IssueTemplateTypeYaml
}
return ""
}
// IssueMeta basic issue information
type IssueMeta struct {
Index int `json:"index"`
Owner string `json:"owner"`
Name string `json:"repo"`
}

View File

@ -0,0 +1,78 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// Comment represents a comment on a commit or issue
type Comment struct {
ID int `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 int `json:"original_author_id"`
Body string `json:"body"`
Attachments []*Attachment `json:"assets"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// CreateIssueCommentOption options for creating a comment on an issue
type CreateIssueCommentOption struct {
// required:true
Body string `json:"body" binding:"Required"`
}
// EditIssueCommentOption options for editing a comment
type EditIssueCommentOption struct {
// required: true
Body string `json:"body" binding:"Required"`
}
// TimelineComment represents a timeline comment (comment of any type) on a commit or issue
type TimelineComment struct {
ID int `json:"id"`
Type string `json:"type"`
HTMLURL string `json:"html_url"`
PRURL string `json:"pull_request_url"`
IssueURL string `json:"issue_url"`
Poster *User `json:"user"`
Body string `json:"body"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
OldProjectID int `json:"old_project_id"`
ProjectID int `json:"project_id"`
OldMilestone *Milestone `json:"old_milestone"`
Milestone *Milestone `json:"milestone"`
TrackedTime *TrackedTime `json:"tracked_time"`
OldTitle string `json:"old_title"`
NewTitle string `json:"new_title"`
OldRef string `json:"old_ref"`
NewRef string `json:"new_ref"`
RefIssue *Issue `json:"ref_issue"`
RefComment *Comment `json:"ref_comment"`
RefAction string `json:"ref_action"`
// commit SHA where issue/PR was referenced
RefCommitSHA string `json:"ref_commit_sha"`
ReviewID int `json:"review_id"`
Label *Label `json:"label"`
Assignee *User `json:"assignee"`
AssigneeTeam *Team `json:"assignee_team"`
// whether the assignees were removed or added
RemovedAssignee bool `json:"removed_assignee"`
ResolveDoer *User `json:"resolve_doer"`
DependentIssue *Issue `json:"dependent_issue"`
}

View File

@ -0,0 +1,62 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// Label a label to an issue or a pr
type Label struct {
ID int `json:"id"`
Name string `json:"name"`
// example: false
Exclusive bool `json:"exclusive"`
// example: false
IsArchived bool `json:"is_archived"`
// example: 00aabb
Color string `json:"color"`
Description string `json:"description"`
URL string `json:"url"`
}
// CreateLabelOption options for creating a label
type CreateLabelOption struct {
// required:true
Name string `json:"name" binding:"Required"`
// example: false
Exclusive bool `json:"exclusive"`
// required:true
// example: #00aabb
Color string `json:"color" binding:"Required"`
Description string `json:"description"`
// example: false
IsArchived bool `json:"is_archived"`
}
// EditLabelOption options for editing a label
type EditLabelOption struct {
Name *string `json:"name"`
// example: false
Exclusive *bool `json:"exclusive"`
// example: #00aabb
Color *string `json:"color"`
Description *string `json:"description"`
// example: false
IsArchived *bool `json:"is_archived"`
}
// IssueLabelsOption a collection of labels
type IssueLabelsOption struct {
// Labels can be a list of integers representing label IDs
// or a list of strings representing label names
Labels []any `json:"labels"`
}
// LabelTemplate info of a Label template
type LabelTemplate struct {
Name string `json:"name"`
// example: false
Exclusive bool `json:"exclusive"`
// example: 00aabb
Color string `json:"color"`
Description string `json:"description"`
}

View File

@ -0,0 +1,39 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// Milestone milestone is a collection of issues on one repository
type Milestone struct {
ID int `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"`
}
// CreateMilestoneOption options for creating a milestone
type CreateMilestoneOption struct {
Title string `json:"title"`
Description string `json:"description"`
Deadline *time.Time `json:"due_on"`
// enum: open,closed
State string `json:"state"`
}
// EditMilestoneOption options for editing a milestone
type EditMilestoneOption struct {
Title string `json:"title"`
Description *string `json:"description"`
State *string `json:"state"`
Deadline *time.Time `json:"due_on"`
}

View File

@ -0,0 +1,20 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// EditReactionOption contain the reaction type
type EditReactionOption struct {
Reaction string `json:"content"`
}
// Reaction contain one reaction
type Reaction struct {
User *User `json:"user"`
Reaction string `json:"content"`
Created time.Time `json:"created_at"`
}

View File

@ -0,0 +1,22 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// StopWatch represent a running stopwatch
type StopWatch struct {
Created time.Time `json:"created"`
Seconds int `json:"seconds"`
Duration string `json:"duration"`
IssueIndex int `json:"issue_index"`
IssueTitle string `json:"issue_title"`
RepoOwnerName string `json:"repo_owner_name"`
RepoName string `json:"repo_name"`
}
// StopWatches represent a list of stopwatches
type StopWatches []StopWatch

105
gitea/structs/issue_test.go Normal file
View File

@ -0,0 +1,105 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
)
func TestIssueTemplate_Type(t *testing.T) {
tests := []struct {
fileName string
want IssueTemplateType
}{
{
fileName: ".gitea/ISSUE_TEMPLATE/bug_report.yaml",
want: IssueTemplateTypeYaml,
},
{
fileName: ".gitea/ISSUE_TEMPLATE/bug_report.md",
want: IssueTemplateTypeMarkdown,
},
{
fileName: ".gitea/ISSUE_TEMPLATE/bug_report.txt",
want: "",
},
{
fileName: ".gitea/ISSUE_TEMPLATE/config.yaml",
want: "",
},
}
for _, tt := range tests {
t.Run(tt.fileName, func(t *testing.T) {
it := IssueTemplate{
FileName: tt.fileName,
}
assert.Equal(t, tt.want, it.Type())
})
}
}
func TestIssueTemplateStringSlice_UnmarshalYAML(t *testing.T) {
tests := []struct {
name string
content string
tmpl *IssueTemplate
want *IssueTemplate
wantErr string
}{
{
name: "array",
content: `labels: ["a", "b", "c"]`,
tmpl: &IssueTemplate{
Labels: []string{"should_be_overwrote"},
},
want: &IssueTemplate{
Labels: []string{"a", "b", "c"},
},
},
{
name: "string",
content: `labels: "a,b,c"`,
tmpl: &IssueTemplate{
Labels: []string{"should_be_overwrote"},
},
want: &IssueTemplate{
Labels: []string{"a", "b", "c"},
},
},
{
name: "empty",
content: `labels:`,
tmpl: &IssueTemplate{
Labels: []string{"should_be_overwrote"},
},
want: &IssueTemplate{
Labels: nil,
},
},
{
name: "error",
content: `
labels:
a: aa
b: bb
`,
tmpl: &IssueTemplate{},
wantErr: "line 3: cannot unmarshal !!map into IssueTemplateStringSlice",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := yaml.Unmarshal([]byte(tt.content), tt.tmpl)
if tt.wantErr != "" {
assert.EqualError(t, err, tt.wantErr)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, tt.tmpl)
}
})
}
}

View File

@ -0,0 +1,35 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// AddTimeOption options for adding time to an issue
type AddTimeOption struct {
// time in seconds
// required: true
Time int `json:"time" binding:"Required"`
Created time.Time `json:"created"`
// User who spent the time (optional)
User string `json:"user_name"`
}
// TrackedTime worked time for an issue / pr
type TrackedTime struct {
ID int `json:"id"`
Created time.Time `json:"created"`
// Time in seconds
Time int `json:"time"`
// deprecated (only for backwards compatibility)
UserID int `json:"user_id"`
UserName string `json:"user_name"`
// deprecated (only for backwards compatibility)
IssueID int `json:"issue_id"`
Issue *Issue `json:"issue"`
}
// TrackedTimeList represents a list of tracked times
type TrackedTimeList []*TrackedTime

64
gitea/structs/lfs_lock.go Normal file
View File

@ -0,0 +1,64 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// LFSLock represent a lock
// for use with the locks API.
type LFSLock struct {
ID string `json:"id"`
Path string `json:"path"`
LockedAt time.Time `json:"locked_at"`
Owner *LFSLockOwner `json:"owner"`
}
// LFSLockOwner represent a lock owner
// for use with the locks API.
type LFSLockOwner struct {
Name string `json:"name"`
}
// LFSLockRequest contains the path of the lock to create
// https://github.com/git-lfs/git-lfs/blob/master/docs/api/locking.md#create-lock
type LFSLockRequest struct {
Path string `json:"path"`
}
// LFSLockResponse represent a lock created
// https://github.com/git-lfs/git-lfs/blob/master/docs/api/locking.md#create-lock
type LFSLockResponse struct {
Lock *LFSLock `json:"lock"`
}
// LFSLockList represent a list of lock requested
// https://github.com/git-lfs/git-lfs/blob/master/docs/api/locking.md#list-locks
type LFSLockList struct {
Locks []*LFSLock `json:"locks"`
Next string `json:"next_cursor,omitempty"`
}
// LFSLockListVerify represent a list of lock verification requested
// https://github.com/git-lfs/git-lfs/blob/master/docs/api/locking.md#list-locks-for-verification
type LFSLockListVerify struct {
Ours []*LFSLock `json:"ours"`
Theirs []*LFSLock `json:"theirs"`
Next string `json:"next_cursor,omitempty"`
}
// LFSLockError contains information on the error that occurs
type LFSLockError struct {
Message string `json:"message"`
Lock *LFSLock `json:"lock,omitempty"`
Documentation string `json:"documentation_url,omitempty"`
RequestID string `json:"request_id,omitempty"`
}
// LFSLockDeleteRequest contains params of a delete request
// https://github.com/git-lfs/git-lfs/blob/master/docs/api/locking.md#delete-lock
type LFSLockDeleteRequest struct {
Force bool `json:"force"`
}

27
gitea/structs/mirror.go Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import "time"
// CreatePushMirrorOption represents need information to create a push mirror of a repository.
type CreatePushMirrorOption struct {
RemoteAddress string `json:"remote_address"`
RemoteUsername string `json:"remote_username"`
RemotePassword string `json:"remote_password"`
Interval string `json:"interval"`
SyncOnCommit bool `json:"sync_on_commit"`
}
// PushMirror represents information of a push mirror
type PushMirror struct {
RepoName string `json:"repo_name"`
RemoteName string `json:"remote_name"`
RemoteAddress string `json:"remote_address"`
CreatedUnix time.Time `json:"created"`
LastUpdateUnix *time.Time `json:"last_update"`
LastError string `json:"last_error"`
Interval string `json:"interval"`
SyncOnCommit bool `json:"sync_on_commit"`
}

View File

@ -0,0 +1,103 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// SearchResults results of a successful search
type SearchResults struct {
OK bool `json:"ok"`
Data []*Repository `json:"data"`
}
// SearchError error of a failed search
type SearchError struct {
OK bool `json:"ok"`
Error string `json:"error"`
}
// MarkupOption markup options
type MarkupOption struct {
// Text markup to render
//
// in: body
Text string
// Mode to render (markdown, comment, wiki, file)
//
// in: body
Mode string
// URL path for rendering issue, media and file links
// Expected format: /subpath/{user}/{repo}/src/{branch, commit, tag}/{identifier/path}/{file/dir}
//
// in: body
Context string
// Is it a wiki page? (use mode=wiki instead)
//
// Deprecated: true
// in: body
Wiki bool
// File path for detecting extension in file mode
//
// in: body
FilePath string
}
// MarkupRender is a rendered markup document
type MarkupRender string
// MarkdownOption markdown options
type MarkdownOption struct {
// Text markdown to render
//
// in: body
Text string
// Mode to render (markdown, comment, wiki, file)
//
// in: body
Mode string
// URL path for rendering issue, media and file links
// Expected format: /subpath/{user}/{repo}/src/{branch, commit, tag}/{identifier/path}/{file/dir}
//
// in: body
Context string
// Is it a wiki page? (use mode=wiki instead)
//
// Deprecated: true
// in: body
Wiki bool
}
// MarkdownRender is a rendered markdown document
type MarkdownRender string
// ServerVersion wraps the version of the server
type ServerVersion struct {
Version string `json:"version"`
}
// GitignoreTemplateInfo name and text of a gitignore template
type GitignoreTemplateInfo struct {
Name string `json:"name"`
Source string `json:"source"`
}
// LicensesListEntry is used for the API
type LicensesTemplateListEntry struct {
Key string `json:"key"`
Name string `json:"name"`
URL string `json:"url"`
}
// LicensesInfo contains information about a License
type LicenseTemplateInfo struct {
Key string `json:"key"`
Name string `json:"name"`
URL string `json:"url"`
Implementation string `json:"implementation"`
Body string `json:"body"`
}
// APIError is an api error with a message
type APIError struct {
Message string `json:"message"`
URL string `json:"url"`
}

43
gitea/structs/nodeinfo.go Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// NodeInfo contains standardized way of exposing metadata about a server running one of the distributed social networks
type NodeInfo struct {
Version string `json:"version"`
Software NodeInfoSoftware `json:"software"`
Protocols []string `json:"protocols"`
Services NodeInfoServices `json:"services"`
OpenRegistrations bool `json:"openRegistrations"`
Usage NodeInfoUsage `json:"usage"`
Metadata struct{} `json:"metadata"`
}
// NodeInfoSoftware contains Metadata about server software in use
type NodeInfoSoftware struct {
Name string `json:"name"`
Version string `json:"version"`
Repository string `json:"repository"`
Homepage string `json:"homepage"`
}
// NodeInfoServices contains the third party sites this server can connect to via their application API
type NodeInfoServices struct {
Inbound []string `json:"inbound"`
Outbound []string `json:"outbound"`
}
// NodeInfoUsage contains usage statistics for this server
type NodeInfoUsage struct {
Users NodeInfoUsageUsers `json:"users"`
LocalPosts int `json:"localPosts,omitempty"`
LocalComments int `json:"localComments,omitempty"`
}
// NodeInfoUsageUsers contains statistics about the users of this server
type NodeInfoUsageUsers struct {
Total int `json:"total,omitempty"`
ActiveHalfyear int `json:"activeHalfyear,omitempty"`
ActiveMonth int `json:"activeMonth,omitempty"`
}

View File

@ -0,0 +1,49 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// NotificationThread expose Notification on API
type NotificationThread struct {
ID int `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"`
HTMLURL string `json:"html_url"`
LatestCommentHTMLURL string `json:"latest_comment_html_url"`
Type NotifySubjectType `json:"type" binding:"In(Issue,Pull,Commit,Repository)"`
State StateType `json:"state"`
}
// NotificationCount number of unread notifications
type NotificationCount struct {
New int `json:"new"`
}
// 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"
)

68
gitea/structs/org.go Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// Organization represents an organization
type Organization struct {
ID int `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
Email string `json:"email"`
AvatarURL string `json:"avatar_url"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
Visibility string `json:"visibility"`
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
// deprecated
UserName string `json:"username"`
}
// OrganizationPermissions list different users permissions on an organization
type OrganizationPermissions struct {
IsOwner bool `json:"is_owner"`
IsAdmin bool `json:"is_admin"`
CanWrite bool `json:"can_write"`
CanRead bool `json:"can_read"`
CanCreateRepository bool `json:"can_create_repository"`
}
// CreateOrgOption options for creating an organization
type CreateOrgOption struct {
// required: true
UserName string `json:"username" binding:"Required;Username;MaxSize(40)"`
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"MaxSize(255)"`
Description string `json:"description" binding:"MaxSize(255)"`
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
Location string `json:"location" binding:"MaxSize(50)"`
// possible values are `public` (default), `limited` or `private`
// enum: public,limited,private
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
}
// TODO: make EditOrgOption fields optional after https://gitea.com/go-chi/binding/pulls/5 got merged
// EditOrgOption options for editing an organization
type EditOrgOption struct {
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"MaxSize(255)"`
Description string `json:"description" binding:"MaxSize(255)"`
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
Location string `json:"location" binding:"MaxSize(50)"`
// possible values are `public`, `limited` or `private`
// enum: public,limited,private
Visibility string `json:"visibility" binding:"In(,public,limited,private)"`
RepoAdminChangeTeamAccess *bool `json:"repo_admin_change_team_access"`
}
// RenameOrgOption options when renaming an organization
type RenameOrgOption struct {
// New username for this org. This name cannot be in use yet by any other user.
//
// required: true
// unique: true
NewName string `json:"new_name" binding:"Required"`
}

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// AddOrgMembershipOption add user to organization options
type AddOrgMembershipOption struct {
Role string `json:"role" binding:"Required"`
}

54
gitea/structs/org_team.go Normal file
View File

@ -0,0 +1,54 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// Team represents a team in an organization
type Team struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Organization *Organization `json:"organization"`
IncludesAllRepositories bool `json:"includes_all_repositories"`
// enum: none,read,write,admin,owner
Permission string `json:"permission"`
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"]
// Deprecated: This variable should be replaced by UnitsMap and will be dropped in later versions.
Units []string `json:"units"`
// example: {"repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}
UnitsMap map[string]string `json:"units_map"`
CanCreateOrgRepo bool `json:"can_create_org_repo"`
}
// CreateTeamOption options for creating a team
type CreateTeamOption struct {
// required: true
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(255)"`
Description string `json:"description" binding:"MaxSize(255)"`
IncludesAllRepositories bool `json:"includes_all_repositories"`
// enum: read,write,admin
Permission string `json:"permission"`
// example: ["repo.actions","repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.ext_wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"]
// Deprecated: This variable should be replaced by UnitsMap and will be dropped in later versions.
Units []string `json:"units"`
// example: {"repo.actions","repo.packages","repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}
UnitsMap map[string]string `json:"units_map"`
CanCreateOrgRepo bool `json:"can_create_org_repo"`
}
// EditTeamOption options for editing a team
type EditTeamOption struct {
// required: true
Name string `json:"name" binding:"AlphaDashDot;MaxSize(255)"`
Description *string `json:"description" binding:"MaxSize(255)"`
IncludesAllRepositories *bool `json:"includes_all_repositories"`
// enum: read,write,admin
Permission string `json:"permission"`
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.projects","repo.ext_wiki"]
// Deprecated: This variable should be replaced by UnitsMap and will be dropped in later versions.
Units []string `json:"units"`
// example: {"repo.code":"read","repo.issues":"write","repo.ext_issues":"none","repo.wiki":"admin","repo.pulls":"owner","repo.releases":"none","repo.projects":"none","repo.ext_wiki":"none"}
UnitsMap map[string]string `json:"units_map"`
CanCreateOrgRepo *bool `json:"can_create_org_repo"`
}

32
gitea/structs/package.go Normal file
View File

@ -0,0 +1,32 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// Package represents a package
type Package struct {
ID int `json:"id"`
Owner *User `json:"owner"`
Repository *Repository `json:"repository"`
Creator *User `json:"creator"`
Type string `json:"type"`
Name string `json:"name"`
Version string `json:"version"`
HTMLURL string `json:"html_url"`
CreatedAt time.Time `json:"created_at"`
}
// PackageFile represents a package file
type PackageFile struct {
ID int `json:"id"`
Size int
Name string `json:"name"`
HashMD5 string `json:"md5"`
HashSHA1 string `json:"sha1"`
HashSHA256 string `json:"sha256"`
HashSHA512 string `json:"sha512"`
}

116
gitea/structs/pull.go Normal file
View File

@ -0,0 +1,116 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// PullRequest represents a pull request
type PullRequest struct {
ID int `json:"id"`
URL string `json:"url"`
Index int `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"`
RequestedReviewers []*User `json:"requested_reviewers"`
RequestedReviewersTeams []*Team `json:"requested_reviewers_teams"`
State StateType `json:"state"`
Draft bool `json:"draft"`
IsLocked bool `json:"is_locked"`
Comments int `json:"comments"`
// number of review comments made on the diff of a PR review (not including comments on commits or issues in a PR)
ReviewComments int `json:"review_comments,omitempty"`
Additions *int `json:"additions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
ChangedFiles *int `json:"changed_files,omitempty"`
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"`
AllowMaintainerEdit bool `json:"allow_maintainer_edit"`
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"`
PinOrder int `json:"pin_order"`
}
// PRBranchInfo information about a branch
type PRBranchInfo struct {
Name string `json:"label"`
Ref string `json:"ref"`
Sha string `json:"sha"`
RepoID int `json:"repo_id"`
Repository *Repository `json:"repo"`
}
// ListPullRequestsOptions options for listing pull requests
type ListPullRequestsOptions struct {
Page int `json:"page"`
State string `json:"state"`
}
// CreatePullRequestOption options when creating a pull request
type CreatePullRequestOption struct {
Head string `json:"head" binding:"Required"`
Base string `json:"base" binding:"Required"`
Title string `json:"title" binding:"Required"`
Body string `json:"body"`
Assignee string `json:"assignee"`
Assignees []string `json:"assignees"`
Milestone int `json:"milestone"`
Labels []int `json:"labels"`
Deadline *time.Time `json:"due_date"`
Reviewers []string `json:"reviewers"`
TeamReviewers []string `json:"team_reviewers"`
}
// 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 int `json:"milestone"`
Labels []int `json:"labels"`
State *string `json:"state"`
Deadline *time.Time `json:"due_date"`
RemoveDeadline *bool `json:"unset_due_date"`
AllowMaintainerEdit *bool `json:"allow_maintainer_edit"`
}
// ChangedFile store information about files affected by the pull request
type ChangedFile struct {
Filename string `json:"filename"`
PreviousFilename string `json:"previous_filename,omitempty"`
Status string `json:"status"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
Changes int `json:"changes"`
HTMLURL string `json:"html_url,omitempty"`
ContentsURL string `json:"contents_url,omitempty"`
RawURL string `json:"raw_url,omitempty"`
}

View File

@ -0,0 +1,104 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"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 int `json:"id"`
Reviewer *User `json:"user"`
ReviewerTeam *Team `json:"team"`
State ReviewStateType `json:"state"`
Body string `json:"body"`
CommitID string `json:"commit_id"`
Stale bool `json:"stale"`
Official bool `json:"official"`
Dismissed bool `json:"dismissed"`
CodeCommentsCount int `json:"comments_count"`
Submitted time.Time `json:"submitted_at"`
Updated time.Time `json:"updated_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 int `json:"id"`
Body string `json:"body"`
Poster *User `json:"user"`
Resolver *User `json:"resolver"`
ReviewID int `json:"pull_request_review_id"`
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 uint `json:"position"`
OldLineNum uint `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 {
Event 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 int `json:"old_position"`
// if comment to new file line or 0
NewLineNum int `json:"new_position"`
}
// SubmitPullReviewOptions are options to submit a pending pull review
type SubmitPullReviewOptions struct {
Event ReviewStateType `json:"event"`
Body string `json:"body"`
}
// DismissPullReviewOptions are options to dismiss a pull review
type DismissPullReviewOptions struct {
Message string `json:"message"`
Priors bool `json:"priors"`
}
// PullReviewRequestOptions are options to add or remove pull review requests
type PullReviewRequestOptions struct {
Reviewers []string `json:"reviewers"`
TeamReviewers []string `json:"team_reviewers"`
}

49
gitea/structs/release.go Normal file
View File

@ -0,0 +1,49 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// Release represents a repository release
type Release struct {
ID int `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"`
UploadURL string `json:"upload_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"`
}
// CreateReleaseOption options when creating a release
type CreateReleaseOption struct {
// required: true
TagName string `json:"tag_name" binding:"Required"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
IsDraft bool `json:"draft"`
IsPrerelease bool `json:"prerelease"`
}
// 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"`
}

410
gitea/structs/repo.go Normal file
View File

@ -0,0 +1,410 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"strings"
"time"
)
// Permission represents a set of permissions
type Permission struct {
Admin bool `json:"admin"` // Admin indicates if the user is an administrator of the repository.
Push bool `json:"push"` // Push indicates if the user can push code to the repository.
Pull bool `json:"pull"` // Pull indicates if the user can pull code from the repository.
}
// 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`, `alphanumeric`, or `regexp`
ExternalTrackerStyle string `json:"external_tracker_style"`
// External Issue Tracker issue regular expression
ExternalTrackerRegexpPattern string `json:"external_tracker_regexp_pattern"`
}
// 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 int `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"`
Language string `json:"language"`
LanguagesURL string `json:"languages_url"`
HTMLURL string `json:"html_url"`
URL string `json:"url"`
Link string `json:"link"`
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"`
ArchivedAt time.Time `json:"archived_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"`
ProjectsMode string `json:"projects_mode"`
HasReleases bool `json:"has_releases"`
HasPackages bool `json:"has_packages"`
HasActions bool `json:"has_actions"`
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"`
AllowFastForwardOnly bool `json:"allow_fast_forward_only_merge"`
AllowRebaseUpdate bool `json:"allow_rebase_update"`
DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"`
DefaultMergeStyle string `json:"default_merge_style"`
DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"`
AvatarURL string `json:"avatar_url"`
Internal bool `json:"internal"`
MirrorInterval string `json:"mirror_interval"`
// ObjectFormatName of the underlying git repository
// enum: sha1,sha256
ObjectFormatName string `json:"object_format_name"`
MirrorUpdated time.Time `json:"mirror_updated,omitempty"`
RepoTransfer *RepoTransfer `json:"repo_transfer"`
Topics []string `json:"topics"`
Licenses []string `json:"licenses"`
}
// CreateRepoOption options when creating repository
type CreateRepoOption struct {
// Name of the repository to create
//
// required: true
// unique: true
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"`
// Description of the repository to create
Description string `json:"description" binding:"MaxSize(2048)"`
// Whether the repository is private
Private bool `json:"private"`
// Label-Set to use
IssueLabels string `json:"issue_labels"`
// Whether the repository should be auto-initialized?
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" binding:"GitRefName;MaxSize(100)"`
// TrustModel of the repository
// enum: default,collaborator,committer,collaboratorcommitter
TrustModel string `json:"trust_model"`
// ObjectFormatName of the underlying git repository
// enum: sha1,sha256
ObjectFormatName string `json:"object_format_name" binding:"MaxSize(6)"`
}
// EditRepoOption options when editing a repository's properties
type EditRepoOption struct {
// name of the repository
// unique: true
Name *string `json:"name,omitempty" binding:"OmitEmpty;AlphaDashDot;MaxSize(100);"`
// a short description of the repository.
Description *string `json:"description,omitempty" binding:"MaxSize(2048)"`
// a URL with more information about the repository.
Website *string `json:"website,omitempty" binding:"MaxSize(1024)"`
// 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
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
// set this structure to use external issue tracker
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
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"`
// `repo` to only allow repo-level projects, `owner` to only allow owner projects, `all` to allow both.
ProjectsMode *string `json:"projects_mode,omitempty" binding:"In(repo,owner,all)"`
// either `true` to enable releases unit, or `false` to disable them.
HasReleases *bool `json:"has_releases,omitempty"`
// either `true` to enable packages unit, or `false` to disable them.
HasPackages *bool `json:"has_packages,omitempty"`
// either `true` to enable actions unit, or `false` to disable them.
HasActions *bool `json:"has_actions,omitempty"`
// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace.
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.
AllowMerge *bool `json:"allow_merge_commits,omitempty"`
// either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging.
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.
AllowRebaseMerge *bool `json:"allow_rebase_explicit,omitempty"`
// either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.
AllowSquash *bool `json:"allow_squash_merge,omitempty"`
// either `true` to allow fast-forward-only merging pull requests, or `false` to prevent fast-forward-only merging.
AllowFastForwardOnly *bool `json:"allow_fast_forward_only_merge,omitempty"`
// either `true` to allow mark pr as merged manually, or `false` to prevent it.
AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
// either `true` to enable AutodetectManualMerge, or `false` to prevent it. Note: In some special cases, misjudgments can occur.
AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"`
// either `true` to allow updating pull request branch by rebase, or `false` to prevent it.
AllowRebaseUpdate *bool `json:"allow_rebase_update,omitempty"`
// set to `true` to delete pr branch after merge by default
DefaultDeleteBranchAfterMerge *bool `json:"default_delete_branch_after_merge,omitempty"`
// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", "squash", or "fast-forward-only".
DefaultMergeStyle *string `json:"default_merge_style,omitempty"`
// set to `true` to allow edits from maintainers by default
DefaultAllowMaintainerEdit *bool `json:"default_allow_maintainer_edit,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"`
// enable prune - remove obsolete remote-tracking references when mirroring
EnablePrune *bool `json:"enable_prune,omitempty"`
}
// GenerateRepoOption options when creating repository using a template
type GenerateRepoOption struct {
// The organization or person who will own the new repository
//
// required: true
Owner string `json:"owner"`
// Name of the repository to create
//
// required: true
// unique: true
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"`
// Default branch of the new repository
DefaultBranch string `json:"default_branch"`
// Description of the repository to create
Description string `json:"description" binding:"MaxSize(2048)"`
// Whether the repository is private
Private bool `json:"private"`
// include git content of default branch in template repo
GitContent bool `json:"git_content"`
// include topics in template repo
Topics bool `json:"topics"`
// include git hooks in template repo
GitHooks bool `json:"git_hooks"`
// include webhooks in template repo
Webhooks bool `json:"webhooks"`
// include avatar of the template repo
Avatar bool `json:"avatar"`
// include labels in template repo
Labels bool `json:"labels"`
// include protected branches in template repo
ProtectedBranch bool `json:"protected_branch"`
}
// CreateBranchRepoOption options when creating a branch in a repository
type CreateBranchRepoOption struct {
// Name of the branch to create
//
// required: true
// unique: true
BranchName string `json:"new_branch_name" binding:"Required;GitRefName;MaxSize(100)"`
// Deprecated: true
// Name of the old branch to create from
//
// unique: true
OldBranchName string `json:"old_branch_name" binding:"GitRefName;MaxSize(100)"`
// Name of the old branch/tag/commit to create from
//
// unique: true
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
}
// UpdateBranchRepoOption options when updating a branch in a repository
type UpdateBranchRepoOption struct {
// New branch name
//
// required: true
// unique: true
Name string `json:"name" binding:"Required;GitRefName;MaxSize(100)"`
}
// 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 *[]int `json:"team_ids"`
}
// GitServiceType represents a git service
type GitServiceType int
// enumerate all GitServiceType
const (
NotMigrated GitServiceType = iota // 0 not migrated from external sites
PlainGitService // 1 plain git service
GithubService // 2 github.com
GiteaService // 3 gitea service
GitlabService // 4 gitlab service
GogsService // 5 gogs service
OneDevService // 6 onedev service
GitBucketService // 7 gitbucket service
CodebaseService // 8 codebase service
CodeCommitService // 9 codecommit service
)
// Name represents the service type's name
// WARNNING: the name have to be equal to that on goth's library
func (gt GitServiceType) Name() string {
return strings.ToLower(gt.Title())
}
// Title represents the service type's proper title
func (gt GitServiceType) Title() string {
switch gt {
case GithubService:
return "GitHub"
case GiteaService:
return "Gitea"
case GitlabService:
return "GitLab"
case GogsService:
return "Gogs"
case OneDevService:
return "OneDev"
case GitBucketService:
return "GitBucket"
case CodebaseService:
return "Codebase"
case CodeCommitService:
return "CodeCommit"
case PlainGitService:
return "Git"
}
return ""
}
// MigrateRepoOptions options for migrating repository's
// this is used to interact with api v1
type MigrateRepoOptions struct {
// required: true
CloneAddr string `json:"clone_addr" binding:"Required"`
// deprecated (only for backwards compatibility)
RepoOwnerID int `json:"uid"`
// Name of User or Organisation who will own Repo after migration
RepoOwner string `json:"repo_owner"`
// required: true
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
// enum: git,github,gitea,gitlab,gogs,onedev,gitbucket,codebase
Service string `json:"service"`
AuthUsername string `json:"auth_username"`
AuthPassword string `json:"auth_password"`
AuthToken string `json:"auth_token"`
Mirror bool `json:"mirror"`
LFS bool `json:"lfs"`
LFSEndpoint string `json:"lfs_endpoint"`
Private bool `json:"private"`
Description string `json:"description" binding:"MaxSize(2048)"`
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"`
AWSAccessKeyID string `json:"aws_access_key_id"`
AWSSecretAccessKey string `json:"aws_secret_access_key"`
}
// TokenAuth represents whether a service type supports token-based auth
func (gt GitServiceType) TokenAuth() bool {
switch gt {
case GithubService, GiteaService, GitlabService:
return true
}
return false
}
// SupportedFullGitService represents all git services supported to migrate issues/labels/prs and etc.
// TODO: add to this list after new git service added
var SupportedFullGitService = []GitServiceType{
GithubService,
GitlabService,
GiteaService,
GogsService,
OneDevService,
GitBucketService,
CodebaseService,
CodeCommitService,
}
// RepoTransfer represents a pending repo transfer
type RepoTransfer struct {
Doer *User `json:"doer"`
Recipient *User `json:"recipient"`
Teams []*Team `json:"teams"`
}
// NewIssuePinsAllowed represents an API response that says if new Issue Pins are allowed
type NewIssuePinsAllowed struct {
Issues bool `json:"issues"`
PullRequests bool `json:"pull_requests"`
}
// UpdateRepoAvatarUserOption options when updating the repo avatar
type UpdateRepoAvatarOption struct {
// image must be base64 encoded
Image string `json:"image" binding:"Required"`
}

View File

@ -0,0 +1,120 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// ActionTask represents a ActionTask
type ActionTask struct {
ID int `json:"id"`
Name string `json:"name"`
HeadBranch string `json:"head_branch"`
HeadSHA string `json:"head_sha"`
RunNumber int `json:"run_number"`
Event string `json:"event"`
DisplayTitle string `json:"display_title"`
Status string `json:"status"`
WorkflowID string `json:"workflow_id"`
URL string `json:"url"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
RunStartedAt time.Time `json:"run_started_at"`
}
// ActionTaskResponse returns a ActionTask
type ActionTaskResponse struct {
Entries []*ActionTask `json:"workflow_runs"`
TotalCount int `json:"total_count"`
}
// CreateActionWorkflowDispatch represents the payload for triggering a workflow dispatch event
type CreateActionWorkflowDispatch struct {
// required: true
// example: refs/heads/main
Ref string `json:"ref" binding:"Required"`
// required: false
Inputs map[string]string `json:"inputs,omitempty"`
}
// ActionWorkflow represents a ActionWorkflow
type ActionWorkflow struct {
ID string `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
BadgeURL string `json:"badge_url"`
DeletedAt time.Time `json:"deleted_at,omitempty"`
}
// ActionWorkflowResponse returns a ActionWorkflow
type ActionWorkflowResponse struct {
Workflows []*ActionWorkflow `json:"workflows"`
TotalCount int `json:"total_count"`
}
// ActionArtifact represents a ActionArtifact
type ActionArtifact struct {
ID int `json:"id"`
Name string `json:"name"`
SizeInBytes int `json:"size_in_bytes"`
URL string `json:"url"`
ArchiveDownloadURL string `json:"archive_download_url"`
Expired bool `json:"expired"`
WorkflowRun *ActionWorkflowRun `json:"workflow_run"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ExpiresAt time.Time `json:"expires_at"`
}
// ActionWorkflowRun represents a WorkflowRun
type ActionWorkflowRun struct {
ID int `json:"id"`
RepositoryID int `json:"repository_id"`
HeadSha string `json:"head_sha"`
}
// ActionArtifactsResponse returns ActionArtifacts
type ActionArtifactsResponse struct {
Entries []*ActionArtifact `json:"artifacts"`
TotalCount int `json:"total_count"`
}
// ActionWorkflowStep represents a step of a WorkflowJob
type ActionWorkflowStep struct {
Name string `json:"name"`
Number int `json:"number"`
Status string `json:"status"`
Conclusion string `json:"conclusion,omitempty"`
StartedAt time.Time `json:"started_at,omitempty"`
CompletedAt time.Time `json:"completed_at,omitempty"`
}
// ActionWorkflowJob represents a WorkflowJob
type ActionWorkflowJob struct {
ID int `json:"id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
RunID int `json:"run_id"`
RunURL string `json:"run_url"`
Name string `json:"name"`
Labels []string `json:"labels"`
RunAttempt int `json:"run_attempt"`
HeadSha string `json:"head_sha"`
HeadBranch string `json:"head_branch,omitempty"`
Status string `json:"status"`
Conclusion string `json:"conclusion,omitempty"`
RunnerID int `json:"runner_id,omitempty"`
RunnerName string `json:"runner_name,omitempty"`
Steps []*ActionWorkflowStep `json:"steps"`
CreatedAt time.Time `json:"created_at"`
StartedAt time.Time `json:"started_at,omitempty"`
CompletedAt time.Time `json:"completed_at,omitempty"`
}

View File

@ -0,0 +1,141 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// Branch represents a repository branch
type Branch struct {
Name string `json:"name"`
Commit *PayloadCommit `json:"commit"`
Protected bool `json:"protected"`
RequiredApprovals int `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"`
}
// BranchProtection represents a branch protection for a repository
type BranchProtection struct {
// Deprecated: true
BranchName string `json:"branch_name"`
RuleName string `json:"rule_name"`
Priority int `json:"priority"`
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"`
EnableForcePush bool `json:"enable_force_push"`
EnableForcePushAllowlist bool `json:"enable_force_push_allowlist"`
ForcePushAllowlistUsernames []string `json:"force_push_allowlist_usernames"`
ForcePushAllowlistTeams []string `json:"force_push_allowlist_teams"`
ForcePushAllowlistDeployKeys bool `json:"force_push_allowlist_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 int `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"`
IgnoreStaleApprovals bool `json:"ignore_stale_approvals"`
RequireSignedCommits bool `json:"require_signed_commits"`
ProtectedFilePatterns string `json:"protected_file_patterns"`
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
BlockAdminMergeOverride bool `json:"block_admin_merge_override"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// CreateBranchProtectionOption options for creating a branch protection
type CreateBranchProtectionOption struct {
// Deprecated: true
BranchName string `json:"branch_name"`
RuleName string `json:"rule_name"`
Priority int `json:"priority"`
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"`
EnableForcePush bool `json:"enable_force_push"`
EnableForcePushAllowlist bool `json:"enable_force_push_allowlist"`
ForcePushAllowlistUsernames []string `json:"force_push_allowlist_usernames"`
ForcePushAllowlistTeams []string `json:"force_push_allowlist_teams"`
ForcePushAllowlistDeployKeys bool `json:"force_push_allowlist_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 int `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"`
IgnoreStaleApprovals bool `json:"ignore_stale_approvals"`
RequireSignedCommits bool `json:"require_signed_commits"`
ProtectedFilePatterns string `json:"protected_file_patterns"`
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
BlockAdminMergeOverride bool `json:"block_admin_merge_override"`
}
// EditBranchProtectionOption options for editing a branch protection
type EditBranchProtectionOption struct {
Priority *int `json:"priority"`
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"`
EnableForcePush *bool `json:"enable_force_push"`
EnableForcePushAllowlist *bool `json:"enable_force_push_allowlist"`
ForcePushAllowlistUsernames []string `json:"force_push_allowlist_usernames"`
ForcePushAllowlistTeams []string `json:"force_push_allowlist_teams"`
ForcePushAllowlistDeployKeys *bool `json:"force_push_allowlist_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 *int `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"`
IgnoreStaleApprovals *bool `json:"ignore_stale_approvals"`
RequireSignedCommits *bool `json:"require_signed_commits"`
ProtectedFilePatterns *string `json:"protected_file_patterns"`
UnprotectedFilePatterns *string `json:"unprotected_file_patterns"`
BlockAdminMergeOverride *bool `json:"block_admin_merge_override"`
}
// UpdateBranchProtectionPriories a list to update the branch protection rule priorities
type UpdateBranchProtectionPriories struct {
IDs []int `json:"ids"`
}
type MergeUpstreamRequest struct {
Branch string `json:"branch"`
}
type MergeUpstreamResponse struct {
MergeStyle string `json:"merge_type"`
}

View File

@ -0,0 +1,17 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// AddCollaboratorOption options when adding a user as a collaborator of a repository
type AddCollaboratorOption struct {
// enum: read,write,admin
Permission *string `json:"permission"`
}
// RepoCollaboratorPermission to get repository permission for a collaborator
type RepoCollaboratorPermission struct {
Permission string `json:"permission"`
RoleName string `json:"role_name"`
User *User `json:"user"`
}

View File

@ -0,0 +1,69 @@
// Copyright 2018 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// Identity for a person's identity like an author or committer
type Identity struct {
Name string `json:"name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"MaxSize(254)"`
}
// 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"`
Verification *PayloadCommitVerification `json:"verification"`
}
// CommitStats is statistics for a RepoCommit
type CommitStats struct {
Total int `json:"total"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
}
// 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"`
Stats *CommitStats `json:"stats"`
}
// 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"`
Status string `json:"status"`
}

View File

@ -0,0 +1,10 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// Compare represents a comparison between two commits.
type Compare struct {
TotalCommits int `json:"total_commits"` // Total number of commits in the comparison.
Commits []*Commit `json:"commits"` // List of commits in the comparison.
}

172
gitea/structs/repo_file.go Normal file
View File

@ -0,0 +1,172 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// 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" binding:"GitRefName;MaxSize(100)"`
// new_branch (optional) will make a new branch from `branch` before creating the file
NewBranchName string `json:"new_branch" binding:"GitRefName;MaxSize(100)"`
// `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
ContentBase64 string `json:"content"`
}
// Branch returns branch name
func (o *CreateFileOptions) Branch() string {
return o.FileOptions.BranchName
}
// 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" binding:"Required"`
}
// Branch returns branch name
func (o *DeleteFileOptions) Branch() string {
return o.FileOptions.BranchName
}
// 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 {
DeleteFileOptions
// content must be base64 encoded
// required: true
ContentBase64 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" binding:"MaxSize(500)"`
}
// Branch returns branch name
func (o *UpdateFileOptions) Branch() string {
return o.FileOptions.BranchName
}
// ChangeFileOperation for creating, updating or deleting a file
type ChangeFileOperation struct {
// indicates what to do with the file
// required: true
// enum: create,update,delete
Operation string `json:"operation" binding:"Required"`
// path to the existing or new file
// required: true
Path string `json:"path" binding:"Required;MaxSize(500)"`
// new or updated file content, must be base64 encoded
ContentBase64 string `json:"content"`
// sha is the SHA for the file that already exists, required for update or delete
SHA string `json:"sha"`
// old path of the file to move
FromPath string `json:"from_path"`
}
// ChangeFilesOptions options for creating, updating or deleting multiple 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 ChangeFilesOptions struct {
FileOptions
// list of file operations
// required: true
Files []*ChangeFileOperation `json:"files" binding:"Required"`
}
// Branch returns branch name
func (o *ChangeFilesOptions) Branch() string {
return o.FileOptions.BranchName
}
// FileOptionInterface provides a unified interface for the different file options
type FileOptionInterface interface {
Branch() string
}
// ApplyDiffPatchFileOptions options for applying a diff patch
// 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 ApplyDiffPatchFileOptions struct {
DeleteFileOptions
// required: true
Content string `json:"content"`
}
// 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"`
LastCommitSHA string `json:"last_commit_sha"`
// `type` will be `file`, `dir`, `symlink`, or `submodule`
Type string `json:"type"`
Size int `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"`
}
// FilesResponse contains information about multiple files from a repo
type FilesResponse struct {
Files []*ContentsResponse `json:"files"`
Commit *FileCommitResponse `json:"commit"`
Verification *PayloadCommitVerification `json:"verification"`
}
// FileDeleteResponse contains information about a repo's file that was deleted
type FileDeleteResponse struct {
Content any `json:"content"` // to be set to nil
Commit *FileCommitResponse `json:"commit"`
Verification *PayloadCommitVerification `json:"verification"`
}

39
gitea/structs/repo_key.go Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// DeployKey a deploy key
type DeployKey struct {
ID int `json:"id"`
KeyID int `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"`
}
// CreateKeyOption options when creating a key
type CreateKeyOption struct {
// Title of the key to add
//
// required: true
// unique: true
Title string `json:"title" binding:"Required"`
// An armored SSH key to add
//
// required: true
// unique: true
Key string `json:"key" binding:"Required"`
// Describe if the key has only read access or read/write
//
// required: false
ReadOnly bool `json:"read_only"`
}

View File

@ -0,0 +1,10 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// Note contains information related to a git note
type Note struct {
Message string `json:"message"`
Commit *Commit `json:"commit"`
}

View File

@ -0,0 +1,18 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// 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"`
}

66
gitea/structs/repo_tag.go Normal file
View File

@ -0,0 +1,66 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import "time"
// 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"`
}
// CreateTagOption options when creating a tag
type CreateTagOption struct {
// required: true
TagName string `json:"tag_name" binding:"Required"`
Message string `json:"message"`
Target string `json:"target"`
}
// TagProtection represents a tag protection
type TagProtection struct {
ID int `json:"id"`
NamePattern string `json:"name_pattern"`
WhitelistUsernames []string `json:"whitelist_usernames"`
WhitelistTeams []string `json:"whitelist_teams"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// CreateTagProtectionOption options for creating a tag protection
type CreateTagProtectionOption struct {
NamePattern string `json:"name_pattern"`
WhitelistUsernames []string `json:"whitelist_usernames"`
WhitelistTeams []string `json:"whitelist_teams"`
}
// EditTagProtectionOption options for editing a tag protection
type EditTagProtectionOption struct {
NamePattern *string `json:"name_pattern"`
WhitelistUsernames []string `json:"whitelist_usernames"`
WhitelistTeams []string `json:"whitelist_teams"`
}

View File

@ -0,0 +1,28 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// TopicResponse for returning topics
type TopicResponse struct {
ID int `json:"id"`
Name string `json:"topic_name"`
RepoCount int `json:"repo_count"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
// TopicName a list of repo topic names
type TopicName struct {
TopicNames []string `json:"topics"`
}
// RepoTopicOptions a collection of repo topic names
type RepoTopicOptions struct {
// list of topic names
Topics []string `json:"topics"`
}

View File

@ -0,0 +1,24 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// GitEntry represents a git tree
type GitEntry struct {
Path string `json:"path"`
Mode string `json:"mode"`
Type string `json:"type"`
Size int `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"`
}

View File

@ -0,0 +1,18 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// WatchInfo represents an API watch status of one repository
type WatchInfo struct {
Subscribed bool `json:"subscribed"`
Ignored bool `json:"ignored"`
Reason any `json:"reason"`
CreatedAt time.Time `json:"created_at"`
URL string `json:"url"`
RepositoryURL string `json:"repository_url"`
}

View File

@ -0,0 +1,46 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// WikiCommit page commit/revision
type WikiCommit struct {
ID string `json:"sha"`
Author *CommitUser `json:"author"`
Committer *CommitUser `json:"commiter"`
Message string `json:"message"`
}
// WikiPage a wiki page
type WikiPage struct {
*WikiPageMetaData
// Page content, base64 encoded
ContentBase64 string `json:"content_base64"`
CommitCount int `json:"commit_count"`
Sidebar string `json:"sidebar"`
Footer string `json:"footer"`
}
// WikiPageMetaData wiki page meta information
type WikiPageMetaData struct {
Title string `json:"title"`
HTMLURL string `json:"html_url"`
SubURL string `json:"sub_url"`
LastCommit *WikiCommit `json:"last_commit"`
}
// CreateWikiPageOptions form for creating wiki
type CreateWikiPageOptions struct {
// page title. leave empty to keep unchanged
Title string `json:"title"`
// content must be base64 encoded
ContentBase64 string `json:"content_base64"`
// optional commit message summarizing the change
Message string `json:"message"`
}
// WikiCommitList commit/revision list
type WikiCommitList struct {
WikiCommits []*WikiCommit `json:"commits"`
Count int `json:"count"`
}

28
gitea/structs/secret.go Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import "time"
// Secret represents a secret
type Secret struct {
// the secret's name
Name string `json:"name"`
// the secret's description
Description string `json:"description"`
Created time.Time `json:"created_at"`
}
// CreateOrUpdateSecretOption options when creating or updating secret
type CreateOrUpdateSecretOption struct {
// Data of the secret to update
//
// required: true
Data string `json:"data" binding:"Required"`
// Description of the secret to update
//
// required: false
Description string `json:"description"`
}

37
gitea/structs/settings.go Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// GeneralRepoSettings contains global repository settings exposed by API
type GeneralRepoSettings 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"`
}
// GeneralUISettings contains global ui settings exposed by API
type GeneralUISettings struct {
DefaultTheme string `json:"default_theme"`
AllowedReactions []string `json:"allowed_reactions"`
CustomEmojis []string `json:"custom_emojis"`
}
// GeneralAPISettings contains global api settings exposed by it
type GeneralAPISettings struct {
MaxResponseItems int `json:"max_response_items"`
DefaultPagingNum int `json:"default_paging_num"`
DefaultGitTreesPerPage int `json:"default_git_trees_per_page"`
DefaultMaxBlobSize int `json:"default_max_blob_size"`
}
// GeneralAttachmentSettings contains global Attachment settings exposed by API
type GeneralAttachmentSettings struct {
Enabled bool `json:"enabled"`
AllowedTypes string `json:"allowed_types"`
MaxSize int `json:"max_size"`
MaxFiles int `json:"max_files"`
}

40
gitea/structs/status.go Normal file
View File

@ -0,0 +1,40 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// CommitStatus holds a single status of a single Commit
type CommitStatus struct {
ID int `json:"id"`
State CommitStatusState `json:"status"`
TargetURL string `json:"target_url"`
Description string `json:"description"`
URL string `json:"url"`
Context string `json:"context"`
Creator *User `json:"creator"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// CombinedStatus holds the combined state of several statuses for a single commit
type CombinedStatus struct {
State CommitStatusState `json:"state"`
SHA string `json:"sha"`
TotalCount int `json:"total_count"`
Statuses []*CommitStatus `json:"statuses"`
Repository *Repository `json:"repository"`
CommitURL string `json:"commit_url"`
URL string `json:"url"`
}
// CreateStatusOption holds the information needed to create a new CommitStatus for a Commit
type CreateStatusOption struct {
State CommitStatusState `json:"state"`
TargetURL string `json:"target_url"`
Description string `json:"description"`
Context string `json:"context"`
}

30
gitea/structs/task.go Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2019 Gitea. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// TaskType defines task type
type TaskType int
const TaskTypeMigrateRepo TaskType = iota // migrate repository from external or local disk
// Name returns the task type name
func (taskType TaskType) Name() string {
switch taskType {
case TaskTypeMigrateRepo:
return "Migrate Repository"
}
return ""
}
// TaskStatus defines task status
type TaskStatus int
// enumerate all the kinds of task status
const (
TaskStatusQueued TaskStatus = iota // 0 task is queued
TaskStatusRunning // 1 task is running
TaskStatusStopped // 2 task is stopped (never used)
TaskStatusFailed // 3 task is failed
TaskStatusFinished // 4 task is finished
)

130
gitea/structs/user.go Normal file
View File

@ -0,0 +1,130 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
"code.gitea.io/gitea/modules/json"
)
// User represents a user
type User struct {
// the user's id
ID int `json:"id"`
// the user's username
UserName string `json:"login"`
// the user's authentication sign-in name.
// default: empty
LoginName string `json:"login_name"`
// The ID of the user's Authentication Source
SourceID int `json:"source_id"`
// 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"`
// URL to the user's gitea page
HTMLURL string `json:"html_url"`
// User locale
Language string `json:"language"`
// Is the user an administrator
IsAdmin bool `json:"is_admin"`
LastLogin time.Time `json:"last_login,omitempty"`
Created time.Time `json:"created,omitempty"`
// 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: public, limited, private
Visibility string `json:"visibility"`
// user counts
Followers int `json:"followers_count"`
Following int `json:"following_count"`
StarredRepos int `json:"starred_repos_count"`
}
// MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility
func (u User) MarshalJSON() ([]byte, error) {
// Re-declaring User to avoid recursion
type shadow User
return json.Marshal(struct {
shadow
CompatUserName string `json:"username"`
}{shadow(u), u.UserName})
}
// 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" binding:"MaxSize(100)"`
Website *string `json:"website" binding:"OmitEmpty;ValidUrl;MaxSize(255)"`
Description *string `json:"description" binding:"MaxSize(255)"`
Location *string `json:"location" binding:"MaxSize(50)"`
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"`
}
// RenameUserOption options when renaming a user
type RenameUserOption struct {
// New username for this user. This name cannot be in use yet by any other user.
//
// required: true
// unique: true
NewName string `json:"new_username" binding:"Required"`
}
// UpdateUserAvatarUserOption options when updating the user avatar
type UpdateUserAvatarOption struct {
// image must be base64 encoded
Image string `json:"image" binding:"Required"`
}
// Badge represents a user badge
type Badge struct {
ID int `json:"id"`
Slug string `json:"slug"`
Description string `json:"description"`
ImageURL string `json:"image_url"`
}
// UserBadge represents a user badge
type UserBadge struct {
ID int `json:"id"`
BadgeID int `json:"badge_id"`
UserID int `json:"user_id"`
}
// UserBadgeOption options for link between users and badges
type UserBadgeOption struct {
// example: ["badge1","badge2"]
BadgeSlugs []string `json:"badge_slugs" binding:"Required"`
}

51
gitea/structs/user_app.go Normal file
View File

@ -0,0 +1,51 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// AccessToken represents an API access token.
type AccessToken struct {
ID int `json:"id"`
Name string `json:"name"`
Token string `json:"sha1"`
TokenLastEight string `json:"token_last_eight"`
Scopes []string `json:"scopes"`
}
// AccessTokenList represents a list of API access token.
type AccessTokenList []*AccessToken
// CreateAccessTokenOption options when create access token
type CreateAccessTokenOption struct {
// required: true
Name string `json:"name" binding:"Required"`
Scopes []string `json:"scopes"`
}
// CreateOAuth2ApplicationOptions holds options to create an oauth2 application
type CreateOAuth2ApplicationOptions struct {
Name string `json:"name" binding:"Required"`
ConfidentialClient bool `json:"confidential_client"`
SkipSecondaryAuthorization bool `json:"skip_secondary_authorization"`
RedirectURIs []string `json:"redirect_uris" binding:"Required"`
}
// OAuth2Application represents an OAuth2 application.
type OAuth2Application struct {
ID int `json:"id"`
Name string `json:"name"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
ConfidentialClient bool `json:"confidential_client"`
SkipSecondaryAuthorization bool `json:"skip_secondary_authorization"`
RedirectURIs []string `json:"redirect_uris"`
Created time.Time `json:"created"`
}
// OAuth2ApplicationList represents a list of OAuth2 applications.
type OAuth2ApplicationList []*OAuth2Application

View File

@ -0,0 +1,26 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// Email an email address belonging to a user
type Email struct {
Email string `json:"email"`
Verified bool `json:"verified"`
Primary bool `json:"primary"`
UserID int `json:"user_id"`
UserName string `json:"username"`
}
// CreateEmailOption options when creating email addresses
type CreateEmailOption struct {
// email addresses to add
Emails []string `json:"emails"`
}
// DeleteEmailOption options when deleting email addresses
type DeleteEmailOption struct {
// email addresses to delete
Emails []string `json:"emails"`
}

View File

@ -0,0 +1,50 @@
// Copyright 2017 Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// GPGKey a user GPG key to sign commit and tag in repository
type GPGKey struct {
ID int `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"`
Verified bool `json:"verified"`
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"`
}
// CreateGPGKeyOption options create user GPG key
type CreateGPGKeyOption struct {
// An armored GPG key to add
//
// required: true
// unique: true
ArmoredKey string `json:"armored_public_key" binding:"Required"`
Signature string `json:"armored_signature,omitempty"`
}
// VerifyGPGKeyOption options verifies user GPG key
type VerifyGPGKeyOption struct {
// An Signature for a GPG key token
//
// required: true
KeyID string `json:"key_id" binding:"Required"`
Signature string `json:"armored_signature" binding:"Required"`
}

21
gitea/structs/user_key.go Normal file
View File

@ -0,0 +1,21 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
import (
"time"
)
// PublicKey publickey is a user key to push code to repository
type PublicKey struct {
ID int `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"`
}

46
gitea/structs/variable.go Normal file
View File

@ -0,0 +1,46 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// CreateVariableOption the option when creating variable
type CreateVariableOption struct {
// Value of the variable to create
//
// required: true
Value string `json:"value" binding:"Required"`
// Description of the variable to create
//
// required: false
Description string `json:"description"`
}
// UpdateVariableOption the option when updating variable
type UpdateVariableOption struct {
// New name for the variable. If the field is empty, the variable name won't be updated.
Name string `json:"name"`
// Value of the variable to update
//
// required: true
Value string `json:"value" binding:"Required"`
// Description of the variable to update
//
// required: false
Description string `json:"description"`
}
// ActionVariable return value of the query API
type ActionVariable struct {
// the owner to which the variable belongs
OwnerID int `json:"owner_id"`
// the repository to which the variable belongs
RepoID int `json:"repo_id"`
// the name of the variable
Name string `json:"name"`
// the value of the variable
Data string `json:"data"`
// the description of the variable
Description string `json:"description"`
}

View File

@ -0,0 +1,58 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package structs
// VisibleType defines the visibility of user and org
type VisibleType int
const (
// VisibleTypePublic Visible for everyone
VisibleTypePublic VisibleType = iota
// VisibleTypeLimited Visible for every connected user
VisibleTypeLimited
// VisibleTypePrivate Visible only for self or admin user
VisibleTypePrivate
)
// VisibilityModes is a map of Visibility types
var VisibilityModes = map[string]VisibleType{
"public": VisibleTypePublic,
"limited": VisibleTypeLimited,
"private": VisibleTypePrivate,
}
// IsPublic returns true if VisibleType is public
func (vt VisibleType) IsPublic() bool {
return vt == VisibleTypePublic
}
// IsLimited returns true if VisibleType is limited
func (vt VisibleType) IsLimited() bool {
return vt == VisibleTypeLimited
}
// IsPrivate returns true if VisibleType is private
func (vt VisibleType) IsPrivate() bool {
return vt == VisibleTypePrivate
}
// VisibilityString provides the mode string of the visibility type (public, limited, private)
func (vt VisibleType) String() string {
for k, v := range VisibilityModes {
if vt == v {
return k
}
}
return ""
}
// ExtractKeysFromMapString provides a slice of keys from map
func ExtractKeysFromMapString(in map[string]VisibleType) (keys []string) {
for k := range in {
keys = append(keys, k)
}
return keys
}

25
gitea/user.go Normal file
View File

@ -0,0 +1,25 @@
package gitea
import (
"net/url"
"path"
gitea_api "sirherobrine23.com.br/go-bds/request/gitea/structs"
"sirherobrine23.com.br/go-bds/request/v2"
)
// Finder user by username
func (client Gitea) User(username string) (*gitea_api.User, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*gitea_api.User](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "users", url.PathEscape(username))}).String(), reqOptions)
return res, err
}
// Return current token User
func (client Gitea) Whoami() (*gitea_api.User, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*gitea_api.User](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "v1/user")}).String(), reqOptions)
return res, err
}

69
github/apipaginator.go Normal file
View File

@ -0,0 +1,69 @@
package github
import (
"net/http"
"net/url"
"strconv"
"strings"
)
type githubPagination struct {
NextPage, PrevPage, FirstPage, LastPage int
NextPageToken, Cursor, Before, After string
}
func parsePaginator(he http.Header) *githubPagination {
r := &githubPagination{}
if links, ok := he["Link"]; ok && len(links) > 0 {
for link := range strings.SplitSeq(links[0], ",") {
segments := strings.Split(strings.TrimSpace(link), ";")
if len(segments) < 2 {
continue
}
if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") {
continue
}
url, err := url.Parse(segments[0][1 : len(segments[0])-1])
if err != nil {
continue
}
q := url.Query()
if cursor := q.Get("cursor"); cursor != "" {
for _, segment := range segments[1:] {
switch strings.TrimSpace(segment) {
case `rel="next"`:
r.Cursor = cursor
}
}
continue
}
page := q.Get("page")
since := q.Get("since")
before := q.Get("before")
after := q.Get("after")
if page == "" && before == "" && after == "" && since == "" {
continue
}
if since != "" && page == "" {
page = since
}
for _, segment := range segments[1:] {
switch strings.TrimSpace(segment) {
case `rel="next"`:
if r.NextPage, err = strconv.Atoi(page); err != nil {
r.NextPageToken = page
}
r.After = after
case `rel="prev"`:
r.PrevPage, _ = strconv.Atoi(page)
r.Before = before
case `rel="first"`:
r.FirstPage, _ = strconv.Atoi(page)
case `rel="last"`:
r.LastPage, _ = strconv.Atoi(page)
}
}
}
}
return r
}

103
github/github.go Normal file
View File

@ -0,0 +1,103 @@
// Client to Github APIs
package github
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"
"sirherobrine23.com.br/go-bds/request/v2"
)
var (
GithubAPI = &url.URL{Scheme: "https", Host: "api.github.com", Path: "/"} // Defaut github api
ErrToken error = errors.New("require Token to request")
err500 = request.RequestStatusFunction(func(res *http.Response) (*http.Response, error) {
buffLog, _ := io.ReadAll(res.Body)
if res.Body != nil {
res.Body.Close()
}
if len(buffLog) == 0 {
buffLog = []byte("not body response")
}
return nil, fmt.Errorf("cannot process request (%s), github api is down: %s", res.Request.URL.String(), buffLog)
})
processCodes = request.MapCode{
500: err500,
501: err500,
401: func(res *http.Response) (*http.Response, error) {
if res.Body != nil {
res.Body.Close()
}
return nil, ErrToken
},
403: func(res *http.Response) (*http.Response, error) {
if res.Body != nil {
res.Body.Close()
}
return nil, errors.New("cannot process request, authorization or not have permission")
},
429: func(res *http.Response) (*http.Response, error) {
if res.Body != nil {
res.Body.Close()
}
// x-ratelimit-reset
if window, err := strconv.Atoi(res.Header.Get("x-ratelimit-reset")); err == nil {
<-time.After(time.Duration(window))
}
return request.ReRequest(res)
},
}
)
// Create new Github Client with Github.com API host
func NewClient(Username, Repository, Token string) *Github {
return &Github{
Host: GithubAPI,
Repository: Repository,
Username: Username,
Token: Token,
}
}
// Create new Github Client
func NewClientHost(apiHost, Username, Repository, Token string) (*Github, error) {
hostUrl, err := url.Parse(apiHost)
if err != nil {
return nil, err
}
return &Github{
Host: hostUrl,
Repository: Repository,
Username: Username,
Token: Token,
}, nil
}
// Basic client to Github APIs
type Github struct {
Host *url.URL // Github API host
Token string // Github Token
// User and Repository name
Username, Repository string
}
// Return escapated Owner+/+Repository
func (client Github) repoPath() string {
return fmt.Sprintf("%s/%s", url.PathEscape(client.Username), url.PathEscape(client.Repository))
}
// Set token to header
func (client Github) authHeader(header *request.Header) {
if client.Token != "" {
(*header)["Authorization"] = fmt.Sprintf("Bearer %s", client.Token)
}
}

194
github/releases.go Normal file
View File

@ -0,0 +1,194 @@
package github
import (
"fmt"
"io"
"iter"
"net/http"
"net/url"
"path"
"strconv"
"time"
"sirherobrine23.com.br/go-bds/request/v2"
)
// File assert
type ReleaseAsset struct {
URL string `json:"url"`
ID int `json:"id"`
NodeID string `json:"node_id"`
Name string `json:"name"`
Label string `json:"label"`
Uploader *User `json:"uploader"`
ContentType string `json:"content_type"`
State string `json:"state"`
Size int `json:"size"`
DownloadCount int `json:"download_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
BrowserDownloadURL string `json:"browser_download_url"`
}
// Release
type Release struct {
ID int `json:"id"`
TagName string `json:"tag_name"`
Name string `json:"name"`
URL string `json:"url"`
AssetsURL string `json:"assets_url"`
UploadURL string `json:"upload_url"`
HTMLURL string `json:"html_url"`
NodeID string `json:"node_id"`
TargetCommitish string `json:"target_commitish"`
Body string `json:"body"`
Draft bool `json:"draft"`
Prerelease bool `json:"prerelease"`
CreatedAt time.Time `json:"created_at"`
PublishedAt time.Time `json:"published_at"`
TarballURL string `json:"tarball_url"`
ZipballURL string `json:"zipball_url"`
MentionsCount int `json:"mentions_count,omitempty"`
Author *User `json:"author"`
Assets []*ReleaseAsset `json:"assets"`
Reactions struct {
URL string `json:"url"`
TotalCount int `json:"total_count"`
PlusOne int `json:"+1"`
LessOne int `json:"-1"`
Laugh int `json:"laugh"`
Hooray int `json:"hooray"`
Confused int `json:"confused"`
Heart int `json:"heart"`
Rocket int `json:"rocket"`
Eyes int `json:"eyes"`
} `json:"reactions"`
}
// Get release by tag name
func (client Github) ReleaseTag(tagName string) (*Release, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases/tags", url.PathEscape(tagName))}).String(), reqOptions)
return res, err
}
// Get release by ID
func (client Github) Release(id int) (*Release, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*Release](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases", strconv.Itoa(id))}).String(), reqOptions)
return res, err
}
// Return all release from API
func (client Github) ReleaseSeq() iter.Seq2[*Release, error] {
releases, res, err := []*Release{}, (*http.Response)(nil), error(nil)
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
return func(yield func(*Release, error) bool) {
requestUrl := client.Host.ResolveReference(&url.URL{RawQuery: "per_page=100", Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases")}).String()
for requestUrl != "" {
if len(releases) == 0 {
if releases, res, err = request.JSON[[]*Release](requestUrl, reqOptions); res != nil {
requestUrl = parsePaginator(res.Header).NextPageToken
} else {
requestUrl = ""
}
}
if err != nil {
yield(nil, err)
return
}
for len(releases) > 0 {
if !yield(releases[0], nil) {
return
}
releases = releases[1:]
}
}
}
}
// List all release Assets in [iter.Seq2]
func (client Github) AssetsSeq(releaseID int) iter.Seq2[*ReleaseAsset, error] {
asserts, res, err := []*ReleaseAsset{}, (*http.Response)(nil), error(nil)
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
return func(yield func(*ReleaseAsset, error) bool) {
requestUrl := client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")}).String()
for requestUrl != "" {
if len(asserts) == 0 {
if asserts, res, err = request.JSON[[]*ReleaseAsset](requestUrl, reqOptions); res != nil {
requestUrl = parsePaginator(res.Header).NextPageToken
} else {
requestUrl = ""
}
}
if err != nil {
yield(nil, err)
return
}
for len(asserts) > 0 {
if !yield(asserts[0], nil) {
return
}
asserts = asserts[1:]
}
}
}
}
// Return all release in to slice
func (client Github) AllReleases() ([]*Release, error) {
allRels := []*Release{}
for release, err := range client.ReleaseSeq() {
if err != nil {
return nil, err
}
allRels = append(allRels, release)
}
return allRels, nil
}
// List all release Assets in to slice
func (client Github) AllAssets(releaseID int) ([]*ReleaseAsset, error) {
asserts := []*ReleaseAsset{}
for assert, err := range client.AssetsSeq(releaseID) {
if err != nil {
return nil, err
}
asserts = append(asserts, assert)
}
return asserts, nil
}
// Delete assert file from Release
func (client Github) DeleteAsset(assetID int) error {
reqOptions := &request.Options{Method: "DELETE", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, err := request.MakeRequestWithStatus(client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases/assets", strconv.Itoa(assetID))}), reqOptions)
res.Body.Close()
return err
}
// Upload file to Release
func (client Github) UploadAsset(releaseID int, name string, file io.Reader) (*ReleaseAsset, error) {
reqOptions := &request.Options{
Method: "POST",
Body: file,
Header: request.Header{"Content-Type": "application/octet-stream"},
CodeProcess: processCodes.Extends(request.MapCode{
201: func(res *http.Response) (*http.Response, error) { return res, nil },
422: func(res *http.Response) (*http.Response, error) {
return nil, fmt.Errorf("same filename exists in release: %s", name)
},
}),
}
client.authHeader(&reqOptions.Header)
requestUrl := client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "repos", client.repoPath(), "releases", strconv.Itoa(releaseID), "assets")})
requestUrl.RawQuery = fmt.Sprintf("name=%s", url.QueryEscape(name))
fileInfo, _, err := request.JSON[*ReleaseAsset](requestUrl.String(), reqOptions)
return fileInfo, err
}

76
github/users.go Normal file
View File

@ -0,0 +1,76 @@
package github
import (
"net/url"
"path"
"time"
"sirherobrine23.com.br/go-bds/request/v2"
)
// User info
type User struct {
Login string `json:"login"`
ID int `json:"id"`
NodeID string `json:"node_id"`
AvatarURL string `json:"avatar_url"`
GravatarID string `json:"gravatar_id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
FollowersURL string `json:"followers_url"`
FollowingURL string `json:"following_url"`
GistsURL string `json:"gists_url"`
StarredURL string `json:"starred_url"`
SubscriptionsURL string `json:"subscriptions_url"`
OrganizationsURL string `json:"organizations_url"`
ReposURL string `json:"repos_url"`
EventsURL string `json:"events_url"`
ReceivedEventsURL string `json:"received_events_url"`
Type string `json:"type"`
SiteAdmin bool `json:"site_admin"`
Name string `json:"name"`
Company string `json:"company"`
Blog string `json:"blog"`
Location string `json:"location"`
Email string `json:"email"`
Hireable bool `json:"hireable"`
Bio string `json:"bio"`
TwitterUsername string `json:"twitter_username"`
PublicRepos int `json:"public_repos"`
PublicGists int `json:"public_gists"`
Followers int `json:"followers"`
Following int `json:"following"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
PrivateGists int `json:"private_gists"`
TotalPrivateRepos int `json:"total_private_repos"`
OwnedPrivateRepos int `json:"owned_private_repos"`
DiskUsage int `json:"disk_usage"`
Collaborators int `json:"collaborators"`
TwoFactorAuthentication bool `json:"two_factor_authentication"`
Plan struct {
Name string `json:"name"`
Space int `json:"space"`
PrivateRepos int `json:"private_repos"`
Collaborators int `json:"collaborators"`
} `json:"plan"`
}
// Finder user by username
func (client Github) User(username string) (*User, error) {
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*User](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "users", url.PathEscape(username))}).String(), reqOptions)
return res, err
}
// Return current token User
func (client Github) Whoami() (*User, error) {
if client.Token == "" {
return nil, ErrToken
}
reqOptions := &request.Options{Method: "GET", Header: request.Header{}, CodeProcess: processCodes}
client.authHeader(&reqOptions.Header)
res, _, err := request.JSON[*User](client.Host.ResolveReference(&url.URL{Path: path.Join(client.Host.Path, "user")}).String(), reqOptions)
return res, err
}

8
go.mod
View File

@ -3,12 +3,20 @@ module sirherobrine23.com.br/go-bds/request
go 1.24
require (
code.gitea.io/gitea v1.23.6
github.com/PuerkitoBio/goquery v1.10.2
github.com/klauspost/compress v1.18.0
github.com/stretchr/testify v1.10.0
github.com/ulikunitz/xz v0.5.12
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
golang.org/x/net v0.37.0 // indirect
)

29
go.sum
View File

@ -1,10 +1,31 @@
code.gitea.io/gitea v1.23.6 h1:4MI1moqMFN+QrnOu9/souwwibrPdVKsN7MRkgKhAGsk=
code.gitea.io/gitea v1.23.6/go.mod h1:DHD2Odz4ACaTm0b2ju+zyljlzXO7O3ibwZwAwBFFM7E=
github.com/PuerkitoBio/goquery v1.10.2 h1:7fh2BdHcG6VFZsK7toXBT/Bh1z5Wmy8Q9MV9HqT2AM8=
github.com/PuerkitoBio/goquery v1.10.2/go.mod h1:0guWGjcLu9AYC7C1GHnpysHy056u9aEkUHwhdnePMCU=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@ -28,8 +49,6 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -50,8 +69,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -77,3 +94,7 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -54,7 +54,7 @@ func (mapCode MapCode) HasCode(httpCode int) bool {
if mapCode == nil {
return false
}
return mapCode[httpCode] != nil && slices.Contains(slices.Collect(maps.Keys(mapCode)), httpCode)
return slices.Contains(slices.Collect(maps.Keys(mapCode)), httpCode) && mapCode[httpCode] != nil
}
// Exists -1 in code
@ -62,6 +62,12 @@ func (mapCode MapCode) HasAll() bool {
return mapCode.HasCode(-1)
}
func (mapCode MapCode) Extends(input MapCode) MapCode {
newMap := maps.Clone(mapCode)
maps.Insert(newMap, maps.All(input))
return newMap
}
// HTTP headers
type Header map[string]string
@ -195,8 +201,14 @@ func MakeRequestWithStatus(Url *url.URL, requestOptions *Options) (*http.Respons
return response, &ResponseError{response, response.Request}
}
// Make new request from old request response
func ReRequest(res *http.Response) (*http.Response, error) {
client := &http.Client{Transport: http.DefaultTransport, CheckRedirect: http.DefaultClient.CheckRedirect, Jar: http.DefaultClient.Jar}
return client.Do(res.Request)
}
// Make request and copy all data from response to [*bytes.Buffer]
func Buffer(Url string, Option *Options) (*bytes.Buffer, *http.Response, error) {
func Buffer(Url string, Option *Options) ([]byte, *http.Response, error) {
res, err := Request(Url, Option)
if err != nil {
return nil, res, err
@ -206,7 +218,7 @@ func Buffer(Url string, Option *Options) (*bytes.Buffer, *http.Response, error)
if err != nil {
return nil, res, err
}
return bytes.NewBuffer(data), res, err
return data, res, err
}
// Make request and save response in Disk