initial commit

This commit is contained in:
Mandresy RABENJAHARISON 2025-07-07 14:15:21 +03:00
commit c6634be696
244 changed files with 37598 additions and 0 deletions

12
Dockerfile Normal file
View File

@ -0,0 +1,12 @@
# Build stage
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/action ./main.go
# Runtime Stage
FROM alpine:3.20
COPY --from=builder /out/action /usr/local/bin/action
ENTRYPOINT ["/usr/local/bin/action"]

33
action.yml Normal file
View File

@ -0,0 +1,33 @@
name: "Create branch in Gitea"
description: "Creates a git branch from an issue and links it back."
author: "Mandresy RABENJAHARISON <mandresyrabenj@gmail.com>"
branding:
icon: git-branch
color: purple
inputs:
ISSUE_LABELS:
description: "Issue Labels."
required: true
ISSUE_NUMBER:
description: "Issue Number."
required: true
ISSUE_TITLE:
description: "Issue Title."
required: true
GITEA_TOKEN:
description: "Gitea Access Token."
required: true
GITEA_URL:
description: "Gitea Instance URL."
required: true
REPO_OWNER:
description: "Git Repository Owner."
required: true
REPO_NAME:
description: "Repository Name."
required: true
runs:
using: "docker"
image: "Dockerfile"

13
go.mod Normal file
View File

@ -0,0 +1,13 @@
module create-branch-action
go 1.23.4
require code.gitea.io/sdk/gitea v0.19.0
require (
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/sys v0.19.0 // indirect
)

34
go.sum Normal file
View File

@ -0,0 +1,34 @@
code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y=
code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

178
main.go Normal file
View File

@ -0,0 +1,178 @@
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
"strconv"
"strings"
"code.gitea.io/sdk/gitea"
)
func main() {
// Créer un logger pour écrire les messages d'erreur
logFile, err := os.OpenFile("action.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("Erreur lors de la création du fichier de log : %v\n", err)
os.Exit(1)
}
defer logFile.Close()
multiWriter := io.MultiWriter(os.Stdout, logFile)
logger := log.New(multiWriter, "", log.LstdFlags)
// Récupérer les variables d'environnement
issueNumberStr := os.Getenv("ISSUE_NUMBER")
issueTitle := os.Getenv("ISSUE_TITLE")
labelsStr := os.Getenv("ISSUE_LABELS")
giteaToken := os.Getenv("GITEA_TOKEN")
giteaAPIURL := os.Getenv("GITEA_URL")
repoOwner := os.Getenv("REPO_OWNER")
repoName := os.Getenv("REPO_NAME")
if issueNumberStr == "" || issueTitle == "" || giteaToken == "" || giteaAPIURL == "" || repoOwner == "" || repoName == "" {
logger.Println("Erreur : certaines variables d'environnement sont manquantes.")
os.Exit(1)
}
// Convertir le numéro de l'issue en int64
issueNumber, err := strconv.ParseInt(issueNumberStr, 10, 64)
if err != nil {
logger.Printf("Erreur lors de la conversion du numéro de l'issue : %v\n", err)
os.Exit(1)
}
// Mapper les labels aux préfixes Git Flow
prefix := "feature"
if labelsStr != "" {
prefix, err = getPrefixFromLabels(labelsStr)
}
if err != nil {
logger.Printf("Erreur lors de la détermination du préfixe : %v\n", err)
os.Exit(1)
}
// Former le nom de la branche au format "prefixe/us-numero"
branchName := fmt.Sprintf("%s/us-%d", prefix, issueNumber)
logger.Printf("Nom de la branche défini : %s\n", branchName)
// Configurer Git
logger.Println("Configuration de Git...")
err = runCommand(logger, "git", "config", "--global", "user.name", "gitea-actions")
if err != nil {
logger.Printf("Erreur lors de la configuration de Git : %v\n", err)
os.Exit(1)
}
err = runCommand(logger, "git", "fetch", "origin")
if err != nil {
logger.Printf("Erreur lors de la mise a jour des references distantes")
os.Exit(1)
}
err = runCommand(logger, "git", "config", "--global", "user.email", "actions@gitea.com")
if err != nil {
logger.Printf("Erreur lors de la configuration de Git : %v\n", err)
os.Exit(1)
}
// Vérifier si la branche existe déjà
logger.Printf("Vérification de l'existence de la branche '%s'...\n", branchName)
output, err := exec.Command("git", "ls-remote", "--heads", "origin", branchName).CombinedOutput()
if err != nil {
logger.Printf("Erreur lors de la vérification de la branche : %v\nSortie : %s\n", err, string(output))
os.Exit(1)
}
branchExists := false
if strings.TrimSpace(string(output)) != "" {
branchExists = true
}
if branchExists {
logger.Printf("La branche '%s' existe déjà. Aucune action n'a été effectuée.\n", branchName)
} else {
// Créer et pousser la branche
logger.Printf("Création de la branche '%s' à partir de 'dev'.\n", branchName)
err = runCommand(logger, "git", "checkout", "-b", branchName, "origin/develop")
if err != nil {
logger.Printf("Erreur lors de la création de la branche : %v\n", err)
os.Exit(1)
}
err = runCommand(logger, "git", "push", "origin", branchName)
if err != nil {
logger.Printf("Erreur lors du push de la branche : %v\n", err)
os.Exit(1)
}
logger.Printf("Branche '%s' créée et poussée avec succès.\n", branchName)
}
// Attribuer la branche à l'issue via l'API Gitea
logger.Printf("Attribution de la branche '%s' à l'issue #%d.\n", branchName, issueNumber)
// Création du client Gitea
client, err := gitea.NewClient(giteaAPIURL, gitea.SetToken(giteaToken))
if err != nil {
logger.Printf("Erreur lors de la création du client Gitea : %v\n", err)
os.Exit(1)
}
// Préparer les options pour éditer l'issue
editIssueOption := gitea.EditIssueOption{
Ref: &branchName,
}
// Mettre à jour l'issue avec la référence de la branche
_, _, err = client.EditIssue(repoOwner, repoName, issueNumber, editIssueOption)
if err != nil {
logger.Printf("Erreur lors de l'attribution de la branche à l'issue : %v\n", err)
os.Exit(1)
}
logger.Printf("Branche '%s' attribuée à l'issue #%d avec succès.\n", branchName, issueNumber)
}
// Fonction pour mapper les labels aux préfixes
func getPrefixFromLabels(labelsStr string) (string, error) {
// Définir la correspondance label ➔ préfixe
labelPrefixMap := map[string]string{
"enhancement": "feature",
"invalid": "bugfix",
"bug": "hotfix",
}
// Séparer les labels (supposant qu'ils sont séparés par des virgules)
labels := strings.Split(labelsStr, ",")
// Créer un mapping avec des clés en minuscules
labelPrefixMapLower := make(map[string]string)
for key, value := range labelPrefixMap {
keyLower := strings.ToLower(key)
labelPrefixMapLower[keyLower] = value
}
for _, label := range labels {
label = strings.TrimSpace(label)
labelLower := strings.ToLower(label)
fmt.Printf("Label actuel : %s", labelLower)
if prefix, exists := labelPrefixMapLower[labelLower]; exists {
return prefix, nil
}
}
return "feature", nil
}
func runCommand(logger *log.Logger, name string, arg ...string) error {
cmd := exec.Command(name, arg...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
logger.Printf("Exécution de la commande : %s %s\n", name, strings.Join(arg, " "))
return cmd.Run()
}

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

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

47
vendor/code.gitea.io/sdk/gitea/admin_cron.go generated vendored Normal file
View File

@ -0,0 +1,47 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"time"
)
// CronTask represents a Cron task
type CronTask struct {
Name string `json:"name"`
Schedule string `json:"schedule"`
Next time.Time `json:"next"`
Prev time.Time `json:"prev"`
ExecTimes int64 `json:"exec_times"`
}
// ListCronTaskOptions list options for ListCronTasks
type ListCronTaskOptions struct {
ListOptions
}
// ListCronTasks list available cron tasks
func (c *Client) ListCronTasks(opt ListCronTaskOptions) ([]*CronTask, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, nil, err
}
opt.setDefaults()
ct := make([]*CronTask, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/cron?%s", opt.getURLQuery().Encode()), jsonHeader, nil, &ct)
return ct, resp, err
}
// RunCronTasks run a cron task
func (c *Client) RunCronTasks(task string) (*Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, err
}
if err := escapeValidatePathSegments(&task); err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil)
return resp, err
}

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

@ -0,0 +1,39 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// AdminListOrgsOptions options for listing admin's organizations
type AdminListOrgsOptions struct {
ListOptions
}
// AdminListOrgs lists all orgs
func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, *Response, error) {
opt.setDefaults()
orgs := make([]*Organization, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
return orgs, resp, err
}
// AdminCreateOrg create an organization
func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
org := new(Organization)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user), jsonHeader, bytes.NewReader(body), org)
return org, resp, err
}

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

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

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

@ -0,0 +1,130 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// AdminListUsersOptions options for listing admin users
type AdminListUsersOptions struct {
ListOptions
}
// AdminListUsers lists all users
func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, *Response, error) {
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users)
return users, resp, err
}
// CreateUserOption create user options
type CreateUserOption struct {
SourceID int64 `json:"source_id"`
LoginName string `json:"login_name"`
Username string `json:"username"`
FullName string `json:"full_name"`
Email string `json:"email"`
Password string `json:"password"`
MustChangePassword *bool `json:"must_change_password"`
SendNotify bool `json:"send_notify"`
Visibility *VisibleType `json:"visibility"`
}
// Validate the CreateUserOption struct
func (opt CreateUserOption) Validate() error {
if len(opt.Email) == 0 {
return fmt.Errorf("email is empty")
}
if len(opt.Username) == 0 {
return fmt.Errorf("username is empty")
}
return nil
}
// AdminCreateUser create a user
func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, *Response, error) {
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
user := new(User)
resp, err := c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user)
return user, resp, err
}
// EditUserOption edit user options
type EditUserOption struct {
SourceID int64 `json:"source_id"`
LoginName string `json:"login_name"`
Email *string `json:"email"`
FullName *string `json:"full_name"`
Password string `json:"password"`
Description *string `json:"description"`
MustChangePassword *bool `json:"must_change_password"`
Website *string `json:"website"`
Location *string `json:"location"`
Active *bool `json:"active"`
Admin *bool `json:"admin"`
AllowGitHook *bool `json:"allow_git_hook"`
AllowImportLocal *bool `json:"allow_import_local"`
MaxRepoCreation *int `json:"max_repo_creation"`
ProhibitLogin *bool `json:"prohibit_login"`
AllowCreateOrganization *bool `json:"allow_create_organization"`
Restricted *bool `json:"restricted"`
Visibility *VisibleType `json:"visibility"`
}
// AdminEditUser modify user informations
func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body))
return resp, err
}
// AdminDeleteUser delete one user according name
func (c *Client) AdminDeleteUser(user string) (*Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
return resp, err
}
// AdminCreateUserPublicKey adds a public key for the user
func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
key := new(PublicKey)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key)
return key, resp, err
}
// AdminDeleteUserPublicKey deletes a user's public key
func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil)
return resp, err
}

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

@ -0,0 +1,38 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build !windows
package gitea
import (
"fmt"
"net"
"os"
"golang.org/x/crypto/ssh/agent"
)
// hasAgent returns true if the ssh agent is available
func hasAgent() bool {
if _, err := os.Stat(os.Getenv("SSH_AUTH_SOCK")); err != nil {
return false
}
return true
}
// GetAgent returns a ssh agent
func GetAgent() (agent.Agent, error) {
if !hasAgent() {
return nil, fmt.Errorf("no ssh agent available")
}
sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
if err != nil {
return nil, err
}
return agent.NewClient(sshAgent), nil
}

28
vendor/code.gitea.io/sdk/gitea/agent_windows.go generated vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build windows
package gitea
import (
"fmt"
"github.com/davidmz/go-pageant"
"golang.org/x/crypto/ssh/agent"
)
// hasAgent returns true if pageant is available
func hasAgent() bool {
return pageant.Available()
}
// GetAgent returns a ssh agent
func GetAgent() (agent.Agent, error) {
if !hasAgent() {
return nil, fmt.Errorf("no pageant available")
}
return pageant.New(), nil
}

111
vendor/code.gitea.io/sdk/gitea/attachment.go generated vendored Normal file
View File

@ -0,0 +1,111 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea // import "code.gitea.io/sdk/gitea"
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"time"
)
// Attachment a generic attachment
type Attachment struct {
ID int64 `json:"id"`
Name string `json:"name"`
Size int64 `json:"size"`
DownloadCount int64 `json:"download_count"`
Created time.Time `json:"created_at"`
UUID string `json:"uuid"`
DownloadURL string `json:"browser_download_url"`
}
// ListReleaseAttachmentsOptions options for listing release's attachments
type ListReleaseAttachmentsOptions struct {
ListOptions
}
// ListReleaseAttachments list release's attachments
func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
attachments := make([]*Attachment, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/%d/assets?%s", user, repo, release, opt.getURLQuery().Encode()),
nil, nil, &attachments)
return attachments, resp, err
}
// GetReleaseAttachment returns the requested attachment
func (c *Client) GetReleaseAttachment(user, repo string, release, id int64) (*Attachment, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
a := new(Attachment)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id),
nil, nil, &a)
return a, resp, err
}
// CreateReleaseAttachment creates an attachment for the given release
func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
// Write file to body
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("attachment", filename)
if err != nil {
return nil, nil, err
}
if _, err = io.Copy(part, file); err != nil {
return nil, nil, err
}
if err = writer.Close(); err != nil {
return nil, nil, err
}
// Send request
attachment := new(Attachment)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release),
http.Header{"Content-Type": {writer.FormDataContentType()}}, body, &attachment)
return attachment, resp, err
}
// EditAttachmentOptions options for editing attachments
type EditAttachmentOptions struct {
Name string `json:"name"`
}
// EditReleaseAttachment updates the given attachment with the given options
func (c *Client) EditReleaseAttachment(user, repo string, release, attachment int64, form EditAttachmentOptions) (*Attachment, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&form)
if err != nil {
return nil, nil, err
}
attach := new(Attachment)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, attachment), jsonHeader, bytes.NewReader(body), attach)
return attach, resp, err
}
// DeleteReleaseAttachment deletes the given attachment including the uploaded file
func (c *Client) DeleteReleaseAttachment(user, repo string, release, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil)
return resp, err
}

498
vendor/code.gitea.io/sdk/gitea/client.go generated vendored Normal file
View File

@ -0,0 +1,498 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"github.com/hashicorp/go-version"
)
var jsonHeader = http.Header{"content-type": []string{"application/json"}}
// Version return the library version
func Version() string {
return "0.16.0"
}
// Client represents a thread-safe Gitea API client.
type Client struct {
url string
accessToken string
username string
password string
otp string
sudo string
userAgent string
debug bool
httpsigner *HTTPSign
client *http.Client
ctx context.Context
mutex sync.RWMutex
serverVersion *version.Version
getVersionOnce sync.Once
ignoreVersion bool // only set by SetGiteaVersion so don't need a mutex lock
}
// Response represents the gitea response
type Response struct {
*http.Response
FirstPage int
PrevPage int
NextPage int
LastPage int
}
// ClientOption are functions used to init a new client
type ClientOption func(*Client) error
// NewClient initializes and returns a API client.
// Usage of all gitea.Client methods is concurrency-safe.
func NewClient(url string, options ...ClientOption) (*Client, error) {
client := &Client{
url: strings.TrimSuffix(url, "/"),
client: &http.Client{},
ctx: context.Background(),
}
for _, opt := range options {
if err := opt(client); err != nil {
return nil, err
}
}
if err := client.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
if errors.Is(err, &ErrUnknownVersion{}) {
return client, err
}
return nil, err
}
return client, nil
}
// NewClientWithHTTP creates an API client with a custom http client
// Deprecated use SetHTTPClient option
func NewClientWithHTTP(url string, httpClient *http.Client) *Client {
client, _ := NewClient(url, SetHTTPClient(httpClient))
return client
}
// SetHTTPClient is an option for NewClient to set custom http client
func SetHTTPClient(httpClient *http.Client) ClientOption {
return func(client *Client) error {
client.SetHTTPClient(httpClient)
return nil
}
}
// SetHTTPClient replaces default http.Client with user given one.
func (c *Client) SetHTTPClient(client *http.Client) {
c.mutex.Lock()
c.client = client
c.mutex.Unlock()
}
// SetToken is an option for NewClient to set token
func SetToken(token string) ClientOption {
return func(client *Client) error {
client.mutex.Lock()
client.accessToken = token
client.mutex.Unlock()
return nil
}
}
// SetBasicAuth is an option for NewClient to set username and password
func SetBasicAuth(username, password string) ClientOption {
return func(client *Client) error {
client.SetBasicAuth(username, password)
return nil
}
}
// UseSSHCert is an option for NewClient to enable SSH certificate authentication via HTTPSign
// If you want to auth against the ssh-agent you'll need to set a principal, if you want to
// use a file on disk you'll need to specify sshKey.
// If you have an encrypted sshKey you'll need to also set the passphrase.
func UseSSHCert(principal, sshKey, passphrase string) ClientOption {
return func(client *Client) error {
if err := client.checkServerVersionGreaterThanOrEqual(version1_17_0); err != nil {
return err
}
client.mutex.Lock()
defer client.mutex.Unlock()
var err error
client.httpsigner, err = NewHTTPSignWithCert(principal, sshKey, passphrase)
if err != nil {
return err
}
return nil
}
}
// UseSSHPubkey is an option for NewClient to enable SSH pubkey authentication via HTTPSign
// If you want to auth against the ssh-agent you'll need to set a fingerprint, if you want to
// use a file on disk you'll need to specify sshKey.
// If you have an encrypted sshKey you'll need to also set the passphrase.
func UseSSHPubkey(fingerprint, sshKey, passphrase string) ClientOption {
return func(client *Client) error {
if err := client.checkServerVersionGreaterThanOrEqual(version1_17_0); err != nil {
return err
}
client.mutex.Lock()
defer client.mutex.Unlock()
var err error
client.httpsigner, err = NewHTTPSignWithPubkey(fingerprint, sshKey, passphrase)
if err != nil {
return err
}
return nil
}
}
// SetBasicAuth sets username and password
func (c *Client) SetBasicAuth(username, password string) {
c.mutex.Lock()
c.username, c.password = username, password
c.mutex.Unlock()
}
// SetOTP is an option for NewClient to set OTP for 2FA
func SetOTP(otp string) ClientOption {
return func(client *Client) error {
client.SetOTP(otp)
return nil
}
}
// SetOTP sets OTP for 2FA
func (c *Client) SetOTP(otp string) {
c.mutex.Lock()
c.otp = otp
c.mutex.Unlock()
}
// SetContext is an option for NewClient to set the default context
func SetContext(ctx context.Context) ClientOption {
return func(client *Client) error {
client.SetContext(ctx)
return nil
}
}
// SetContext set default context witch is used for http requests
func (c *Client) SetContext(ctx context.Context) {
c.mutex.Lock()
c.ctx = ctx
c.mutex.Unlock()
}
// SetSudo is an option for NewClient to set sudo header
func SetSudo(sudo string) ClientOption {
return func(client *Client) error {
client.SetSudo(sudo)
return nil
}
}
// SetSudo sets username to impersonate.
func (c *Client) SetSudo(sudo string) {
c.mutex.Lock()
c.sudo = sudo
c.mutex.Unlock()
}
// SetUserAgent is an option for NewClient to set user-agent header
func SetUserAgent(userAgent string) ClientOption {
return func(client *Client) error {
client.SetUserAgent(userAgent)
return nil
}
}
// SetUserAgent sets the user-agent to send with every request.
func (c *Client) SetUserAgent(userAgent string) {
c.mutex.Lock()
c.userAgent = userAgent
c.mutex.Unlock()
}
// SetDebugMode is an option for NewClient to enable debug mode
func SetDebugMode() ClientOption {
return func(client *Client) error {
client.mutex.Lock()
client.debug = true
client.mutex.Unlock()
return nil
}
}
func newResponse(r *http.Response) *Response {
response := &Response{Response: r}
response.parseLinkHeader()
return response
}
func (r *Response) parseLinkHeader() {
link := r.Header.Get("Link")
if link == "" {
return
}
links := strings.Split(link, ",")
for _, l := range links {
u, param, ok := strings.Cut(l, ";")
if !ok {
continue
}
u = strings.Trim(u, " <>")
key, value, ok := strings.Cut(strings.TrimSpace(param), "=")
if !ok || key != "rel" {
continue
}
value = strings.Trim(value, "\"")
parsed, err := url.Parse(u)
if err != nil {
continue
}
page := parsed.Query().Get("page")
if page == "" {
continue
}
switch value {
case "first":
r.FirstPage, _ = strconv.Atoi(page)
case "prev":
r.PrevPage, _ = strconv.Atoi(page)
case "next":
r.NextPage, _ = strconv.Atoi(page)
case "last":
r.LastPage, _ = strconv.Atoi(page)
}
}
}
func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *Response, error) {
c.mutex.RLock()
debug := c.debug
if debug {
fmt.Printf("%s: %s\nBody: %v\n", method, c.url+path, body)
}
req, err := http.NewRequestWithContext(c.ctx, method, c.url+path, body)
client := c.client // client ref can change from this point on so safe it
c.mutex.RUnlock()
if err != nil {
return nil, nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if debug {
fmt.Printf("Response: %v\n\n", resp)
}
return data, newResponse(resp), err
}
func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*Response, error) {
c.mutex.RLock()
debug := c.debug
if debug {
var bodyStr string
if body != nil {
bs, _ := io.ReadAll(body)
body = bytes.NewReader(bs)
bodyStr = string(bs)
}
fmt.Printf("%s: %s\nHeader: %v\nBody: %s\n", method, c.url+"/api/v1"+path, header, bodyStr)
}
req, err := http.NewRequestWithContext(c.ctx, method, c.url+"/api/v1"+path, body)
if err != nil {
c.mutex.RUnlock()
return nil, err
}
if len(c.accessToken) != 0 {
req.Header.Set("Authorization", "token "+c.accessToken)
}
if len(c.otp) != 0 {
req.Header.Set("X-GITEA-OTP", c.otp)
}
if len(c.username) != 0 {
req.SetBasicAuth(c.username, c.password)
}
if len(c.sudo) != 0 {
req.Header.Set("Sudo", c.sudo)
}
if len(c.userAgent) != 0 {
req.Header.Set("User-Agent", c.userAgent)
}
client := c.client // client ref can change from this point on so safe it
c.mutex.RUnlock()
for k, v := range header {
req.Header[k] = v
}
if c.httpsigner != nil {
err = c.SignRequest(req)
if err != nil {
return nil, err
}
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if debug {
fmt.Printf("Response: %v\n\n", resp)
}
return newResponse(resp), nil
}
// Converts a response for a HTTP status code indicating an error condition
// (non-2XX) to a well-known error value and response body. For non-problematic
// (2XX) status codes nil will be returned. Note that on a non-2XX response, the
// response body stream will have been read and, hence, is closed on return.
func statusCodeToErr(resp *Response) (body []byte, err error) {
// no error
if resp.StatusCode/100 == 2 {
return nil, nil
}
//
// error: body will be read for details
//
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err)
}
// Try to unmarshal and get an error message
errMap := make(map[string]interface{})
if err = json.Unmarshal(data, &errMap); err != nil {
// when the JSON can't be parsed, data was probably empty or a
// plain string, so we try to return a helpful error anyway
path := resp.Request.URL.Path
method := resp.Request.Method
return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method and '%s' body", resp.StatusCode, path, method, string(data))
}
if msg, ok := errMap["message"]; ok {
return data, fmt.Errorf("%v", msg)
}
// If no error message, at least give status and data
return data, fmt.Errorf("%s: %s", resp.Status, string(data))
}
func (c *Client) getResponseReader(method, path string, header http.Header, body io.Reader) (io.ReadCloser, *Response, error) {
resp, err := c.doRequest(method, path, header, body)
if err != nil {
return nil, resp, err
}
// check for errors
data, err := statusCodeToErr(resp)
if err != nil {
return io.NopCloser(bytes.NewReader(data)), resp, err
}
return resp.Body, resp, nil
}
func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) {
resp, err := c.doRequest(method, path, header, body)
if err != nil {
return nil, resp, err
}
defer resp.Body.Close()
// check for errors
data, err := statusCodeToErr(resp)
if err != nil {
return data, resp, err
}
// success (2XX), read body
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, resp, err
}
return data, resp, nil
}
func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) (*Response, error) {
data, resp, err := c.getResponse(method, path, header, body)
if err != nil {
return resp, err
}
return resp, json.Unmarshal(data, obj)
}
func (c *Client) getStatusCode(method, path string, header http.Header, body io.Reader) (int, *Response, error) {
resp, err := c.doRequest(method, path, header, body)
if err != nil {
return -1, resp, err
}
defer resp.Body.Close()
return resp.StatusCode, resp, nil
}
// pathEscapeSegments escapes segments of a path while not escaping forward slash
func pathEscapeSegments(path string) string {
slice := strings.Split(path, "/")
for index := range slice {
slice[index] = url.PathEscape(slice[index])
}
escapedPath := strings.Join(slice, "/")
return escapedPath
}
// escapeValidatePathSegments is a help function to validate and encode url path segments
func escapeValidatePathSegments(seg ...*string) error {
for i := range seg {
if seg[i] == nil || len(*seg[i]) == 0 {
return fmt.Errorf("path segment [%d] is empty", i)
}
*seg[i] = url.PathEscape(*seg[i])
}
return nil
}

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

@ -0,0 +1,9 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Package gitea implements a client for the Gitea API.
// The version corresponds to the highest supported version
// of the gitea API, but backwards-compatibility is mostly
// given.
package gitea // import "code.gitea.io/sdk/gitea"

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

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

28
vendor/code.gitea.io/sdk/gitea/git_blob.go generated vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
)
// GitBlobResponse represents a git blob
type GitBlobResponse struct {
Content string `json:"content"`
Encoding string `json:"encoding"`
URL string `json:"url"`
SHA string `json:"sha"`
Size int64 `json:"size"`
}
// GetBlob get the blob of a repository file
func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
return nil, nil, err
}
blob := new(GitBlobResponse)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob)
return blob, resp, err
}

71
vendor/code.gitea.io/sdk/gitea/git_hook.go generated vendored Normal file
View File

@ -0,0 +1,71 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// GitHook represents a Git repository hook
type GitHook struct {
Name string `json:"name"`
IsActive bool `json:"is_active"`
Content string `json:"content,omitempty"`
}
// ListRepoGitHooksOptions options for listing repository's githooks
type ListRepoGitHooksOptions struct {
ListOptions
}
// ListRepoGitHooks list all the Git hooks of one repository
func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
hooks := make([]*GitHook, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
return hooks, resp, err
}
// GetRepoGitHook get a Git hook of a repository
func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
return nil, nil, err
}
h := new(GitHook)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h)
return h, resp, err
}
// EditGitHookOption options when modifying one Git hook
type EditGitHookOption struct {
Content string `json:"content"`
}
// EditRepoGitHook modify one Git hook of a repository
func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body))
return resp, err
}
// DeleteRepoGitHook delete one Git hook from a repository
func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil)
return resp, err
}

20
vendor/code.gitea.io/sdk/gitea/helper.go generated vendored Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
// OptionalBool convert a bool to a bool reference
func OptionalBool(v bool) *bool {
return &v
}
// OptionalString convert a string to a string reference
func OptionalString(v string) *string {
return &v
}
// OptionalInt64 convert a int64 to a int64 reference
func OptionalInt64(v int64) *int64 {
return &v
}

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

@ -0,0 +1,241 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Hook a hook is a web hook when one repository changed
type Hook struct {
ID int64 `json:"id"`
Type string `json:"type"`
URL string `json:"-"`
Config map[string]string `json:"config"`
Events []string `json:"events"`
Active bool `json:"active"`
Updated time.Time `json:"updated_at"`
Created time.Time `json:"created_at"`
}
// HookType represent all webhook types gitea currently offer
type HookType string
const (
// HookTypeDingtalk webhook that dingtalk understand
HookTypeDingtalk HookType = "dingtalk"
// HookTypeDiscord webhook that discord understand
HookTypeDiscord HookType = "discord"
// HookTypeGitea webhook that gitea understand
HookTypeGitea HookType = "gitea"
// HookTypeGogs webhook that gogs understand
HookTypeGogs HookType = "gogs"
// HookTypeMsteams webhook that msteams understand
HookTypeMsteams HookType = "msteams"
// HookTypeSlack webhook that slack understand
HookTypeSlack HookType = "slack"
// HookTypeTelegram webhook that telegram understand
HookTypeTelegram HookType = "telegram"
// HookTypeFeishu webhook that feishu understand
HookTypeFeishu HookType = "feishu"
)
// ListHooksOptions options for listing hooks
type ListHooksOptions struct {
ListOptions
}
// ListOrgHooks list all the hooks of one organization
func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
opt.setDefaults()
hooks := make([]*Hook, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks)
return hooks, resp, err
}
// ListMyHooks list all the hooks of the authenticated user
func (c *Client) ListMyHooks(opt ListHooksOptions) ([]*Hook, *Response, error) {
opt.setDefaults()
hooks := make([]*Hook, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/hooks?%s", opt.getURLQuery().Encode()), nil, nil, &hooks)
return hooks, resp, err
}
// ListRepoHooks list all the hooks of one repository
func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
hooks := make([]*Hook, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
return hooks, resp, err
}
// GetOrgHook get a hook of an organization
func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h)
return h, resp, err
}
// GetMyHook get a hook of the authenticated user
func (c *Client) GetMyHook(id int64) (*Hook, *Response, error) {
h := new(Hook)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/hooks/%d", id), nil, nil, h)
return h, resp, err
}
// GetRepoHook get a hook of a repository
func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h)
return h, resp, err
}
// CreateHookOption options when create a hook
type CreateHookOption struct {
Type HookType `json:"type"`
Config map[string]string `json:"config"`
Events []string `json:"events"`
BranchFilter string `json:"branch_filter"`
Active bool `json:"active"`
AuthorizationHeader string `json:"authorization_header"`
}
// Validate the CreateHookOption struct
func (opt CreateHookOption) Validate() error {
if len(opt.Type) == 0 {
return fmt.Errorf("hook type needed")
}
return nil
}
// CreateOrgHook create one hook for an organization, with options
func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/hooks", org), jsonHeader, bytes.NewReader(body), h)
return h, resp, err
}
// CreateMyHook create one hook for the authenticated user, with options
func (c *Client) CreateMyHook(opt CreateHookOption) (*Hook, *Response, error) {
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := c.getParsedResponse("POST", "/user/hooks", jsonHeader, bytes.NewReader(body), h)
return h, resp, err
}
// CreateRepoHook create one hook for a repository, with options
func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h)
return h, resp, err
}
// EditHookOption options when modify one hook
type EditHookOption struct {
Config map[string]string `json:"config"`
Events []string `json:"events"`
BranchFilter string `json:"branch_filter"`
Active *bool `json:"active"`
AuthorizationHeader string `json:"authorization_header"`
}
// EditOrgHook modify one hook of an organization, with hook id and options
func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body))
return resp, err
}
// EditMyHook modify one hook of the authenticated user, with hook id and options
func (c *Client) EditMyHook(id int64, opt EditHookOption) (*Response, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/user/hooks/%d", id), jsonHeader, bytes.NewReader(body))
return resp, err
}
// EditRepoHook modify one hook of a repository, with hook id and options
func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body))
return resp, err
}
// DeleteOrgHook delete one hook from an organization, with hook id
func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil)
return resp, err
}
// DeleteMyHook delete one hook from the authenticated user, with hook id
func (c *Client) DeleteMyHook(id int64) (*Response, error) {
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/hooks/%d", id), nil, nil)
return resp, err
}
// DeleteRepoHook delete one hook from a repository, with hook id
func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
return resp, err
}

59
vendor/code.gitea.io/sdk/gitea/hook_validate.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"io"
"net/http"
)
// VerifyWebhookSignature verifies that a payload matches the X-Gitea-Signature based on a secret
func VerifyWebhookSignature(secret, expected string, payload []byte) (bool, error) {
hash := hmac.New(sha256.New, []byte(secret))
if _, err := hash.Write(payload); err != nil {
return false, err
}
expectedSum, err := hex.DecodeString(expected)
if err != nil {
return false, err
}
return hmac.Equal(hash.Sum(nil), expectedSum), nil
}
// VerifyWebhookSignatureMiddleware is a http.Handler for verifying X-Gitea-Signature on incoming webhooks
func VerifyWebhookSignatureMiddleware(secret string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var b bytes.Buffer
if _, err := io.Copy(&b, r.Body); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
expected := r.Header.Get("X-Gitea-Signature")
if expected == "" {
http.Error(w, "no signature found", http.StatusBadRequest)
return
}
ok, err := VerifyWebhookSignature(secret, expected, b.Bytes())
if err != nil {
http.Error(w, err.Error(), http.StatusUnauthorized)
return
}
if !ok {
http.Error(w, "invalid payload", http.StatusUnauthorized)
return
}
r.Body = io.NopCloser(&b)
next.ServeHTTP(w, r)
})
}
}

253
vendor/code.gitea.io/sdk/gitea/httpsign.go generated vendored Normal file
View File

@ -0,0 +1,253 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"crypto"
"encoding/base64"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
"github.com/go-fed/httpsig"
"golang.org/x/crypto/ssh"
)
// HTTPSign contains the signer used for signing requests
type HTTPSign struct {
ssh.Signer
cert bool
}
// HTTPSignConfig contains the configuration for creating a HTTPSign
type HTTPSignConfig struct {
fingerprint string
principal string
pubkey bool
cert bool
sshKey string
passphrase string
}
// NewHTTPSignWithPubkey can be used to create a HTTPSign with a public key
// if no fingerprint is specified it returns the first public key found
func NewHTTPSignWithPubkey(fingerprint, sshKey, passphrase string) (*HTTPSign, error) {
return newHTTPSign(&HTTPSignConfig{
fingerprint: fingerprint,
pubkey: true,
sshKey: sshKey,
passphrase: passphrase,
})
}
// NewHTTPSignWithCert can be used to create a HTTPSign with a certificate
// if no principal is specified it returns the first certificate found
func NewHTTPSignWithCert(principal, sshKey, passphrase string) (*HTTPSign, error) {
return newHTTPSign(&HTTPSignConfig{
principal: principal,
cert: true,
sshKey: sshKey,
passphrase: passphrase,
})
}
// NewHTTPSign returns a new HTTPSign
// It will check the ssh-agent or a local file is config.sshKey is set.
// Depending on the configuration it will either use a certificate or a public key
func newHTTPSign(config *HTTPSignConfig) (*HTTPSign, error) {
var signer ssh.Signer
if config.sshKey != "" {
priv, err := os.ReadFile(config.sshKey)
if err != nil {
return nil, err
}
if config.passphrase == "" {
signer, err = ssh.ParsePrivateKey(priv)
if err != nil {
return nil, err
}
} else {
signer, err = ssh.ParsePrivateKeyWithPassphrase(priv, []byte(config.passphrase))
if err != nil {
return nil, err
}
}
if config.cert {
certbytes, err := os.ReadFile(config.sshKey + "-cert.pub")
if err != nil {
return nil, err
}
pub, _, _, _, err := ssh.ParseAuthorizedKey(certbytes)
if err != nil {
return nil, err
}
cert, ok := pub.(*ssh.Certificate)
if !ok {
return nil, fmt.Errorf("failed to parse certificate")
}
signer, err = ssh.NewCertSigner(cert, signer)
if err != nil {
return nil, err
}
}
} else {
// if no sshKey is specified, check if we have a ssh-agent and use it
agent, err := GetAgent()
if err != nil {
return nil, err
}
signers, err := agent.Signers()
if err != nil {
return nil, err
}
if len(signers) == 0 {
return nil, fmt.Errorf("no signers found")
}
if config.cert {
signer = findCertSigner(signers, config.principal)
if signer == nil {
return nil, fmt.Errorf("no certificate found for %s", config.principal)
}
}
if config.pubkey {
signer = findPubkeySigner(signers, config.fingerprint)
if signer == nil {
return nil, fmt.Errorf("no public key found for %s", config.fingerprint)
}
}
}
return &HTTPSign{
Signer: signer,
cert: config.cert,
}, nil
}
// SignRequest signs a HTTP request
func (c *Client) SignRequest(r *http.Request) error {
var contents []byte
headersToSign := []string{httpsig.RequestTarget, "(created)", "(expires)"}
if c.httpsigner.cert {
// add our certificate to the headers to sign
pubkey, _ := ssh.ParsePublicKey(c.httpsigner.Signer.PublicKey().Marshal())
if cert, ok := pubkey.(*ssh.Certificate); ok {
certString := base64.RawStdEncoding.EncodeToString(cert.Marshal())
r.Header.Add("x-ssh-certificate", certString)
headersToSign = append(headersToSign, "x-ssh-certificate")
} else {
return fmt.Errorf("no ssh certificate found")
}
}
// if we have a body, the Digest header will be added and we'll include this also in
// our signature.
if r.Body != nil {
body, err := r.GetBody()
if err != nil {
return fmt.Errorf("getBody() failed: %s", err)
}
contents, err = io.ReadAll(body)
if err != nil {
return fmt.Errorf("failed reading body: %s", err)
}
headersToSign = append(headersToSign, "Digest")
}
// create a signer for the request and headers, the signature will be valid for 10 seconds
signer, _, err := httpsig.NewSSHSigner(c.httpsigner.Signer, httpsig.DigestSha512, headersToSign, httpsig.Signature, 10)
if err != nil {
return fmt.Errorf("httpsig.NewSSHSigner failed: %s", err)
}
// sign the request, use the fingerprint if we don't have a certificate
keyID := "gitea"
if !c.httpsigner.cert {
keyID = ssh.FingerprintSHA256(c.httpsigner.Signer.PublicKey())
}
err = signer.SignRequest(keyID, r, contents)
if err != nil {
return fmt.Errorf("httpsig.Signrequest failed: %s", err)
}
return nil
}
// findCertSigner returns the Signer containing a valid certificate
// if no principal is specified it returns the first certificate found
func findCertSigner(sshsigners []ssh.Signer, principal string) ssh.Signer {
for _, s := range sshsigners {
// Check if the key is a certificate
if !strings.Contains(s.PublicKey().Type(), "cert-v01@openssh.com") {
continue
}
// convert the ssh.Signer to a ssh.Certificate
mpubkey, _ := ssh.ParsePublicKey(s.PublicKey().Marshal())
cryptopub := mpubkey.(crypto.PublicKey)
cert := cryptopub.(*ssh.Certificate)
t := time.Unix(int64(cert.ValidBefore), 0)
// make sure the certificate is at least 10 seconds valid
if time.Until(t) <= time.Second*10 {
continue
}
if principal == "" {
return s
}
for _, p := range cert.ValidPrincipals {
if p == principal {
return s
}
}
}
return nil
}
// findPubkeySigner returns the Signer containing a valid public key
// if no fingerprint is specified it returns the first public key found
func findPubkeySigner(sshsigners []ssh.Signer, fingerprint string) ssh.Signer {
for _, s := range sshsigners {
// Check if the key is a certificate
if strings.Contains(s.PublicKey().Type(), "cert-v01@openssh.com") {
continue
}
if fingerprint == "" {
return s
}
if strings.TrimSpace(string(ssh.MarshalAuthorizedKey(s.PublicKey()))) == fingerprint {
return s
}
if ssh.FingerprintSHA256(s.PublicKey()) == fingerprint {
return s
}
}
return nil
}

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

@ -0,0 +1,309 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
)
// PullRequestMeta PR info if an issue is a PR
type PullRequestMeta struct {
HasMerged bool `json:"merged"`
Merged *time.Time `json:"merged_at"`
}
// RepositoryMeta basic repository information
type RepositoryMeta struct {
ID int64 `json:"id"`
Name string `json:"name"`
Owner string `json:"owner"`
FullName string `json:"full_name"`
}
// Issue represents an issue in a repository
type Issue struct {
ID int64 `json:"id"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
Index int64 `json:"number"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int64 `json:"original_author_id"`
Title string `json:"title"`
Body string `json:"body"`
Ref string `json:"ref"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
Assignees []*User `json:"assignees"`
// Whether the issue is open or closed
State StateType `json:"state"`
IsLocked bool `json:"is_locked"`
Comments int `json:"comments"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
Closed *time.Time `json:"closed_at"`
Deadline *time.Time `json:"due_date"`
PullRequest *PullRequestMeta `json:"pull_request"`
Repository *RepositoryMeta `json:"repository"`
}
// ListIssueOption list issue options
type ListIssueOption struct {
ListOptions
State StateType
Type IssueType
Labels []string
Milestones []string
KeyWord string
Since time.Time
Before time.Time
// filter by created by username
CreatedBy string
// filter by assigned to username
AssignedBy string
// filter by username mentioned
MentionedBy string
// filter by owner (only works on ListIssues on User)
Owner string
// filter by team (requires organization owner parameter to be provided and only works on ListIssues on User)
Team string
}
// StateType issue state type
type StateType string
const (
// StateOpen pr/issue is opend
StateOpen StateType = "open"
// StateClosed pr/issue is closed
StateClosed StateType = "closed"
// StateAll is all
StateAll StateType = "all"
)
// IssueType is issue a pull or only an issue
type IssueType string
const (
// IssueTypeAll pr and issue
IssueTypeAll IssueType = ""
// IssueTypeIssue only issues
IssueTypeIssue IssueType = "issues"
// IssueTypePull only pulls
IssueTypePull IssueType = "pulls"
)
// QueryEncode turns options into querystring argument
func (opt *ListIssueOption) QueryEncode() string {
query := opt.getURLQuery()
if len(opt.State) > 0 {
query.Add("state", string(opt.State))
}
if len(opt.Labels) > 0 {
query.Add("labels", strings.Join(opt.Labels, ","))
}
if len(opt.KeyWord) > 0 {
query.Add("q", opt.KeyWord)
}
query.Add("type", string(opt.Type))
if len(opt.Milestones) > 0 {
query.Add("milestones", strings.Join(opt.Milestones, ","))
}
if !opt.Since.IsZero() {
query.Add("since", opt.Since.Format(time.RFC3339))
}
if !opt.Before.IsZero() {
query.Add("before", opt.Before.Format(time.RFC3339))
}
if len(opt.CreatedBy) > 0 {
query.Add("created_by", opt.CreatedBy)
}
if len(opt.AssignedBy) > 0 {
query.Add("assigned_by", opt.AssignedBy)
}
if len(opt.MentionedBy) > 0 {
query.Add("mentioned_by", opt.MentionedBy)
}
if len(opt.Owner) > 0 {
query.Add("owner", opt.Owner)
}
if len(opt.Team) > 0 {
query.Add("team", opt.MentionedBy)
}
return query.Encode()
}
// ListIssues returns all issues assigned the authenticated user
func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, *Response, error) {
opt.setDefaults()
issues := make([]*Issue, 0, opt.PageSize)
link, _ := url.Parse("/repos/issues/search")
link.RawQuery = opt.QueryEncode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil {
for i := 0; i < len(issues); i++ {
if issues[i].Repository != nil {
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
}
}
}
for i := range issues {
c.issueBackwardsCompatibility(issues[i])
}
return issues, resp, err
}
// ListRepoIssues returns all issues for a given repository
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
issues := make([]*Issue, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo))
link.RawQuery = opt.QueryEncode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil {
for i := 0; i < len(issues); i++ {
if issues[i].Repository != nil {
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
}
}
}
for i := range issues {
c.issueBackwardsCompatibility(issues[i])
}
return issues, resp, err
}
// GetIssue returns a single issue for a given repository
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
issue := new(Issue)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil && issue.Repository != nil {
issue.Repository.Owner = strings.Split(issue.Repository.FullName, "/")[0]
}
c.issueBackwardsCompatibility(issue)
return issue, resp, err
}
// CreateIssueOption options to create one issue
type CreateIssueOption struct {
Title string `json:"title"`
Body string `json:"body"`
Ref string `json:"ref"`
Assignees []string `json:"assignees"`
Deadline *time.Time `json:"due_date"`
// milestone id
Milestone int64 `json:"milestone"`
// list of label ids
Labels []int64 `json:"labels"`
Closed bool `json:"closed"`
}
// Validate the CreateIssueOption struct
func (opt CreateIssueOption) Validate() error {
if len(strings.TrimSpace(opt.Title)) == 0 {
return fmt.Errorf("title is empty")
}
return nil
}
// CreateIssue create a new issue for a given repository
func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
issue := new(Issue)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
jsonHeader, bytes.NewReader(body), issue)
c.issueBackwardsCompatibility(issue)
return issue, resp, err
}
// EditIssueOption options for editing an issue
type EditIssueOption struct {
Title string `json:"title"`
Body *string `json:"body"`
Ref *string `json:"ref"`
Assignees []string `json:"assignees"`
Milestone *int64 `json:"milestone"`
State *StateType `json:"state"`
Deadline *time.Time `json:"due_date"`
RemoveDeadline *bool `json:"unset_due_date"`
}
// Validate the EditIssueOption struct
func (opt EditIssueOption) Validate() error {
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
return fmt.Errorf("title is empty")
}
return nil
}
// EditIssue modify an existing issue for a given repository
func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
issue := new(Issue)
resp, err := c.getParsedResponse("PATCH",
fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
jsonHeader, bytes.NewReader(body), issue)
c.issueBackwardsCompatibility(issue)
return issue, resp, err
}
// DeleteIssue delete a issue from a repository
func (c *Client) DeleteIssue(user, repo string, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/issues/%d", user, repo, id),
nil, nil)
return resp, err
}
func (c *Client) issueBackwardsCompatibility(issue *Issue) {
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
c.mutex.RLock()
issue.HTMLURL = fmt.Sprintf("%s/%s/issues/%d", c.url, issue.Repository.FullName, issue.Index)
c.mutex.RUnlock()
}
}

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

@ -0,0 +1,154 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"time"
)
// Comment represents a comment on a commit or issue
type Comment struct {
ID int64 `json:"id"`
HTMLURL string `json:"html_url"`
PRURL string `json:"pull_request_url"`
IssueURL string `json:"issue_url"`
Poster *User `json:"user"`
OriginalAuthor string `json:"original_author"`
OriginalAuthorID int64 `json:"original_author_id"`
Body string `json:"body"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// ListIssueCommentOptions list comment options
type ListIssueCommentOptions struct {
ListOptions
Since time.Time
Before time.Time
}
// QueryEncode turns options into querystring argument
func (opt *ListIssueCommentOptions) QueryEncode() string {
query := opt.getURLQuery()
if !opt.Since.IsZero() {
query.Add("since", opt.Since.Format(time.RFC3339))
}
if !opt.Before.IsZero() {
query.Add("before", opt.Before.Format(time.RFC3339))
}
return query.Encode()
}
// ListIssueComments list comments on an issue.
func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index))
link.RawQuery = opt.QueryEncode()
comments := make([]*Comment, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments)
return comments, resp, err
}
// ListRepoIssueComments list comments for a given repo.
func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo))
link.RawQuery = opt.QueryEncode()
comments := make([]*Comment, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments)
return comments, resp, err
}
// GetIssueComment get a comment for a given repo by id.
func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
comment := new(Comment)
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return comment, nil, err
}
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, id), nil, nil, &comment)
return comment, resp, err
}
// CreateIssueCommentOption options for creating a comment on an issue
type CreateIssueCommentOption struct {
Body string `json:"body"`
}
// Validate the CreateIssueCommentOption struct
func (opt CreateIssueCommentOption) Validate() error {
if len(opt.Body) == 0 {
return fmt.Errorf("body is empty")
}
return nil
}
// CreateIssueComment create comment on an issue.
func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
comment := new(Comment)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment)
return comment, resp, err
}
// EditIssueCommentOption options for editing a comment
type EditIssueCommentOption struct {
Body string `json:"body"`
}
// Validate the EditIssueCommentOption struct
func (opt EditIssueCommentOption) Validate() error {
if len(opt.Body) == 0 {
return fmt.Errorf("body is empty")
}
return nil
}
// EditIssueComment edits an issue comment.
func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
comment := new(Comment)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), jsonHeader, bytes.NewReader(body), comment)
return comment, resp, err
}
// DeleteIssueComment deletes an issue comment.
func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil)
return resp, err
}

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

@ -0,0 +1,211 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"regexp"
"strings"
)
// Label a label to an issue or a pr
type Label struct {
ID int64 `json:"id"`
Name string `json:"name"`
// example: 00aabb
Color string `json:"color"`
Description string `json:"description"`
URL string `json:"url"`
}
// ListLabelsOptions options for listing repository's labels
type ListLabelsOptions struct {
ListOptions
}
// ListRepoLabels list labels of one repository
func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
labels := make([]*Label, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels)
return labels, resp, err
}
// GetRepoLabel get one label of repository by repo it
func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
label := new(Label)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
return label, resp, err
}
// CreateLabelOption options for creating a label
type CreateLabelOption struct {
Name string `json:"name"`
// example: #00aabb
Color string `json:"color"`
Description string `json:"description"`
}
// Validate the CreateLabelOption struct
func (opt CreateLabelOption) Validate() error {
aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color)
if err != nil {
return err
}
if !aw {
return fmt.Errorf("invalid color format")
}
if len(strings.TrimSpace(opt.Name)) == 0 {
return fmt.Errorf("empty name not allowed")
}
return nil
}
// CreateLabel create one label of repository
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
if len(opt.Color) == 6 {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
opt.Color = "#" + opt.Color
}
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
label := new(Label)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/labels", owner, repo),
jsonHeader, bytes.NewReader(body), label)
return label, resp, err
}
// EditLabelOption options for editing a label
type EditLabelOption struct {
Name *string `json:"name"`
Color *string `json:"color"`
Description *string `json:"description"`
}
// Validate the EditLabelOption struct
func (opt EditLabelOption) Validate() error {
if opt.Color != nil {
aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", *opt.Color)
if err != nil {
return err
}
if !aw {
return fmt.Errorf("invalid color format")
}
}
if opt.Name != nil {
if len(strings.TrimSpace(*opt.Name)) == 0 {
return fmt.Errorf("empty name not allowed")
}
}
return nil
}
// EditLabel modify one label with options
func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
label := new(Label)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label)
return label, resp, err
}
// DeleteLabel delete one label of repository by id
func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
return resp, err
}
// GetIssueLabels get labels of one issue via issue id
func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
labels := make([]*Label, 0, 5)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels)
return labels, resp, err
}
// IssueLabelsOption a collection of labels
type IssueLabelsOption struct {
// list of label IDs
Labels []int64 `json:"labels"`
}
// AddIssueLabels add one or more labels to one issue
func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
var labels []*Label
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
return labels, resp, err
}
// ReplaceIssueLabels replace old labels of issue with new labels
func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
var labels []*Label
resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
return labels, resp, err
}
// DeleteIssueLabel delete one label of one issue by issue id and label id
// TODO: maybe we need delete by label name and issue id
func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
return resp, err
}
// ClearIssueLabels delete all the labels of one issue.
func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
return resp, err
}

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

@ -0,0 +1,237 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
)
// Milestone milestone is a collection of issues on one repository
type Milestone struct {
ID int64 `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
State StateType `json:"state"`
OpenIssues int `json:"open_issues"`
ClosedIssues int `json:"closed_issues"`
Created time.Time `json:"created_at"`
Updated *time.Time `json:"updated_at"`
Closed *time.Time `json:"closed_at"`
Deadline *time.Time `json:"due_on"`
}
// ListMilestoneOption list milestone options
type ListMilestoneOption struct {
ListOptions
// open, closed, all
State StateType
Name string
}
// QueryEncode turns options into querystring argument
func (opt *ListMilestoneOption) QueryEncode() string {
query := opt.getURLQuery()
if opt.State != "" {
query.Add("state", string(opt.State))
}
if len(opt.Name) != 0 {
query.Add("name", opt.Name)
}
return query.Encode()
}
// ListRepoMilestones list all the milestones of one repository
func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
milestones := make([]*Milestone, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/milestones", owner, repo))
link.RawQuery = opt.QueryEncode()
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &milestones)
return milestones, resp, err
}
// GetMilestone get one milestone by repo name and milestone id
func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
return milestone, resp, err
}
// GetMilestoneByName get one milestone by repo and milestone name
func (c *Client) GetMilestoneByName(owner, repo, name string) (*Milestone, *Response, error) {
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
// backwards compatibility mode
m, resp, err := c.resolveMilestoneByName(owner, repo, name)
return m, resp, err
}
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil, milestone)
return milestone, resp, err
}
// CreateMilestoneOption options for creating a milestone
type CreateMilestoneOption struct {
Title string `json:"title"`
Description string `json:"description"`
State StateType `json:"state"`
Deadline *time.Time `json:"due_on"`
}
// Validate the CreateMilestoneOption struct
func (opt CreateMilestoneOption) Validate() error {
if len(strings.TrimSpace(opt.Title)) == 0 {
return fmt.Errorf("title is empty")
}
return nil
}
// CreateMilestone create one milestone with options
func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
// make creating closed milestones need gitea >= v1.13.0
// this make it backwards compatible
if err == nil && opt.State == StateClosed && milestone.State != StateClosed {
closed := StateClosed
return c.EditMilestone(owner, repo, milestone.ID, EditMilestoneOption{
State: &closed,
})
}
return milestone, resp, err
}
// EditMilestoneOption options for editing a milestone
type EditMilestoneOption struct {
Title string `json:"title"`
Description *string `json:"description"`
State *StateType `json:"state"`
Deadline *time.Time `json:"due_on"`
}
// Validate the EditMilestoneOption struct
func (opt EditMilestoneOption) Validate() error {
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
return fmt.Errorf("title is empty")
}
return nil
}
// EditMilestone modify milestone with options
func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone)
return milestone, resp, err
}
// EditMilestoneByName modify milestone with options
func (c *Client) EditMilestoneByName(owner, repo, name string, opt EditMilestoneOption) (*Milestone, *Response, error) {
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
// backwards compatibility mode
m, _, err := c.resolveMilestoneByName(owner, repo, name)
if err != nil {
return nil, nil, err
}
return c.EditMilestone(owner, repo, m.ID, opt)
}
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), milestone)
return milestone, resp, err
}
// DeleteMilestone delete one milestone by id
func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
return resp, err
}
// DeleteMilestoneByName delete one milestone by name
func (c *Client) DeleteMilestoneByName(owner, repo, name string) (*Response, error) {
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
// backwards compatibility mode
m, _, err := c.resolveMilestoneByName(owner, repo, name)
if err != nil {
return nil, err
}
return c.DeleteMilestone(owner, repo, m.ID)
}
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil)
return resp, err
}
// resolveMilestoneByName is a fallback method to find milestone id by name
func (c *Client) resolveMilestoneByName(owner, repo, name string) (*Milestone, *Response, error) {
for i := 1; ; i++ {
miles, resp, err := c.ListRepoMilestones(owner, repo, ListMilestoneOption{
ListOptions: ListOptions{
Page: i,
},
State: "all",
})
if err != nil {
return nil, nil, err
}
if len(miles) == 0 {
return nil, nil, fmt.Errorf("milestone '%s' do not exist", name)
}
for _, m := range miles {
if strings.EqualFold(strings.TrimSpace(m.Title), strings.TrimSpace(name)) {
return m, resp, nil
}
}
}
}

104
vendor/code.gitea.io/sdk/gitea/issue_reaction.go generated vendored Normal file
View File

@ -0,0 +1,104 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Reaction contain one reaction
type Reaction struct {
User *User `json:"user"`
Reaction string `json:"content"`
Created time.Time `json:"created_at"`
}
// GetIssueReactions get a list reactions of an issue
func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
reactions := make([]*Reaction, 0, 10)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions)
return reactions, resp, err
}
// GetIssueCommentReactions get a list of reactions from a comment of an issue
func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
reactions := make([]*Reaction, 0, 10)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions)
return reactions, resp, err
}
// editReactionOption contain the reaction type
type editReactionOption struct {
Reaction string `json:"content"`
}
// PostIssueReaction add a reaction to an issue
func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
reactionResponse := new(Reaction)
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
return nil, nil, err
}
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index),
jsonHeader, bytes.NewReader(body), reactionResponse)
return reactionResponse, resp, err
}
// DeleteIssueReaction remove a reaction from an issue
func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body))
return resp, err
}
// PostIssueCommentReaction add a reaction to a comment of an issue
func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
reactionResponse := new(Reaction)
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
return nil, nil, err
}
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID),
jsonHeader, bytes.NewReader(body), reactionResponse)
return reactionResponse, resp, err
}
// DeleteIssueCommentReaction remove a reaction from a comment of an issue
func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID),
jsonHeader, bytes.NewReader(body))
return resp, err
}

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

@ -0,0 +1,57 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"time"
)
// StopWatch represents a running stopwatch of an issue / pr
type StopWatch struct {
Created time.Time `json:"created"`
Seconds int64 `json:"seconds"`
Duration string `json:"duration"`
IssueIndex int64 `json:"issue_index"`
IssueTitle string `json:"issue_title"`
RepoOwnerName string `json:"repo_owner_name"`
RepoName string `json:"repo_name"`
}
// GetMyStopwatches list all stopwatches
func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) {
stopwatches := make([]*StopWatch, 0, 1)
resp, err := c.getParsedResponse("GET", "/user/stopwatches", nil, nil, &stopwatches)
return stopwatches, resp, err
}
// DeleteIssueStopwatch delete / cancel a specific stopwatch
func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil)
return resp, err
}
// StartIssueStopWatch starts a stopwatch for an existing issue for a given
// repository
func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil)
return resp, err
}
// StopIssueStopWatch stops an existing stopwatch for an issue in a given
// repository
func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil)
return resp, err
}

87
vendor/code.gitea.io/sdk/gitea/issue_subscription.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/http"
)
// GetIssueSubscribers get list of users who subscribed on an issue
func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
subscribers := make([]*User, 0, 10)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers)
return subscribers, resp, err
}
// AddIssueSubscription Subscribe user to issue
func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
if err != nil {
return resp, err
}
if status == http.StatusCreated {
return resp, nil
}
if status == http.StatusOK {
return resp, fmt.Errorf("already subscribed")
}
return resp, fmt.Errorf("unexpected Status: %d", status)
}
// DeleteIssueSubscription unsubscribe user from issue
func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
if err != nil {
return resp, err
}
if status == http.StatusCreated {
return resp, nil
}
if status == http.StatusOK {
return resp, fmt.Errorf("already unsubscribed")
}
return resp, fmt.Errorf("unexpected Status: %d", status)
}
// CheckIssueSubscription check if current user is subscribed to an issue
func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
wi := new(WatchInfo)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/check", owner, repo, index), nil, nil, wi)
return wi, resp, err
}
// IssueSubscribe subscribe current user to an issue
func (c *Client) IssueSubscribe(owner, repo string, index int64) (*Response, error) {
u, _, err := c.GetMyUserInfo()
if err != nil {
return nil, err
}
return c.AddIssueSubscription(owner, repo, index, u.UserName)
}
// IssueUnSubscribe unsubscribe current user from an issue
func (c *Client) IssueUnSubscribe(owner, repo string, index int64) (*Response, error) {
u, _, err := c.GetMyUserInfo()
if err != nil {
return nil, err
}
return c.DeleteIssueSubscription(owner, repo, index, u.UserName)
}

97
vendor/code.gitea.io/sdk/gitea/issue_template.go generated vendored Normal file
View File

@ -0,0 +1,97 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
)
// IssueTemplate provides metadata and content on an issue template.
// There are two types of issue templates: .Markdown- and .Form-based.
type IssueTemplate struct {
Name string `json:"name"`
About string `json:"about"`
Filename string `json:"file_name"`
IssueTitle string `json:"title"`
IssueLabels []string `json:"labels"`
IssueRef string `json:"ref"`
// If non-nil, this is a form-based template
Form []IssueFormElement `json:"body"`
// Should only be used when .Form is nil.
MarkdownContent string `json:"content"`
}
// IssueFormElement describes a part of a IssueTemplate form
type IssueFormElement struct {
ID string `json:"id"`
Type IssueFormElementType `json:"type"`
Attributes IssueFormElementAttributes `json:"attributes"`
Validations IssueFormElementValidations `json:"validations"`
}
// IssueFormElementAttributes contains the combined set of attributes available on all element types.
type IssueFormElementAttributes struct {
// required for all element types.
// A brief description of the expected user input, which is also displayed in the form.
Label string `json:"label"`
// required for element types "dropdown", "checkboxes"
// for dropdown, contains the available options
Options []string `json:"options"`
// for element types "markdown", "textarea", "input"
// Text that is pre-filled in the input
Value string `json:"value"`
// for element types "textarea", "input", "dropdown", "checkboxes"
// A description of the text area to provide context or guidance, which is displayed in the form.
Description string `json:"description"`
// for element types "textarea", "input"
// A semi-opaque placeholder that renders in the text area when empty.
Placeholder string `json:"placeholder"`
// for element types "textarea"
// A language specifier. If set, the input is rendered as codeblock with syntax highlighting.
SyntaxHighlighting string `json:"render"`
// for element types "dropdown"
Multiple bool `json:"multiple"`
}
// IssueFormElementValidations contains the combined set of validations available on all element types.
type IssueFormElementValidations struct {
// for all element types
Required bool `json:"required"`
// for element types "input"
IsNumber bool `json:"is_number"`
// for element types "input"
Regex string `json:"regex"`
}
// IssueFormElementType is an enum
type IssueFormElementType string
const (
// IssueFormElementMarkdown is markdown rendered to the form for context, but omitted in the resulting issue
IssueFormElementMarkdown IssueFormElementType = "markdown"
// IssueFormElementTextarea is a multi line input
IssueFormElementTextarea IssueFormElementType = "textarea"
// IssueFormElementInput is a single line input
IssueFormElementInput IssueFormElementType = "input"
// IssueFormElementDropdown is a select form
IssueFormElementDropdown IssueFormElementType = "dropdown"
// IssueFormElementCheckboxes are a multi checkbox input
IssueFormElementCheckboxes IssueFormElementType = "checkboxes"
)
// GetIssueTemplates lists all issue templates of the repository
func (c *Client) GetIssueTemplates(owner, repo string) ([]*IssueTemplate, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
templates := new([]*IssueTemplate)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issue_templates", owner, repo), nil, nil, templates)
return *templates, resp, err
}
// IsForm tells if this template is a form instead of a markdown-based template.
func (t IssueTemplate) IsForm() bool {
return t.Form != nil
}

142
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go generated vendored Normal file
View File

@ -0,0 +1,142 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"time"
)
// TrackedTime worked time for an issue / pr
type TrackedTime struct {
ID int64 `json:"id"`
Created time.Time `json:"created"`
// Time in seconds
Time int64 `json:"time"`
// deprecated (only for backwards compatibility)
UserID int64 `json:"user_id"`
UserName string `json:"user_name"`
// deprecated (only for backwards compatibility)
IssueID int64 `json:"issue_id"`
Issue *Issue `json:"issue"`
}
// ListTrackedTimesOptions options for listing repository's tracked times
type ListTrackedTimesOptions struct {
ListOptions
Since time.Time
Before time.Time
// User filter is only used by ListRepoTrackedTimes !!!
User string
}
// QueryEncode turns options into querystring argument
func (opt *ListTrackedTimesOptions) QueryEncode() string {
query := opt.getURLQuery()
if !opt.Since.IsZero() {
query.Add("since", opt.Since.Format(time.RFC3339))
}
if !opt.Before.IsZero() {
query.Add("before", opt.Before.Format(time.RFC3339))
}
if len(opt.User) != 0 {
query.Add("user", opt.User)
}
return query.Encode()
}
// ListRepoTrackedTimes list tracked times of a repository
func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/times", owner, repo))
opt.setDefaults()
link.RawQuery = opt.QueryEncode()
times := make([]*TrackedTime, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &times)
return times, resp, err
}
// GetMyTrackedTimes list tracked times of the current user
func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) {
times := make([]*TrackedTime, 0, 10)
resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, &times)
return times, resp, err
}
// AddTimeOption options for adding time to an issue
type AddTimeOption struct {
// time in seconds
Time int64 `json:"time"`
// optional
Created time.Time `json:"created"`
// optional
User string `json:"user_name"`
}
// Validate the AddTimeOption struct
func (opt AddTimeOption) Validate() error {
if opt.Time == 0 {
return fmt.Errorf("no time to add")
}
return nil
}
// AddTime adds time to issue with the given index
func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
t := new(TrackedTime)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index),
jsonHeader, bytes.NewReader(body), t)
return t, resp, err
}
// ListIssueTrackedTimes list tracked times of a single issue for a given repository
func (c *Client) ListIssueTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index))
opt.setDefaults()
link.RawQuery = opt.QueryEncode()
times := make([]*TrackedTime, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &times)
return times, resp, err
}
// ResetIssueTime reset tracked time of a single issue for a given repository
func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil)
return resp, err
}
// DeleteTime delete a specific tracked time by id of a single issue for a given repository
func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil)
return resp, err
}

40
vendor/code.gitea.io/sdk/gitea/list_options.go generated vendored Normal file
View File

@ -0,0 +1,40 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/url"
)
// ListOptions options for using Gitea's API pagination
type ListOptions struct {
// Setting Page to -1 disables pagination on endpoints that support it.
// Page numbering starts at 1.
Page int
// The default value depends on the server config DEFAULT_PAGING_NUM
// The highest valid value depends on the server config MAX_RESPONSE_ITEMS
PageSize int
}
func (o ListOptions) getURLQuery() url.Values {
query := make(url.Values)
query.Add("page", fmt.Sprintf("%d", o.Page))
query.Add("limit", fmt.Sprintf("%d", o.PageSize))
return query
}
// setDefaults applies default pagination options.
// If .Page is set to -1, it will disable pagination.
// WARNING: This function is not idempotent, make sure to never call this method twice!
func (o *ListOptions) setDefaults() {
if o.Page < 0 {
o.Page, o.PageSize = 0, 0
return
} else if o.Page == 0 {
o.Page = 1
}
}

257
vendor/code.gitea.io/sdk/gitea/notifications.go generated vendored Normal file
View File

@ -0,0 +1,257 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/url"
"time"
)
// NotificationThread expose Notification on API
type NotificationThread struct {
ID int64 `json:"id"`
Repository *Repository `json:"repository"`
Subject *NotificationSubject `json:"subject"`
Unread bool `json:"unread"`
Pinned bool `json:"pinned"`
UpdatedAt time.Time `json:"updated_at"`
URL string `json:"url"`
}
// NotificationSubject contains the notification subject (Issue/Pull/Commit)
type NotificationSubject struct {
Title string `json:"title"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
LatestCommentURL string `json:"latest_comment_url"`
LatestCommentHTMLURL string `json:"latest_comment_html_url"`
Type NotifySubjectType `json:"type"`
State NotifySubjectState `json:"state"`
}
// NotifyStatus notification status type
type NotifyStatus string
const (
// NotifyStatusUnread was not read
NotifyStatusUnread NotifyStatus = "unread"
// NotifyStatusRead was already read by user
NotifyStatusRead NotifyStatus = "read"
// NotifyStatusPinned notification is pinned by user
NotifyStatusPinned NotifyStatus = "pinned"
)
// NotifySubjectType represent type of notification subject
type NotifySubjectType string
const (
// NotifySubjectIssue an issue is subject of an notification
NotifySubjectIssue NotifySubjectType = "Issue"
// NotifySubjectPull an pull is subject of an notification
NotifySubjectPull NotifySubjectType = "Pull"
// NotifySubjectCommit an commit is subject of an notification
NotifySubjectCommit NotifySubjectType = "Commit"
// NotifySubjectRepository an repository is subject of an notification
NotifySubjectRepository NotifySubjectType = "Repository"
)
// NotifySubjectState reflect state of notification subject
type NotifySubjectState string
const (
// NotifySubjectOpen if subject is a pull/issue and is open at the moment
NotifySubjectOpen NotifySubjectState = "open"
// NotifySubjectClosed if subject is a pull/issue and is closed at the moment
NotifySubjectClosed NotifySubjectState = "closed"
// NotifySubjectMerged if subject is a pull and got merged
NotifySubjectMerged NotifySubjectState = "merged"
)
// ListNotificationOptions represents the filter options
type ListNotificationOptions struct {
ListOptions
Since time.Time
Before time.Time
Status []NotifyStatus
SubjectTypes []NotifySubjectType
}
// MarkNotificationOptions represents the filter & modify options
type MarkNotificationOptions struct {
LastReadAt time.Time
Status []NotifyStatus
ToStatus NotifyStatus
}
// QueryEncode encode options to url query
func (opt *ListNotificationOptions) QueryEncode() string {
query := opt.getURLQuery()
if !opt.Since.IsZero() {
query.Add("since", opt.Since.Format(time.RFC3339))
}
if !opt.Before.IsZero() {
query.Add("before", opt.Before.Format(time.RFC3339))
}
for _, s := range opt.Status {
query.Add("status-types", string(s))
}
for _, s := range opt.SubjectTypes {
query.Add("subject-type", string(s))
}
return query.Encode()
}
// Validate the CreateUserOption struct
func (opt ListNotificationOptions) Validate(c *Client) error {
if len(opt.Status) != 0 {
return c.checkServerVersionGreaterThanOrEqual(version1_12_3)
}
return nil
}
// QueryEncode encode options to url query
func (opt *MarkNotificationOptions) QueryEncode() string {
query := make(url.Values)
if !opt.LastReadAt.IsZero() {
query.Add("last_read_at", opt.LastReadAt.Format(time.RFC3339))
}
for _, s := range opt.Status {
query.Add("status-types", string(s))
}
if len(opt.ToStatus) != 0 {
query.Add("to-status", string(opt.ToStatus))
}
return query.Encode()
}
// Validate the CreateUserOption struct
func (opt MarkNotificationOptions) Validate(c *Client) error {
if len(opt.Status) != 0 || len(opt.ToStatus) != 0 {
return c.checkServerVersionGreaterThanOrEqual(version1_12_3)
}
return nil
}
// CheckNotifications list users's notification threads
func (c *Client) CheckNotifications() (int64, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return 0, nil, err
}
new := struct {
New int64 `json:"new"`
}{}
resp, err := c.getParsedResponse("GET", "/notifications/new", jsonHeader, nil, &new)
return new.New, resp, err
}
// GetNotification get notification thread by ID
func (c *Client) GetNotification(id int64) (*NotificationThread, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
thread := new(NotificationThread)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/notifications/threads/%d", id), nil, nil, thread)
return thread, resp, err
}
// ReadNotification mark notification thread as read by ID
// It optionally takes a second argument if status has to be set other than 'read'
// The relevant notification will be returned as the first parameter when the Gitea server is 1.16.0 or higher.
func (c *Client) ReadNotification(id int64, status ...NotifyStatus) (*NotificationThread, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
link := fmt.Sprintf("/notifications/threads/%d", id)
if len(status) != 0 {
link += fmt.Sprintf("?to-status=%s", status[0])
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err == nil {
thread := &NotificationThread{}
resp, err := c.getParsedResponse("PATCH", link, nil, nil, thread)
return thread, resp, err
}
_, resp, err := c.getResponse("PATCH", link, nil, nil)
return nil, resp, err
}
// ListNotifications list users's notification threads
func (c *Client) ListNotifications(opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
link, _ := url.Parse("/notifications")
link.RawQuery = opt.QueryEncode()
threads := make([]*NotificationThread, 0, 10)
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
return threads, resp, err
}
// ReadNotifications mark notification threads as read
// The relevant notifications will only be returned as the first parameter when the Gitea server is 1.16.0 or higher.
func (c *Client) ReadNotifications(opt MarkNotificationOptions) ([]*NotificationThread, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
link, _ := url.Parse("/notifications")
link.RawQuery = opt.QueryEncode()
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err == nil {
threads := make([]*NotificationThread, 0, 10)
resp, err := c.getParsedResponse("PUT", link.String(), nil, nil, &threads)
return threads, resp, err
}
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
return nil, resp, err
}
// ListRepoNotifications list users's notification threads on a specific repo
func (c *Client) ListRepoNotifications(owner, repo string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
link.RawQuery = opt.QueryEncode()
threads := make([]*NotificationThread, 0, 10)
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
return threads, resp, err
}
// ReadRepoNotifications mark notification threads as read on a specific repo
// The relevant notifications will only be returned as the first parameter when the Gitea server is 1.16.0 or higher.
func (c *Client) ReadRepoNotifications(owner, repo string, opt MarkNotificationOptions) ([]*NotificationThread, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
link.RawQuery = opt.QueryEncode()
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err == nil {
threads := make([]*NotificationThread, 0, 10)
resp, err := c.getParsedResponse("PUT", link.String(), nil, nil, &threads)
return threads, resp, err
}
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
return nil, resp, err
}

93
vendor/code.gitea.io/sdk/gitea/oauth2.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Oauth2 represents an Oauth2 Application
type Oauth2 struct {
ID int64 `json:"id"`
Name string `json:"name"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RedirectURIs []string `json:"redirect_uris"`
ConfidentialClient bool `json:"confidential_client"`
Created time.Time `json:"created"`
}
// ListOauth2Option for listing Oauth2 Applications
type ListOauth2Option struct {
ListOptions
}
// CreateOauth2Option required options for creating an Application
type CreateOauth2Option struct {
Name string `json:"name"`
ConfidentialClient bool `json:"confidential_client"`
RedirectURIs []string `json:"redirect_uris"`
}
// CreateOauth2 create an Oauth2 Application and returns a completed Oauth2 object.
func (c *Client) CreateOauth2(opt CreateOauth2Option) (*Oauth2, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
oauth := new(Oauth2)
resp, err := c.getParsedResponse("POST", "/user/applications/oauth2", jsonHeader, bytes.NewReader(body), oauth)
return oauth, resp, err
}
// UpdateOauth2 a specific Oauth2 Application by ID and return a completed Oauth2 object.
func (c *Client) UpdateOauth2(oauth2id int64, opt CreateOauth2Option) (*Oauth2, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
oauth := new(Oauth2)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), jsonHeader, bytes.NewReader(body), oauth)
return oauth, resp, err
}
// GetOauth2 a specific Oauth2 Application by ID.
func (c *Client) GetOauth2(oauth2id int64) (*Oauth2, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
oauth2s := &Oauth2{}
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil, &oauth2s)
return oauth2s, resp, err
}
// ListOauth2 all of your Oauth2 Applications.
func (c *Client) ListOauth2(opt ListOauth2Option) ([]*Oauth2, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
opt.setDefaults()
oauth2s := make([]*Oauth2, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2?%s", opt.getURLQuery().Encode()), nil, nil, &oauth2s)
return oauth2s, resp, err
}
// DeleteOauth2 delete an Oauth2 application by ID
func (c *Client) DeleteOauth2(oauth2id int64) (*Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil)
return resp, err
}

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

@ -0,0 +1,155 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// Organization represents an organization
type Organization struct {
ID int64 `json:"id"`
UserName string `json:"username"`
FullName string `json:"full_name"`
AvatarURL string `json:"avatar_url"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
Visibility string `json:"visibility"`
}
// VisibleType defines the visibility
type VisibleType string
const (
// VisibleTypePublic Visible for everyone
VisibleTypePublic VisibleType = "public"
// VisibleTypeLimited Visible for every connected user
VisibleTypeLimited VisibleType = "limited"
// VisibleTypePrivate Visible only for organization's members
VisibleTypePrivate VisibleType = "private"
)
// ListOrgsOptions options for listing organizations
type ListOrgsOptions struct {
ListOptions
}
// ListMyOrgs list all of current user's organizations
func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, error) {
opt.setDefaults()
orgs := make([]*Organization, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
return orgs, resp, err
}
// ListUserOrgs list all of some user's organizations
func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
opt.setDefaults()
orgs := make([]*Organization, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs)
return orgs, resp, err
}
// GetOrg get one organization by name
func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) {
if err := escapeValidatePathSegments(&orgname); err != nil {
return nil, nil, err
}
org := new(Organization)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
return org, resp, err
}
// CreateOrgOption options for creating an organization
type CreateOrgOption struct {
Name string `json:"username"`
FullName string `json:"full_name"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
Visibility VisibleType `json:"visibility"`
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
}
// checkVisibilityOpt check if mode exist
func checkVisibilityOpt(v VisibleType) bool {
return v == VisibleTypePublic || v == VisibleTypeLimited || v == VisibleTypePrivate
}
// Validate the CreateOrgOption struct
func (opt CreateOrgOption) Validate() error {
if len(opt.Name) == 0 {
return fmt.Errorf("empty org name")
}
if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) {
return fmt.Errorf("invalid visibility option")
}
return nil
}
// CreateOrg creates an organization
func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, *Response, error) {
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
org := new(Organization)
resp, err := c.getParsedResponse("POST", "/orgs", jsonHeader, bytes.NewReader(body), org)
return org, resp, err
}
// EditOrgOption options for editing an organization
type EditOrgOption struct {
FullName string `json:"full_name"`
Description string `json:"description"`
Website string `json:"website"`
Location string `json:"location"`
Visibility VisibleType `json:"visibility"`
}
// Validate the EditOrgOption struct
func (opt EditOrgOption) Validate() error {
if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) {
return fmt.Errorf("invalid visibility option")
}
return nil
}
// EditOrg modify one organization via options
func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
if err := escapeValidatePathSegments(&orgname); err != nil {
return nil, err
}
if err := opt.Validate(); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body))
return resp, err
}
// DeleteOrg deletes an organization
func (c *Client) DeleteOrg(orgname string) (*Response, error) {
if err := escapeValidatePathSegments(&orgname); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil)
return resp, err
}

87
vendor/code.gitea.io/sdk/gitea/org_action.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
)
// ListOrgActionSecretOption list OrgActionSecret options
type ListOrgActionSecretOption struct {
ListOptions
}
// ListOrgActionSecret list an organization's secrets
func (c *Client) ListOrgActionSecret(org string, opt ListOrgActionSecretOption) ([]*Secret, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
opt.setDefaults()
secrets := make([]*Secret, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/actions/secrets", org))
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &secrets)
return secrets, resp, err
}
// CreateSecretOption represents the options for creating a secret.
type CreateSecretOption struct {
Name string `json:"name"` // Name is the name of the secret.
Data string `json:"data"` // Data is the data of the secret.
}
// Validate checks if the CreateSecretOption is valid.
// It returns an error if any of the validation checks fail.
func (opt *CreateSecretOption) Validate() error {
if len(opt.Name) == 0 {
return fmt.Errorf("name required")
}
if len(opt.Name) > 30 {
return fmt.Errorf("name to long")
}
if len(opt.Data) == 0 {
return fmt.Errorf("data required")
}
return nil
}
// CreateOrgActionSecret creates a secret for the specified organization in the Gitea Actions.
// It takes the organization name and the secret options as parameters.
// The function returns the HTTP response and an error, if any.
func (c *Client) CreateOrgActionSecret(org string, opt CreateSecretOption) (*Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, err
}
if err := (&opt).Validate(); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/actions/secrets/%s", org, opt.Name), jsonHeader, bytes.NewReader(body))
if err != nil {
return nil, err
}
switch status {
case http.StatusCreated:
return resp, nil
case http.StatusNoContent:
return resp, nil
case http.StatusNotFound:
return resp, fmt.Errorf("forbidden")
case http.StatusBadRequest:
return resp, fmt.Errorf("bad request")
default:
return resp, fmt.Errorf("unexpected Status: %d", status)
}
}

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

@ -0,0 +1,142 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/http"
"net/url"
)
// DeleteOrgMembership remove a member from an organization
func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) {
if err := escapeValidatePathSegments(&org, &user); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
return resp, err
}
// ListOrgMembershipOption list OrgMembership options
type ListOrgMembershipOption struct {
ListOptions
}
// ListOrgMembership list an organization's members
func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", org))
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
return users, resp, err
}
// ListPublicOrgMembership list an organization's members
func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", org))
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
return users, resp, err
}
// CheckOrgMembership Check if a user is a member of an organization
func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
if err := escapeValidatePathSegments(&org, &user); err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
if err != nil {
return false, resp, err
}
switch status {
case http.StatusNoContent:
return true, resp, nil
case http.StatusNotFound:
return false, resp, nil
default:
return false, resp, fmt.Errorf("unexpected Status: %d", status)
}
}
// CheckPublicOrgMembership Check if a user is a member of an organization
func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, error) {
if err := escapeValidatePathSegments(&org, &user); err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
if err != nil {
return false, resp, err
}
switch status {
case http.StatusNoContent:
return true, resp, nil
case http.StatusNotFound:
return false, resp, nil
default:
return false, resp, fmt.Errorf("unexpected Status: %d", status)
}
}
// SetPublicOrgMembership publicize/conceal a user's membership
func (c *Client) SetPublicOrgMembership(org, user string, visible bool) (*Response, error) {
if err := escapeValidatePathSegments(&org, &user); err != nil {
return nil, err
}
var (
status int
err error
resp *Response
)
if visible {
status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
} else {
status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
}
if err != nil {
return resp, err
}
switch status {
case http.StatusNoContent:
return resp, nil
case http.StatusNotFound:
return resp, fmt.Errorf("forbidden")
default:
return resp, fmt.Errorf("unexpected Status: %d", status)
}
}
// OrgPermissions represents the permissions for an user in an organization
type OrgPermissions struct {
CanCreateRepository bool `json:"can_create_repository"`
CanRead bool `json:"can_read"`
CanWrite bool `json:"can_write"`
IsAdmin bool `json:"is_admin"`
IsOwner bool `json:"is_owner"`
}
// GetOrgPermissions returns user permissions for specific organization.
func (c *Client) GetOrgPermissions(org, user string) (*OrgPermissions, *Response, error) {
if err := escapeValidatePathSegments(&org, &user); err != nil {
return nil, nil, err
}
perm := &OrgPermissions{}
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs/%s/permissions", user, org), jsonHeader, nil, &perm)
if err != nil {
return nil, resp, err
}
return perm, resp, nil
}

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

@ -0,0 +1,285 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
)
// Team represents a team in an organization
type Team struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Organization *Organization `json:"organization"`
Permission AccessMode `json:"permission"`
CanCreateOrgRepo bool `json:"can_create_org_repo"`
IncludesAllRepositories bool `json:"includes_all_repositories"`
Units []RepoUnitType `json:"units"`
}
// RepoUnitType represent all unit types of a repo gitea currently offer
type RepoUnitType string
const (
// RepoUnitCode represent file view of a repository
RepoUnitCode RepoUnitType = "repo.code"
// RepoUnitIssues represent issues of a repository
RepoUnitIssues RepoUnitType = "repo.issues"
// RepoUnitPulls represent pulls of a repository
RepoUnitPulls RepoUnitType = "repo.pulls"
// RepoUnitExtIssues represent external issues of a repository
RepoUnitExtIssues RepoUnitType = "repo.ext_issues"
// RepoUnitWiki represent wiki of a repository
RepoUnitWiki RepoUnitType = "repo.wiki"
// RepoUnitExtWiki represent external wiki of a repository
RepoUnitExtWiki RepoUnitType = "repo.ext_wiki"
// RepoUnitReleases represent releases of a repository
RepoUnitReleases RepoUnitType = "repo.releases"
// RepoUnitProjects represent projects of a repository
RepoUnitProjects RepoUnitType = "repo.projects"
// RepoUnitPackages represents packages of a repository
RepoUnitPackages RepoUnitType = "repo.packages"
// RepoUnitActions represents actions of a repository
RepoUnitActions RepoUnitType = "repo.actions"
)
// ListTeamsOptions options for listing teams
type ListTeamsOptions struct {
ListOptions
}
// ListOrgTeams lists all teams of an organization
func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
opt.setDefaults()
teams := make([]*Team, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams)
return teams, resp, err
}
// ListMyTeams lists all the teams of the current user
func (c *Client) ListMyTeams(opt *ListTeamsOptions) ([]*Team, *Response, error) {
opt.setDefaults()
teams := make([]*Team, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/teams?%s", opt.getURLQuery().Encode()), nil, nil, &teams)
return teams, resp, err
}
// GetTeam gets a team by ID
func (c *Client) GetTeam(id int64) (*Team, *Response, error) {
t := new(Team)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d", id), nil, nil, t)
return t, resp, err
}
// SearchTeamsOptions options for searching teams.
type SearchTeamsOptions struct {
ListOptions
Query string
IncludeDescription bool
}
func (o SearchTeamsOptions) getURLQuery() url.Values {
query := make(url.Values)
query.Add("page", fmt.Sprintf("%d", o.Page))
query.Add("limit", fmt.Sprintf("%d", o.PageSize))
query.Add("q", o.Query)
query.Add("include_desc", fmt.Sprintf("%t", o.IncludeDescription))
return query
}
// TeamSearchResults is the JSON struct that is returned from Team search API.
type TeamSearchResults struct {
OK bool `json:"ok"`
Error string `json:"error"`
Data []*Team `json:"data"`
}
// SearchOrgTeams search for teams in a org.
func (c *Client) SearchOrgTeams(org string, opt *SearchTeamsOptions) ([]*Team, *Response, error) {
responseBody := TeamSearchResults{}
opt.setDefaults()
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams/search?%s", org, opt.getURLQuery().Encode()), nil, nil, &responseBody)
if err != nil {
return nil, resp, err
}
if !responseBody.OK {
return nil, resp, fmt.Errorf("gitea error: %v", responseBody.Error)
}
return responseBody.Data, resp, err
}
// CreateTeamOption options for creating a team
type CreateTeamOption struct {
Name string `json:"name"`
Description string `json:"description"`
Permission AccessMode `json:"permission"`
CanCreateOrgRepo bool `json:"can_create_org_repo"`
IncludesAllRepositories bool `json:"includes_all_repositories"`
Units []RepoUnitType `json:"units"`
}
// Validate the CreateTeamOption struct
func (opt *CreateTeamOption) Validate() error {
if opt.Permission == AccessModeOwner {
opt.Permission = AccessModeAdmin
} else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin {
return fmt.Errorf("permission mode invalid")
}
if len(opt.Name) == 0 {
return fmt.Errorf("name required")
}
if len(opt.Name) > 30 {
return fmt.Errorf("name to long")
}
if len(opt.Description) > 255 {
return fmt.Errorf("description to long")
}
return nil
}
// CreateTeam creates a team for an organization
func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
if err := (&opt).Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/teams", org), jsonHeader, bytes.NewReader(body), t)
return t, resp, err
}
// EditTeamOption options for editing a team
type EditTeamOption struct {
Name string `json:"name"`
Description *string `json:"description"`
Permission AccessMode `json:"permission"`
CanCreateOrgRepo *bool `json:"can_create_org_repo"`
IncludesAllRepositories *bool `json:"includes_all_repositories"`
Units []RepoUnitType `json:"units"`
}
// Validate the EditTeamOption struct
func (opt *EditTeamOption) Validate() error {
if opt.Permission == AccessModeOwner {
opt.Permission = AccessModeAdmin
} else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin {
return fmt.Errorf("permission mode invalid")
}
if len(opt.Name) == 0 {
return fmt.Errorf("name required")
}
if len(opt.Name) > 30 {
return fmt.Errorf("name to long")
}
if opt.Description != nil && len(*opt.Description) > 255 {
return fmt.Errorf("description to long")
}
return nil
}
// EditTeam edits a team of an organization
func (c *Client) EditTeam(id int64, opt EditTeamOption) (*Response, error) {
if err := (&opt).Validate(); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body))
return resp, err
}
// DeleteTeam deletes a team of an organization
func (c *Client) DeleteTeam(id int64) (*Response, error) {
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil)
return resp, err
}
// ListTeamMembersOptions options for listing team's members
type ListTeamMembersOptions struct {
ListOptions
}
// ListTeamMembers lists all members of a team
func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User, *Response, error) {
opt.setDefaults()
members := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members?%s", id, opt.getURLQuery().Encode()), nil, nil, &members)
return members, resp, err
}
// GetTeamMember gets a member of a team
func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
m := new(User)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m)
return m, resp, err
}
// AddTeamMember adds a member to a team
func (c *Client) AddTeamMember(id int64, user string) (*Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
return resp, err
}
// RemoveTeamMember removes a member from a team
func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
return resp, err
}
// ListTeamRepositoriesOptions options for listing team's repositories
type ListTeamRepositoriesOptions struct {
ListOptions
}
// ListTeamRepositories lists all repositories of a team
func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions) ([]*Repository, *Response, error) {
opt.setDefaults()
repos := make([]*Repository, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos?%s", id, opt.getURLQuery().Encode()), nil, nil, &repos)
return repos, resp, err
}
// AddTeamRepository adds a repository to a team
func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&org, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
return resp, err
}
// RemoveTeamRepository removes a repository from a team
func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&org, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
return resp, err
}

93
vendor/code.gitea.io/sdk/gitea/package.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"time"
)
// Package represents a package
type Package struct {
// the package's id
ID int64 `json:"id"`
// the package's owner
Owner User `json:"owner"`
// the repo this package belongs to (if any)
Repository *Repository `json:"repository"`
// the package's creator
Creator User `json:"creator"`
// the type of package:
Type string `json:"type"`
// the name of the package
Name string `json:"name"`
// the version of the package
Version string `json:"version"`
// the date the package was uploaded
CreatedAt time.Time `json:"created_at"`
}
// PackageFile represents a file from a package
type PackageFile struct {
// the file's ID
ID int64 `json:"id"`
// the size of the file in bytes
Size int64 `json:"size"`
// the name of the file
Name string `json:"name"`
// the md5 hash of the file
MD5 string `json:"md5"`
// the sha1 hash of the file
SHA1 string `json:"sha1"`
// the sha256 hash of the file
SHA256 string `json:"sha256"`
// the sha512 hash of the file
SHA512 string `json:"sha512"`
}
// ListPackagesOptions options for listing packages
type ListPackagesOptions struct {
ListOptions
}
// ListPackages lists all the packages owned by a given owner (user, organisation)
func (c *Client) ListPackages(owner string, opt ListPackagesOptions) ([]*Package, *Response, error) {
if err := escapeValidatePathSegments(&owner); err != nil {
return nil, nil, err
}
opt.setDefaults()
packages := make([]*Package, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/packages/%s?%s", owner, opt.getURLQuery().Encode()), nil, nil, &packages)
return packages, resp, err
}
// GetPackage gets the details of a specific package version
func (c *Client) GetPackage(owner, packageType, name, version string) (*Package, *Response, error) {
if err := escapeValidatePathSegments(&owner, &packageType, &name, &version); err != nil {
return nil, nil, err
}
foundPackage := new(Package)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/packages/%s/%s/%s/%s", owner, packageType, name, version), nil, nil, foundPackage)
return foundPackage, resp, err
}
// DeletePackage deletes a specific package version
func (c *Client) DeletePackage(owner, packageType, name, version string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &packageType, &name, &version); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/packages/%s/%s/%s/%s", owner, packageType, name, version), nil, nil)
return resp, err
}
// ListPackageFiles lists the files within a package
func (c *Client) ListPackageFiles(owner, packageType, name, version string) ([]*PackageFile, *Response, error) {
if err := escapeValidatePathSegments(&owner, &packageType, &name, &version); err != nil {
return nil, nil, err
}
packageFiles := make([]*PackageFile, 0)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/packages/%s/%s/%s/%s/files", owner, packageType, name, version), nil, nil, &packageFiles)
return packageFiles, resp, err
}

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

@ -0,0 +1,383 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
)
// PRBranchInfo information about a branch
type PRBranchInfo struct {
Name string `json:"label"`
Ref string `json:"ref"`
Sha string `json:"sha"`
RepoID int64 `json:"repo_id"`
Repository *Repository `json:"repo"`
}
// PullRequest represents a pull request
type PullRequest struct {
ID int64 `json:"id"`
URL string `json:"url"`
Index int64 `json:"number"`
Poster *User `json:"user"`
Title string `json:"title"`
Body string `json:"body"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
Assignee *User `json:"assignee"`
Assignees []*User `json:"assignees"`
State StateType `json:"state"`
IsLocked bool `json:"is_locked"`
Comments int `json:"comments"`
HTMLURL string `json:"html_url"`
DiffURL string `json:"diff_url"`
PatchURL string `json:"patch_url"`
Mergeable bool `json:"mergeable"`
HasMerged bool `json:"merged"`
Merged *time.Time `json:"merged_at"`
MergedCommitID *string `json:"merge_commit_sha"`
MergedBy *User `json:"merged_by"`
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"`
}
// ChangedFile is a changed file in a diff
type ChangedFile struct {
Filename string `json:"filename"`
PreviousFilename string `json:"previous_filename"`
Status string `json:"status"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
Changes int `json:"changes"`
HTMLURL string `json:"html_url"`
ContentsURL string `json:"contents_url"`
RawURL string `json:"raw_url"`
}
// ListPullRequestsOptions options for listing pull requests
type ListPullRequestsOptions struct {
ListOptions
State StateType `json:"state"`
// oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority
Sort string
Milestone int64
}
// MergeStyle is used specify how a pull is merged
type MergeStyle string
const (
// MergeStyleMerge merge pull as usual
MergeStyleMerge MergeStyle = "merge"
// MergeStyleRebase rebase pull
MergeStyleRebase MergeStyle = "rebase"
// MergeStyleRebaseMerge rebase and merge pull
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
// MergeStyleSquash squash and merge pull
MergeStyleSquash MergeStyle = "squash"
)
// QueryEncode turns options into querystring argument
func (opt *ListPullRequestsOptions) QueryEncode() string {
query := opt.getURLQuery()
if len(opt.State) > 0 {
query.Add("state", string(opt.State))
}
if len(opt.Sort) > 0 {
query.Add("sort", opt.Sort)
}
if opt.Milestone > 0 {
query.Add("milestone", fmt.Sprintf("%d", opt.Milestone))
}
return query.Encode()
}
// ListRepoPullRequests list PRs of one repository
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
prs := make([]*PullRequest, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo))
link.RawQuery = opt.QueryEncode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs)
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
for i := range prs {
if err := fixPullHeadSha(c, prs[i]); err != nil {
return prs, resp, err
}
}
}
return prs, resp, err
}
// GetPullRequest get information of one PR
func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
pr := new(PullRequest)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr)
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
if err := fixPullHeadSha(c, pr); err != nil {
return pr, resp, err
}
}
return pr, resp, err
}
// CreatePullRequestOption options when creating a pull request
type CreatePullRequestOption struct {
Head string `json:"head"`
Base string `json:"base"`
Title string `json:"title"`
Body string `json:"body"`
Assignee string `json:"assignee"`
Assignees []string `json:"assignees"`
Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"`
Deadline *time.Time `json:"due_date"`
}
// CreatePullRequest create pull request with options
func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
pr := new(PullRequest)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/pulls", owner, repo),
jsonHeader, bytes.NewReader(body), pr)
return pr, resp, err
}
// EditPullRequestOption options when modify pull request
type EditPullRequestOption struct {
Title string `json:"title"`
Body string `json:"body"`
Base string `json:"base"`
Assignee string `json:"assignee"`
Assignees []string `json:"assignees"`
Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"`
State *StateType `json:"state"`
Deadline *time.Time `json:"due_date"`
RemoveDeadline *bool `json:"unset_due_date"`
AllowMaintainerEdit *bool `json:"allow_maintainer_edit"`
}
// Validate the EditPullRequestOption struct
func (opt EditPullRequestOption) Validate(c *Client) error {
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
return fmt.Errorf("title is empty")
}
if len(opt.Base) != 0 {
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return fmt.Errorf("can not change base gitea to old")
}
}
return nil
}
// EditPullRequest modify pull request with PR id and options
func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
pr := new(PullRequest)
resp, err := c.getParsedResponse("PATCH",
fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index),
jsonHeader, bytes.NewReader(body), pr)
return pr, resp, err
}
// MergePullRequestOption options when merging a pull request
type MergePullRequestOption struct {
Style MergeStyle `json:"Do"`
MergeCommitID string `json:"MergeCommitID"`
Title string `json:"MergeTitleField"`
Message string `json:"MergeMessageField"`
DeleteBranchAfterMerge bool `json:"delete_branch_after_merge"`
ForceMerge bool `json:"force_merge"`
HeadCommitId string `json:"head_commit_id"`
MergeWhenChecksSucceed bool `json:"merge_when_checks_succeed"`
}
// Validate the MergePullRequestOption struct
func (opt MergePullRequestOption) Validate(c *Client) error {
if opt.Style == MergeStyleSquash {
if err := c.checkServerVersionGreaterThanOrEqual(version1_11_5); err != nil {
return err
}
}
return nil
}
// MergePullRequest merge a PR to repository by PR id
func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return false, nil, err
}
if err := opt.Validate(c); err != nil {
return false, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), jsonHeader, bytes.NewReader(body))
if err != nil {
return false, resp, err
}
return status == 200, resp, nil
}
// IsPullRequestMerged test if one PR is merged to one repository
func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
if err != nil {
return false, resp, err
}
return status == 204, resp, nil
}
// PullRequestDiffOptions options for GET /repos/<owner>/<repo>/pulls/<idx>.[diff|patch]
type PullRequestDiffOptions struct {
// Include binary file changes when requesting a .diff
Binary bool
}
// QueryEncode converts the options to a query string
func (o PullRequestDiffOptions) QueryEncode() string {
query := make(url.Values)
query.Add("binary", fmt.Sprintf("%v", o.Binary))
return query.Encode()
}
type pullRequestDiffType string
const (
pullRequestDiffTypeDiff pullRequestDiffType = "diff"
pullRequestDiffTypePatch pullRequestDiffType = "patch"
)
// getPullRequestDiffOrPatch gets the patch or diff file as bytes for a PR
func (c *Client) getPullRequestDiffOrPatch(owner, repo string, kind pullRequestDiffType, index int64, opts PullRequestDiffOptions) ([]byte, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
r, _, err2 := c.GetRepo(owner, repo)
if err2 != nil {
return nil, nil, err
}
if r.Private {
return nil, nil, err
}
url := fmt.Sprintf("/%s/%s/pulls/%d.%s?%s", owner, repo, index, kind, opts.QueryEncode())
return c.getWebResponse("GET", url, nil)
}
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil, nil)
}
// GetPullRequestPatch gets the git patchset of a PR
func (c *Client) GetPullRequestPatch(owner, repo string, index int64) ([]byte, *Response, error) {
return c.getPullRequestDiffOrPatch(owner, repo, pullRequestDiffTypePatch, index, PullRequestDiffOptions{})
}
// GetPullRequestDiff gets the diff of a PR. For Gitea >= 1.16, you must set includeBinary to get an applicable diff
func (c *Client) GetPullRequestDiff(owner, repo string, index int64, opts PullRequestDiffOptions) ([]byte, *Response, error) {
return c.getPullRequestDiffOrPatch(owner, repo, pullRequestDiffTypeDiff, index, opts)
}
// ListPullRequestCommitsOptions options for listing pull requests
type ListPullRequestCommitsOptions struct {
ListOptions
}
// ListPullRequestCommits list commits for a pull request
func (c *Client) ListPullRequestCommits(owner, repo string, index int64, opt ListPullRequestCommitsOptions) ([]*Commit, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/commits", owner, repo, index))
opt.setDefaults()
commits := make([]*Commit, 0, opt.PageSize)
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
return commits, resp, err
}
// fixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
// When no head sha is available, this is because the branch got deleted in the base repo.
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
// which stays available to resolve the commit sha. This is fixed for gitea >= 1.14.0
func fixPullHeadSha(client *Client, pr *PullRequest) error {
if pr.Base != nil && pr.Base.Repository != nil && pr.Base.Repository.Owner != nil &&
pr.Head != nil && pr.Head.Ref != "" && pr.Head.Sha == "" {
owner := pr.Base.Repository.Owner.UserName
repo := pr.Base.Repository.Name
refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
if err != nil {
return err
} else if len(refs) == 0 {
return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
}
pr.Head.Sha = refs[0].Object.SHA
}
return nil
}
// ListPullRequestFilesOptions options for listing pull request files
type ListPullRequestFilesOptions struct {
ListOptions
}
// ListPullRequestFiles list changed files for a pull request
func (c *Client) ListPullRequestFiles(owner, repo string, index int64, opt ListPullRequestFilesOptions) ([]*ChangedFile, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/files", owner, repo, index))
opt.setDefaults()
files := make([]*ChangedFile, 0, opt.PageSize)
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &files)
return files, resp, err
}

325
vendor/code.gitea.io/sdk/gitea/pull_review.go generated vendored Normal file
View File

@ -0,0 +1,325 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
)
// ReviewStateType review state type
type ReviewStateType string
const (
// ReviewStateApproved pr is approved
ReviewStateApproved ReviewStateType = "APPROVED"
// ReviewStatePending pr state is pending
ReviewStatePending ReviewStateType = "PENDING"
// ReviewStateComment is a comment review
ReviewStateComment ReviewStateType = "COMMENT"
// ReviewStateRequestChanges changes for pr are requested
ReviewStateRequestChanges ReviewStateType = "REQUEST_CHANGES"
// ReviewStateRequestReview review is requested from user
ReviewStateRequestReview ReviewStateType = "REQUEST_REVIEW"
// ReviewStateUnknown state of pr is unknown
ReviewStateUnknown ReviewStateType = ""
)
// PullReview represents a pull request review
type PullReview struct {
ID int64 `json:"id"`
Reviewer *User `json:"user"`
ReviewerTeam *Team `json:"team"`
State ReviewStateType `json:"state"`
Body string `json:"body"`
CommitID string `json:"commit_id"`
// Stale indicates if the pull has changed since the review
Stale bool `json:"stale"`
// Official indicates if the review counts towards the required approval limit, if PR base is a protected branch
Official bool `json:"official"`
Dismissed bool `json:"dismissed"`
CodeCommentsCount int `json:"comments_count"`
Submitted time.Time `json:"submitted_at"`
HTMLURL string `json:"html_url"`
HTMLPullURL string `json:"pull_request_url"`
}
// PullReviewComment represents a comment on a pull request review
type PullReviewComment struct {
ID int64 `json:"id"`
Body string `json:"body"`
Reviewer *User `json:"user"`
ReviewID int64 `json:"pull_request_review_id"`
Resolver *User `json:"resolver"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
Path string `json:"path"`
CommitID string `json:"commit_id"`
OrigCommitID string `json:"original_commit_id"`
DiffHunk string `json:"diff_hunk"`
LineNum uint64 `json:"position"`
OldLineNum uint64 `json:"original_position"`
HTMLURL string `json:"html_url"`
HTMLPullURL string `json:"pull_request_url"`
}
// CreatePullReviewOptions are options to create a pull review
type CreatePullReviewOptions struct {
State ReviewStateType `json:"event"`
Body string `json:"body"`
CommitID string `json:"commit_id"`
Comments []CreatePullReviewComment `json:"comments"`
}
// CreatePullReviewComment represent a review comment for creation api
type CreatePullReviewComment struct {
// the tree path
Path string `json:"path"`
Body string `json:"body"`
// if comment to old file line or 0
OldLineNum int64 `json:"old_position"`
// if comment to new file line or 0
NewLineNum int64 `json:"new_position"`
}
// SubmitPullReviewOptions are options to submit a pending pull review
type SubmitPullReviewOptions struct {
State ReviewStateType `json:"event"`
Body string `json:"body"`
}
// DismissPullReviewOptions are options to dismiss a pull review
type DismissPullReviewOptions struct {
Message string `json:"message"`
}
// PullReviewRequestOptions are options to add or remove pull review requests
type PullReviewRequestOptions struct {
Reviewers []string `json:"reviewers"`
TeamReviewers []string `json:"team_reviewers"`
}
// ListPullReviewsOptions options for listing PullReviews
type ListPullReviewsOptions struct {
ListOptions
}
// Validate the CreatePullReviewOptions struct
func (opt CreatePullReviewOptions) Validate() error {
if opt.State != ReviewStateApproved && len(opt.Comments) == 0 && len(strings.TrimSpace(opt.Body)) == 0 {
return fmt.Errorf("body is empty")
}
for i := range opt.Comments {
if err := opt.Comments[i].Validate(); err != nil {
return err
}
}
return nil
}
// Validate the SubmitPullReviewOptions struct
func (opt SubmitPullReviewOptions) Validate() error {
if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 {
return fmt.Errorf("body is empty")
}
return nil
}
// Validate the CreatePullReviewComment struct
func (opt CreatePullReviewComment) Validate() error {
if len(strings.TrimSpace(opt.Body)) == 0 {
return fmt.Errorf("body is empty")
}
if opt.NewLineNum != 0 && opt.OldLineNum != 0 {
return fmt.Errorf("old and new line num are set, cant identify the code comment position")
}
return nil
}
// ListPullReviews lists all reviews of a pull request
func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
opt.setDefaults()
rs := make([]*PullReview, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index))
link.RawQuery = opt.ListOptions.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rs)
return rs, resp, err
}
// GetPullReview gets a specific review of a pull request
func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
r := new(PullReview)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil, &r)
return r, resp, err
}
// ListPullReviewComments lists all comments of a pull request review
func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]*PullReviewComment, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
rcl := make([]*PullReviewComment, 0, 4)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/comments", owner, repo, index, id))
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rcl)
return rcl, resp, err
}
// DeletePullReview delete a specific review from a pull request
func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil)
return resp, err
}
// CreatePullReview create a review to an pull request
func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
r := new(PullReview)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index),
jsonHeader, bytes.NewReader(body), r)
return r, resp, err
}
// SubmitPullReview submit a pending review to an pull request
func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
r := new(PullReview)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id),
jsonHeader, bytes.NewReader(body), r)
return r, resp, err
}
// CreateReviewRequests create review requests to an pull request
func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST",
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
jsonHeader, bytes.NewReader(body))
return resp, err
}
// DeleteReviewRequests delete review requests to an pull request
func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
jsonHeader, bytes.NewReader(body))
return resp, err
}
// DismissPullReview dismiss a review for a pull request
func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt DismissPullReviewOptions) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST",
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id),
jsonHeader, bytes.NewReader(body))
return resp, err
}
// UnDismissPullReview cancel to dismiss a review for a pull request
func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST",
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id),
jsonHeader, nil)
return resp, err
}

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

@ -0,0 +1,214 @@
// Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
)
// Release represents a repository release
type Release struct {
ID int64 `json:"id"`
TagName string `json:"tag_name"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
TarURL string `json:"tarball_url"`
ZipURL string `json:"zipball_url"`
IsDraft bool `json:"draft"`
IsPrerelease bool `json:"prerelease"`
CreatedAt time.Time `json:"created_at"`
PublishedAt time.Time `json:"published_at"`
Publisher *User `json:"author"`
Attachments []*Attachment `json:"assets"`
}
// ListReleasesOptions options for listing repository's releases
type ListReleasesOptions struct {
ListOptions
IsDraft *bool
IsPreRelease *bool
}
// QueryEncode turns options into querystring argument
func (opt *ListReleasesOptions) QueryEncode() string {
query := opt.getURLQuery()
if opt.IsDraft != nil {
query.Add("draft", fmt.Sprintf("%t", *opt.IsDraft))
}
if opt.IsPreRelease != nil {
query.Add("pre-release", fmt.Sprintf("%t", *opt.IsPreRelease))
}
return query.Encode()
}
// ListReleases list releases of a repository
func (c *Client) ListReleases(owner, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
releases := make([]*Release, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases?%s", owner, repo, opt.QueryEncode()),
nil, nil, &releases)
return releases, resp, err
}
// GetRelease get a release of a repository by id
func (c *Client) GetRelease(owner, repo string, id int64) (*Release, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
r := new(Release)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
jsonHeader, nil, &r)
return r, resp, err
}
// GetLatestRelease get the latest release of a repository
func (c *Client) GetLatestRelease(owner, repo string) (*Release, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
r := new(Release)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/latest", owner, repo),
jsonHeader, nil, &r)
return r, resp, err
}
// GetReleaseByTag get a release of a repository by tag
func (c *Client) GetReleaseByTag(owner, repo, tag string) (*Release, *Response, error) {
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
return c.fallbackGetReleaseByTag(owner, repo, tag)
}
if err := escapeValidatePathSegments(&owner, &repo, &tag); err != nil {
return nil, nil, err
}
r := new(Release)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", owner, repo, tag),
nil, nil, &r)
return r, resp, err
}
// CreateReleaseOption options when creating a release
type CreateReleaseOption struct {
TagName string `json:"tag_name"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
IsDraft bool `json:"draft"`
IsPrerelease bool `json:"prerelease"`
}
// Validate the CreateReleaseOption struct
func (opt CreateReleaseOption) Validate() error {
if len(strings.TrimSpace(opt.Title)) == 0 {
return fmt.Errorf("title is empty")
}
return nil
}
// CreateRelease create a release
func (c *Client) CreateRelease(owner, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(opt)
if err != nil {
return nil, nil, err
}
r := new(Release)
resp, err := c.getParsedResponse("POST",
fmt.Sprintf("/repos/%s/%s/releases", owner, repo),
jsonHeader, bytes.NewReader(body), r)
return r, resp, err
}
// EditReleaseOption options when editing a release
type EditReleaseOption struct {
TagName string `json:"tag_name"`
Target string `json:"target_commitish"`
Title string `json:"name"`
Note string `json:"body"`
IsDraft *bool `json:"draft"`
IsPrerelease *bool `json:"prerelease"`
}
// EditRelease edit a release
func (c *Client) EditRelease(owner, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(form)
if err != nil {
return nil, nil, err
}
r := new(Release)
resp, err := c.getParsedResponse("PATCH",
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
jsonHeader, bytes.NewReader(body), r)
return r, resp, err
}
// DeleteRelease delete a release from a repository, keeping its tag
func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
nil, nil)
return resp, err
}
// DeleteReleaseByTag deletes a release frm a repository by tag
func (c *Client) DeleteReleaseByTag(user, repo, tag string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
nil, nil)
return resp, err
}
// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 )
func (c *Client) fallbackGetReleaseByTag(owner, repo, tag string) (*Release, *Response, error) {
for i := 1; ; i++ {
rl, resp, err := c.ListReleases(owner, repo, ListReleasesOptions{ListOptions: ListOptions{Page: i}})
if err != nil {
return nil, resp, err
}
if len(rl) == 0 {
return nil,
newResponse(&http.Response{StatusCode: 404}),
fmt.Errorf("release with tag '%s' not found", tag)
}
for _, r := range rl {
if r.TagName == tag {
return r, resp, nil
}
}
}
}

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

@ -0,0 +1,546 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/url"
"strings"
"time"
)
// Permission represents a set of permissions
type Permission struct {
Admin bool `json:"admin"`
Push bool `json:"push"`
Pull bool `json:"pull"`
}
// InternalTracker represents settings for internal tracker
type InternalTracker struct {
// Enable time tracking (Built-in issue tracker)
EnableTimeTracker bool `json:"enable_time_tracker"`
// Let only contributors track time (Built-in issue tracker)
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
// Enable dependencies for issues and pull requests (Built-in issue tracker)
EnableIssueDependencies bool `json:"enable_issue_dependencies"`
}
// ExternalTracker represents settings for external tracker
type ExternalTracker struct {
// URL of external issue tracker.
ExternalTrackerURL string `json:"external_tracker_url"`
// External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.
ExternalTrackerFormat string `json:"external_tracker_format"`
// External Issue Tracker Number Format, either `numeric` or `alphanumeric`
ExternalTrackerStyle string `json:"external_tracker_style"`
}
// ExternalWiki represents setting for external wiki
type ExternalWiki struct {
// URL of external wiki.
ExternalWikiURL string `json:"external_wiki_url"`
}
// Repository represents a repository
type Repository struct {
ID int64 `json:"id"`
Owner *User `json:"owner"`
Name string `json:"name"`
FullName string `json:"full_name"`
Description string `json:"description"`
Empty bool `json:"empty"`
Private bool `json:"private"`
Fork bool `json:"fork"`
Template bool `json:"template"`
Parent *Repository `json:"parent"`
Mirror bool `json:"mirror"`
Size int `json:"size"`
HTMLURL string `json:"html_url"`
SSHURL string `json:"ssh_url"`
CloneURL string `json:"clone_url"`
OriginalURL string `json:"original_url"`
Website string `json:"website"`
Stars int `json:"stars_count"`
Forks int `json:"forks_count"`
Watchers int `json:"watchers_count"`
OpenIssues int `json:"open_issues_count"`
OpenPulls int `json:"open_pr_counter"`
Releases int `json:"release_counter"`
DefaultBranch string `json:"default_branch"`
Archived bool `json:"archived"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
Permissions *Permission `json:"permissions,omitempty"`
HasIssues bool `json:"has_issues"`
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
HasWiki bool `json:"has_wiki"`
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
HasPullRequests bool `json:"has_pull_requests"`
HasProjects bool `json:"has_projects"`
HasReleases bool `json:"has_releases,omitempty"`
HasPackages bool `json:"has_packages,omitempty"`
HasActions bool `json:"has_actions,omitempty"`
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
AllowMerge bool `json:"allow_merge_commits"`
AllowRebase bool `json:"allow_rebase"`
AllowRebaseMerge bool `json:"allow_rebase_explicit"`
AllowSquash bool `json:"allow_squash_merge"`
AvatarURL string `json:"avatar_url"`
Internal bool `json:"internal"`
MirrorInterval string `json:"mirror_interval"`
MirrorUpdated time.Time `json:"mirror_updated,omitempty"`
DefaultMergeStyle MergeStyle `json:"default_merge_style"`
}
// RepoType represent repo type
type RepoType string
const (
// RepoTypeNone dont specify a type
RepoTypeNone RepoType = ""
// RepoTypeSource is the default repo type
RepoTypeSource RepoType = "source"
// RepoTypeFork is a repo witch was forked from an other one
RepoTypeFork RepoType = "fork"
// RepoTypeMirror represents an mirror repo
RepoTypeMirror RepoType = "mirror"
)
// TrustModel represent how git signatures are handled in a repository
type TrustModel string
const (
// TrustModelDefault use TM set by global config
TrustModelDefault TrustModel = "default"
// TrustModelCollaborator gpg signature has to be owned by a repo collaborator
TrustModelCollaborator TrustModel = "collaborator"
// TrustModelCommitter gpg signature has to match committer
TrustModelCommitter TrustModel = "committer"
// TrustModelCollaboratorCommitter gpg signature has to match committer and owned by a repo collaborator
TrustModelCollaboratorCommitter TrustModel = "collaboratorcommitter"
)
// ListReposOptions options for listing repositories
type ListReposOptions struct {
ListOptions
}
// ListMyRepos lists all repositories for the authenticated user that has access to.
func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, *Response, error) {
opt.setDefaults()
repos := make([]*Repository, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/repos?%s", opt.getURLQuery().Encode()), nil, nil, &repos)
return repos, resp, err
}
// ListUserRepos list all repositories of one user by user's name
func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
opt.setDefaults()
repos := make([]*Repository, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos)
return repos, resp, err
}
// ListOrgReposOptions options for a organization's repositories
type ListOrgReposOptions struct {
ListOptions
}
// ListOrgRepos list all repositories of one organization by organization's name
func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
opt.setDefaults()
repos := make([]*Repository, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos)
return repos, resp, err
}
// SearchRepoOptions options for searching repositories
type SearchRepoOptions struct {
ListOptions
// The keyword to query
Keyword string
// Limit search to repositories with keyword as topic
KeywordIsTopic bool
// Include search of keyword within repository description
KeywordInDescription bool
/*
User Filter
*/
// Repo Owner
OwnerID int64
// Stared By UserID
StarredByUserID int64
/*
Repo Attributes
*/
// pubic, private or all repositories (defaults to all)
IsPrivate *bool
// archived, non-archived or all repositories (defaults to all)
IsArchived *bool
// Exclude template repos from search
ExcludeTemplate bool
// Filter by "fork", "source", "mirror"
Type RepoType
/*
Sort Filters
*/
// sort repos by attribute. Supported values are "alpha", "created", "updated", "size", and "id". Default is "alpha"
Sort string
// sort order, either "asc" (ascending) or "desc" (descending). Default is "asc", ignored if "sort" is not specified.
Order string
// Repo owner to prioritize in the results
PrioritizedByOwnerID int64
/*
Cover EdgeCases
*/
// if set all other options are ignored and this string is used as query
RawQuery string
}
// QueryEncode turns options into querystring argument
func (opt *SearchRepoOptions) QueryEncode() string {
query := opt.getURLQuery()
if opt.Keyword != "" {
query.Add("q", opt.Keyword)
}
if opt.KeywordIsTopic {
query.Add("topic", "true")
}
if opt.KeywordInDescription {
query.Add("includeDesc", "true")
}
// User Filter
if opt.OwnerID > 0 {
query.Add("uid", fmt.Sprintf("%d", opt.OwnerID))
query.Add("exclusive", "true")
}
if opt.StarredByUserID > 0 {
query.Add("starredBy", fmt.Sprintf("%d", opt.StarredByUserID))
}
// Repo Attributes
if opt.IsPrivate != nil {
query.Add("is_private", fmt.Sprintf("%v", opt.IsPrivate))
}
if opt.IsArchived != nil {
query.Add("archived", fmt.Sprintf("%v", opt.IsArchived))
}
if opt.ExcludeTemplate {
query.Add("template", "false")
}
if len(opt.Type) != 0 {
query.Add("mode", string(opt.Type))
}
// Sort Filters
if opt.Sort != "" {
query.Add("sort", opt.Sort)
}
if opt.PrioritizedByOwnerID > 0 {
query.Add("priority_owner_id", fmt.Sprintf("%d", opt.PrioritizedByOwnerID))
}
if opt.Order != "" {
query.Add("order", opt.Order)
}
return query.Encode()
}
type searchRepoResponse struct {
Repos []*Repository `json:"data"`
}
// SearchRepos searches for repositories matching the given filters
func (c *Client) SearchRepos(opt SearchRepoOptions) ([]*Repository, *Response, error) {
opt.setDefaults()
repos := new(searchRepoResponse)
link, _ := url.Parse("/repos/search")
if len(opt.RawQuery) != 0 {
link.RawQuery = opt.RawQuery
} else {
link.RawQuery = opt.QueryEncode()
// IsPrivate only works on gitea >= 1.12.0
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil && opt.IsPrivate != nil {
if *opt.IsPrivate {
// private repos only not supported on gitea <= 1.11.x
return nil, nil, err
}
newQuery := link.Query()
newQuery.Add("private", "false")
link.RawQuery = newQuery.Encode()
}
}
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &repos)
return repos.Repos, resp, err
}
// CreateRepoOption options when creating repository
type CreateRepoOption struct {
// Name of the repository to create
Name string `json:"name"`
// Description of the repository to create
Description string `json:"description"`
// Whether the repository is private
Private bool `json:"private"`
// Issue Label set to use
IssueLabels string `json:"issue_labels"`
// Whether the repository should be auto-intialized?
AutoInit bool `json:"auto_init"`
// Whether the repository is template
Template bool `json:"template"`
// Gitignores to use
Gitignores string `json:"gitignores"`
// License to use
License string `json:"license"`
// Readme of the repository to create
Readme string `json:"readme"`
// DefaultBranch of the repository (used when initializes and in template)
DefaultBranch string `json:"default_branch"`
// TrustModel of the repository
TrustModel TrustModel `json:"trust_model"`
}
// Validate the CreateRepoOption struct
func (opt CreateRepoOption) Validate(c *Client) error {
if len(strings.TrimSpace(opt.Name)) == 0 {
return fmt.Errorf("name is empty")
}
if len(opt.Name) > 100 {
return fmt.Errorf("name has more than 100 chars")
}
if len(opt.Description) > 2048 {
return fmt.Errorf("description has more than 2048 chars")
}
if len(opt.DefaultBranch) > 100 {
return fmt.Errorf("default branch name has more than 100 chars")
}
if len(opt.TrustModel) != 0 {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return err
}
}
return nil
}
// CreateRepo creates a repository for authenticated user.
func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, *Response, error) {
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo)
return repo, resp, err
}
// CreateOrgRepo creates an organization repository for authenticated user.
func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&org); err != nil {
return nil, nil, err
}
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo)
return repo, resp, err
}
// GetRepo returns information of a repository of given owner.
func (c *Client) GetRepo(owner, reponame string) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
return repo, resp, err
}
// GetRepoByID returns information of a repository by a giver repository ID.
func (c *Client) GetRepoByID(id int64) (*Repository, *Response, error) {
repo := new(Repository)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repositories/%d", id), nil, nil, repo)
return repo, resp, err
}
// EditRepoOption options when editing a repository's properties
type EditRepoOption struct {
// name of the repository
Name *string `json:"name,omitempty"`
// a short description of the repository.
Description *string `json:"description,omitempty"`
// a URL with more information about the repository.
Website *string `json:"website,omitempty"`
// either `true` to make the repository private or `false` to make it public.
// Note: you will get a 422 error if the organization restricts changing repository visibility to organization
// owners and a non-owner tries to change the value of private.
Private *bool `json:"private,omitempty"`
// either `true` to make this repository a template or `false` to make it a normal repository
Template *bool `json:"template,omitempty"`
// either `true` to enable issues for this repository or `false` to disable them.
HasIssues *bool `json:"has_issues,omitempty"`
// set this structure to configure internal issue tracker (requires has_issues)
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
// set this structure to use external issue tracker (requires has_issues)
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
// either `true` to enable the wiki for this repository or `false` to disable it.
HasWiki *bool `json:"has_wiki,omitempty"`
// set this structure to use external wiki instead of internal (requires has_wiki)
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
// sets the default branch for this repository.
DefaultBranch *string `json:"default_branch,omitempty"`
// either `true` to allow pull requests, or `false` to prevent pull request.
HasPullRequests *bool `json:"has_pull_requests,omitempty"`
// either `true` to enable project unit, or `false` to disable them.
HasProjects *bool `json:"has_projects,omitempty"`
// either `true` to enable release, or `false` to disable them.
HasReleases *bool `json:"has_releases,omitempty"`
// either `true` to enable packages, or `false` to disable them.
HasPackages *bool `json:"has_packages,omitempty"`
// either `true` to enable actions, or `false` to disable them.
HasActions *bool `json:"has_actions,omitempty"`
// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`.
IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"`
// either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`.
AllowMerge *bool `json:"allow_merge_commits,omitempty"`
// either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging. `has_pull_requests` must be `true`.
AllowRebase *bool `json:"allow_rebase,omitempty"`
// either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits. `has_pull_requests` must be `true`.
AllowRebaseMerge *bool `json:"allow_rebase_explicit,omitempty"`
// either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging. `has_pull_requests` must be `true`.
AllowSquash *bool `json:"allow_squash_merge,omitempty"`
// set to `true` to archive this repository.
Archived *bool `json:"archived,omitempty"`
// set to a string like `8h30m0s` to set the mirror interval time
MirrorInterval *string `json:"mirror_interval,omitempty"`
// either `true` to allow mark pr as merged manually, or `false` to prevent it. `has_pull_requests` must be `true`.
AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
// either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur.
AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"`
// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`.
DefaultMergeStyle *MergeStyle `json:"default_merge_style,omitempty"`
// set to `true` to archive this repository.
}
// EditRepo edit the properties of a repository
func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
return repo, resp, err
}
// DeleteRepo deletes a repository of user or organization.
func (c *Client) DeleteRepo(owner, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
return resp, err
}
// MirrorSync adds a mirrored repository to the mirror sync queue.
func (c *Client) MirrorSync(owner, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil)
return resp, err
}
// GetRepoLanguages return language stats of a repo
func (c *Client) GetRepoLanguages(owner, repo string) (map[string]int64, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
langMap := make(map[string]int64)
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/languages", owner, repo), jsonHeader, nil)
if err != nil {
return nil, resp, err
}
if err = json.Unmarshal(data, &langMap); err != nil {
return nil, resp, err
}
return langMap, resp, nil
}
// ArchiveType represent supported archive formats by gitea
type ArchiveType string
const (
// ZipArchive represent zip format
ZipArchive ArchiveType = ".zip"
// TarGZArchive represent tar.gz format
TarGZArchive ArchiveType = ".tar.gz"
)
// GetArchive get an archive of a repository by git reference
// e.g.: ref -> master, 70b7c74b33, v1.2.1, ...
func (c *Client) GetArchive(owner, repo, ref string, ext ArchiveType) ([]byte, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
ref = pathEscapeSegments(ref)
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
}
// GetArchiveReader gets a `git archive` for a particular tree-ish git reference
// such as a branch name (`master`), a commit hash (`70b7c74b33`), a tag
// (`v1.2.1`). The archive is returned as a byte stream in a ReadCloser. It is
// the responsibility of the client to close the reader.
func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io.ReadCloser, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
ref = pathEscapeSegments(ref)
resp, err := c.doRequest("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
if err != nil {
return nil, resp, err
}
if _, err := statusCodeToErr(resp); err != nil {
return nil, resp, err
}
return resp.Body, resp, nil
}

66
vendor/code.gitea.io/sdk/gitea/repo_action.go generated vendored Normal file
View File

@ -0,0 +1,66 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
)
// ListRepoActionSecretOption list RepoActionSecret options
type ListRepoActionSecretOption struct {
ListOptions
}
// ListRepoActionSecret list a repository's secrets
func (c *Client) ListRepoActionSecret(user, repo string, opt ListRepoActionSecretOption) ([]*Secret, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
secrets := make([]*Secret, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/actions/secrets", user, repo))
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &secrets)
return secrets, resp, err
}
// CreateRepoActionSecret creates a secret for the specified repository in the Gitea Actions.
// It takes the organization name and the secret options as parameters.
// The function returns the HTTP response and an error, if any.
func (c *Client) CreateRepoActionSecret(user, repo string, opt CreateSecretOption) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
if err := (&opt).Validate(); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/actions/secrets/%s", user, repo, opt.Name), jsonHeader, bytes.NewReader(body))
if err != nil {
return nil, err
}
switch status {
case http.StatusCreated:
return resp, nil
case http.StatusNoContent:
return resp, nil
case http.StatusNotFound:
return resp, fmt.Errorf("forbidden")
case http.StatusBadRequest:
return resp, fmt.Errorf("bad request")
default:
return resp, fmt.Errorf("unexpected Status: %d", status)
}
}

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

@ -0,0 +1,143 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// PayloadUser represents the author or committer of a commit
type PayloadUser struct {
// Full name of the commit author
Name string `json:"name"`
Email string `json:"email"`
UserName string `json:"username"`
}
// PayloadCommit represents a commit
type PayloadCommit struct {
// sha1 hash of the commit
ID string `json:"id"`
Message string `json:"message"`
URL string `json:"url"`
Author *PayloadUser `json:"author"`
Committer *PayloadUser `json:"committer"`
Verification *PayloadCommitVerification `json:"verification"`
Timestamp time.Time `json:"timestamp"`
Added []string `json:"added"`
Removed []string `json:"removed"`
Modified []string `json:"modified"`
}
// PayloadCommitVerification represents the GPG verification of a commit
type PayloadCommitVerification struct {
Verified bool `json:"verified"`
Reason string `json:"reason"`
Signature string `json:"signature"`
Payload string `json:"payload"`
}
// Branch represents a repository branch
type Branch struct {
Name string `json:"name"`
Commit *PayloadCommit `json:"commit"`
Protected bool `json:"protected"`
RequiredApprovals int64 `json:"required_approvals"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
UserCanPush bool `json:"user_can_push"`
UserCanMerge bool `json:"user_can_merge"`
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
}
// ListRepoBranchesOptions options for listing a repository's branches
type ListRepoBranchesOptions struct {
ListOptions
}
// ListRepoBranches list all the branches of one repository
func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
branches := make([]*Branch, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches)
return branches, resp, err
}
// GetRepoBranch get one branch's information of one repository
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
return nil, nil, err
}
b := new(Branch)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
if err != nil {
return nil, resp, err
}
return b, resp, nil
}
// DeleteRepoBranch delete a branch in a repository
func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
return false, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil)
if err != nil {
return false, resp, err
}
return status == 204, resp, nil
}
// CreateBranchOption options when creating a branch in a repository
type CreateBranchOption struct {
// Name of the branch to create
BranchName string `json:"new_branch_name"`
// Name of the old branch to create from (optional)
OldBranchName string `json:"old_branch_name"`
}
// Validate the CreateBranchOption struct
func (opt CreateBranchOption) Validate() error {
if len(opt.BranchName) == 0 {
return fmt.Errorf("BranchName is empty")
}
if len(opt.BranchName) > 100 {
return fmt.Errorf("BranchName to long")
}
if len(opt.OldBranchName) > 100 {
return fmt.Errorf("OldBranchName to long")
}
return nil
}
// CreateBranch creates a branch for a user's repository
func (c *Client) CreateBranch(owner, repo string, opt CreateBranchOption) (*Branch, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
branch := new(Branch)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branches", owner, repo), jsonHeader, bytes.NewReader(body), branch)
return branch, resp, err
}

View File

@ -0,0 +1,173 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"time"
)
// BranchProtection represents a branch protection for a repository
type BranchProtection struct {
BranchName string `json:"branch_name"`
RuleName string `json:"rule_name"`
EnablePush bool `json:"enable_push"`
EnablePushWhitelist bool `json:"enable_push_whitelist"`
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
PushWhitelistTeams []string `json:"push_whitelist_teams"`
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
RequiredApprovals int64 `json:"required_approvals"`
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
RequireSignedCommits bool `json:"require_signed_commits"`
ProtectedFilePatterns string `json:"protected_file_patterns"`
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
Created time.Time `json:"created_at"`
Updated time.Time `json:"updated_at"`
}
// CreateBranchProtectionOption options for creating a branch protection
type CreateBranchProtectionOption struct {
BranchName string `json:"branch_name"`
RuleName string `json:"rule_name"`
EnablePush bool `json:"enable_push"`
EnablePushWhitelist bool `json:"enable_push_whitelist"`
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
PushWhitelistTeams []string `json:"push_whitelist_teams"`
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
RequiredApprovals int64 `json:"required_approvals"`
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
RequireSignedCommits bool `json:"require_signed_commits"`
ProtectedFilePatterns string `json:"protected_file_patterns"`
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
}
// EditBranchProtectionOption options for editing a branch protection
type EditBranchProtectionOption struct {
EnablePush *bool `json:"enable_push"`
EnablePushWhitelist *bool `json:"enable_push_whitelist"`
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
PushWhitelistTeams []string `json:"push_whitelist_teams"`
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
EnableStatusCheck *bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
RequiredApprovals *int64 `json:"required_approvals"`
EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"`
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"`
BlockOnOfficialReviewRequests *bool `json:"block_on_official_review_requests"`
BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"`
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
RequireSignedCommits *bool `json:"require_signed_commits"`
ProtectedFilePatterns *string `json:"protected_file_patterns"`
UnprotectedFilePatterns *string `json:"unprotected_file_patterns"`
}
// ListBranchProtectionsOptions list branch protection options
type ListBranchProtectionsOptions struct {
ListOptions
}
// ListBranchProtections list branch protections for a repo
func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
bps := make([]*BranchProtection, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo))
link.RawQuery = opt.getURLQuery().Encode()
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &bps)
return bps, resp, err
}
// GetBranchProtection gets a branch protection
func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
bp := new(BranchProtection)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil, bp)
return bp, resp, err
}
// CreateBranchProtection creates a branch protection for a repo
func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
bp := new(BranchProtection)
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo), jsonHeader, bytes.NewReader(body), bp)
return bp, resp, err
}
// EditBranchProtection edits a branch protection for a repo
func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
bp := new(BranchProtection)
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), bp)
return bp, resp, err
}
// DeleteBranchProtection deletes a branch protection for a repo
func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil)
return resp, err
}

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

@ -0,0 +1,163 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// ListCollaboratorsOptions options for listing a repository's collaborators
type ListCollaboratorsOptions struct {
ListOptions
}
// CollaboratorPermissionResult result type for CollaboratorPermission
type CollaboratorPermissionResult struct {
Permission AccessMode `json:"permission"`
Role string `json:"role_name"`
User *User `json:"user"`
}
// ListCollaborators list a repository's collaborators
func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
collaborators := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/collaborators?%s", user, repo, opt.getURLQuery().Encode()),
nil, nil, &collaborators)
return collaborators, resp, err
}
// IsCollaborator check if a user is a collaborator of a repository
func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
if err != nil {
return false, resp, err
}
if status == 204 {
return true, resp, nil
}
return false, resp, nil
}
// CollaboratorPermission gets collaborator permission of a repository
func (c *Client) CollaboratorPermission(user, repo, collaborator string) (*CollaboratorPermissionResult, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
return nil, nil, err
}
rv := new(CollaboratorPermissionResult)
resp, err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/collaborators/%s/permission", user, repo, collaborator),
nil,
nil,
rv)
if err != nil {
return nil, resp, err
}
if resp.StatusCode != 200 {
rv = nil
}
return rv, resp, nil
}
// AddCollaboratorOption options when adding a user as a collaborator of a repository
type AddCollaboratorOption struct {
Permission *AccessMode `json:"permission"`
}
// AccessMode represent the grade of access you have to something
type AccessMode string
const (
// AccessModeNone no access
AccessModeNone AccessMode = "none"
// AccessModeRead read access
AccessModeRead AccessMode = "read"
// AccessModeWrite write access
AccessModeWrite AccessMode = "write"
// AccessModeAdmin admin access
AccessModeAdmin AccessMode = "admin"
// AccessModeOwner owner
AccessModeOwner AccessMode = "owner"
)
// Validate the AddCollaboratorOption struct
func (opt *AddCollaboratorOption) Validate() error {
if opt.Permission != nil {
if *opt.Permission == AccessModeOwner {
*opt.Permission = AccessModeAdmin
return nil
}
if *opt.Permission == AccessModeNone {
opt.Permission = nil
return nil
}
if *opt.Permission != AccessModeRead && *opt.Permission != AccessModeWrite && *opt.Permission != AccessModeAdmin {
return fmt.Errorf("permission mode invalid")
}
}
return nil
}
// AddCollaborator add some user as a collaborator of a repository
func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
return nil, err
}
if err := (&opt).Validate(); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body))
return resp, err
}
// DeleteCollaborator remove a collaborator from a repository
func (c *Client) DeleteCollaborator(user, repo, collaborator string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
return resp, err
}
// GetReviewers return all users that can be requested to review in this repo
func (c *Client) GetReviewers(user, repo string) ([]*User, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
reviewers := make([]*User, 0, 5)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/reviewers", user, repo), nil, nil, &reviewers)
return reviewers, resp, err
}
// GetAssignees return all users that have write access and can be assigned to issues
func (c *Client) GetAssignees(user, repo string) ([]*User, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
assignees := make([]*User, 0, 5)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/assignees", user, repo), nil, nil, &assignees)
return assignees, resp, err
}

141
vendor/code.gitea.io/sdk/gitea/repo_commit.go generated vendored Normal file
View File

@ -0,0 +1,141 @@
// Copyright 2018 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/url"
"time"
)
// Identity for a person's identity like an author or committer
type Identity struct {
Name string `json:"name"`
Email string `json:"email"`
}
// CommitMeta contains meta information of a commit in terms of API.
type CommitMeta struct {
URL string `json:"url"`
SHA string `json:"sha"`
Created time.Time `json:"created"`
}
// CommitUser contains information of a user in the context of a commit.
type CommitUser struct {
Identity
Date string `json:"date"`
}
// RepoCommit contains information of a commit in the context of a repository.
type RepoCommit struct {
URL string `json:"url"`
Author *CommitUser `json:"author"`
Committer *CommitUser `json:"committer"`
Message string `json:"message"`
Tree *CommitMeta `json:"tree"`
Verification *PayloadCommitVerification `json:"verification"`
}
// CommitStats contains stats from a Git commit
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"`
}
// GetSingleCommit returns a single commit
func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &commitID); err != nil {
return nil, nil, err
}
commit := new(Commit)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit)
return commit, resp, err
}
// ListCommitOptions list commit options
type ListCommitOptions struct {
ListOptions
// SHA or branch to start listing commits from (usually 'master')
SHA string
// Path indicates that only commits that include the path's file/dir should be returned.
Path string
}
// QueryEncode turns options into querystring argument
func (opt *ListCommitOptions) QueryEncode() string {
query := opt.getURLQuery()
if opt.SHA != "" {
query.Add("sha", opt.SHA)
}
if opt.Path != "" {
query.Add("path", opt.Path)
}
return query.Encode()
}
// ListRepoCommits return list of commits from a repo
func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/commits", user, repo))
opt.setDefaults()
commits := make([]*Commit, 0, opt.PageSize)
link.RawQuery = opt.QueryEncode()
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
return commits, resp, err
}
// GetCommitDiff returns the commit's raw diff.
func (c *Client) GetCommitDiff(user, repo, commitID string) ([]byte, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s.%s", user, repo, commitID, pullRequestDiffTypeDiff), nil, nil)
}
// GetCommitPatch returns the commit's raw patch.
func (c *Client) GetCommitPatch(user, repo, commitID string) ([]byte, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s.%s", user, repo, commitID, pullRequestDiffTypePatch), nil, nil)
}

33
vendor/code.gitea.io/sdk/gitea/repo_compare.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import "fmt"
// 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.
}
// CompareCommits compares two commits in a repository.
func (c *Client) CompareCommits(user, repo, prev, current string) (*Compare, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_22_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo, &prev, &current); err != nil {
return nil, nil, err
}
basehead := fmt.Sprintf("%s...%s", prev, current)
apiResp := new(Compare)
resp, err := c.getParsedResponse(
"GET",
fmt.Sprintf("/repos/%s/%s/compare/%s", user, repo, basehead),
nil, nil, apiResp,
)
return apiResp, resp, err
}

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

@ -0,0 +1,277 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/url"
"strings"
)
// FileOptions options for all file APIs
type FileOptions struct {
// message (optional) for the commit of this file. if not supplied, a default message will be used
Message string `json:"message"`
// branch (optional) to base this file from. if not given, the default branch is used
BranchName string `json:"branch"`
// new_branch (optional) will make a new branch from `branch` before creating the file
NewBranchName string `json:"new_branch"`
// `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
Author Identity `json:"author"`
Committer Identity `json:"committer"`
Dates CommitDateOptions `json:"dates"`
// Add a Signed-off-by trailer by the committer at the end of the commit log message.
Signoff bool `json:"signoff"`
}
// CreateFileOptions options for creating files
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type CreateFileOptions struct {
FileOptions
// content must be base64 encoded
// required: true
Content string `json:"content"`
}
// DeleteFileOptions options for deleting files (used for other File structs below)
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type DeleteFileOptions struct {
FileOptions
// sha is the SHA for the file that already exists
// required: true
SHA string `json:"sha"`
}
// UpdateFileOptions options for updating files
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type UpdateFileOptions struct {
FileOptions
// sha is the SHA for the file that already exists
// required: true
SHA string `json:"sha"`
// content must be base64 encoded
// required: true
Content string `json:"content"`
// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL
FromPath string `json:"from_path"`
}
// FileLinksResponse contains the links for a repo's file
type FileLinksResponse struct {
Self *string `json:"self"`
GitURL *string `json:"git"`
HTMLURL *string `json:"html"`
}
// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content
type ContentsResponse struct {
Name string `json:"name"`
Path string `json:"path"`
SHA string `json:"sha"`
// `type` will be `file`, `dir`, `symlink`, or `submodule`
Type string `json:"type"`
Size int64 `json:"size"`
// `encoding` is populated when `type` is `file`, otherwise null
Encoding *string `json:"encoding"`
// `content` is populated when `type` is `file`, otherwise null
Content *string `json:"content"`
// `target` is populated when `type` is `symlink`, otherwise null
Target *string `json:"target"`
URL *string `json:"url"`
HTMLURL *string `json:"html_url"`
GitURL *string `json:"git_url"`
DownloadURL *string `json:"download_url"`
// `submodule_git_url` is populated when `type` is `submodule`, otherwise null
SubmoduleGitURL *string `json:"submodule_git_url"`
Links *FileLinksResponse `json:"_links"`
}
// FileCommitResponse contains information generated from a Git commit for a repo's file.
type FileCommitResponse struct {
CommitMeta
HTMLURL string `json:"html_url"`
Author *CommitUser `json:"author"`
Committer *CommitUser `json:"committer"`
Parents []*CommitMeta `json:"parents"`
Message string `json:"message"`
Tree *CommitMeta `json:"tree"`
}
// FileResponse contains information about a repo's file
type FileResponse struct {
Content *ContentsResponse `json:"content"`
Commit *FileCommitResponse `json:"commit"`
Verification *PayloadCommitVerification `json:"verification"`
}
// FileDeleteResponse contains information about a repo's file that was deleted
type FileDeleteResponse struct {
Content interface{} `json:"content"` // to be set to nil
Commit *FileCommitResponse `json:"commit"`
Verification *PayloadCommitVerification `json:"verification"`
}
// GetFile downloads a file of repository, ref can be branch/tag/commit.
// it optional can resolve lfs pointers and server the file instead
// e.g.: ref -> master, filepath -> README.md (no leading slash)
func (c *Client) GetFile(owner, repo, ref, filepath string, resolveLFS ...bool) ([]byte, *Response, error) {
reader, resp, err := c.GetFileReader(owner, repo, ref, filepath, resolveLFS...)
if reader == nil {
return nil, resp, err
}
defer reader.Close()
data, err2 := io.ReadAll(reader)
if err2 != nil {
return nil, resp, err2
}
return data, resp, err
}
// GetFileReader return reader for download a file of repository, ref can be branch/tag/commit.
// it optional can resolve lfs pointers and server the file instead
// e.g.: ref -> master, filepath -> README.md (no leading slash)
func (c *Client) GetFileReader(owner, repo, ref, filepath string, resolveLFS ...bool) (io.ReadCloser, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
// resolve lfs
if len(resolveLFS) != 0 && resolveLFS[0] {
if err := c.checkServerVersionGreaterThanOrEqual(version1_17_0); err != nil {
return nil, nil, err
}
return c.getResponseReader("GET", fmt.Sprintf("/repos/%s/%s/media/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), nil, nil)
}
// normal get
filepath = pathEscapeSegments(filepath)
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
ref = pathEscapeSegments(ref)
return c.getResponseReader("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", owner, repo, ref, filepath), nil, nil)
}
return c.getResponseReader("GET", fmt.Sprintf("/repos/%s/%s/raw/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), nil, nil)
}
// GetContents get the metadata and contents of a file in a repository
// ref is optional
func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, *Response, error) {
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
if err != nil {
return nil, resp, err
}
cr := new(ContentsResponse)
if json.Unmarshal(data, &cr) != nil {
return nil, resp, fmt.Errorf("expect file, got directory")
}
return cr, resp, err
}
// ListContents gets a list of entries in a dir
// ref is optional
func (c *Client) ListContents(owner, repo, ref, filepath string) ([]*ContentsResponse, *Response, error) {
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
if err != nil {
return nil, resp, err
}
crl := make([]*ContentsResponse, 0)
if json.Unmarshal(data, &crl) != nil {
return nil, resp, fmt.Errorf("expect directory, got file")
}
return crl, resp, err
}
func (c *Client) getDirOrFileContents(owner, repo, ref, filepath string) ([]byte, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
filepath = pathEscapeSegments(strings.TrimPrefix(filepath, "/"))
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), jsonHeader, nil)
}
// CreateFile create a file in a repository
func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, *Response, error) {
var err error
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
filepath = pathEscapeSegments(filepath)
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
fr := new(FileResponse)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
return fr, resp, err
}
// UpdateFile update a file in a repository
func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, *Response, error) {
var err error
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, nil, err
}
filepath = pathEscapeSegments(filepath)
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
fr := new(FileResponse)
resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
return fr, resp, err
}
// DeleteFile delete a file from repository
func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) (*Response, error) {
var err error
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
return nil, err
}
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
filepath = pathEscapeSegments(filepath)
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body))
if err != nil {
return resp, err
}
if status != 200 && status != 204 {
return resp, fmt.Errorf("unexpected Status: %d", status)
}
return resp, nil
}
func (c *Client) setDefaultBranchForOldVersions(owner, repo, branch string) (string, error) {
if len(branch) == 0 {
// Gitea >= 1.12.0 Use DefaultBranch on "", mimic this for older versions
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
r, _, err := c.GetRepo(owner, repo)
if err != nil {
return "", err
}
return r.DefaultBranch, nil
}
}
return branch, nil
}

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

@ -0,0 +1,91 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"time"
)
// DeployKey a deploy key
type DeployKey struct {
ID int64 `json:"id"`
KeyID int64 `json:"key_id"`
Key string `json:"key"`
URL string `json:"url"`
Title string `json:"title"`
Fingerprint string `json:"fingerprint"`
Created time.Time `json:"created_at"`
ReadOnly bool `json:"read_only"`
Repository *Repository `json:"repository,omitempty"`
}
// ListDeployKeysOptions options for listing a repository's deploy keys
type ListDeployKeysOptions struct {
ListOptions
KeyID int64
Fingerprint string
}
// QueryEncode turns options into querystring argument
func (opt *ListDeployKeysOptions) QueryEncode() string {
query := opt.getURLQuery()
if opt.KeyID > 0 {
query.Add("key_id", fmt.Sprintf("%d", opt.KeyID))
}
if len(opt.Fingerprint) > 0 {
query.Add("fingerprint", opt.Fingerprint)
}
return query.Encode()
}
// ListDeployKeys list all the deploy keys of one repository
func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/keys", user, repo))
opt.setDefaults()
link.RawQuery = opt.QueryEncode()
keys := make([]*DeployKey, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &keys)
return keys, resp, err
}
// GetDeployKey get one deploy key with key id
func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
key := new(DeployKey)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
return key, resp, err
}
// CreateDeployKey options when create one deploy key
func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
key := new(DeployKey)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key)
return key, resp, err
}
// DeleteDeployKey delete deploy key with key id
func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil)
return resp, err
}

132
vendor/code.gitea.io/sdk/gitea/repo_migrate.go generated vendored Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// GitServiceType represents a git service
type GitServiceType string
const (
// GitServicePlain represents a plain git service
GitServicePlain GitServiceType = "git"
// GitServiceGithub represents github.com
GitServiceGithub GitServiceType = "github"
// GitServiceGitlab represents a gitlab service
GitServiceGitlab GitServiceType = "gitlab"
// GitServiceGitea represents a gitea service
GitServiceGitea GitServiceType = "gitea"
// GitServiceGogs represents a gogs service
GitServiceGogs GitServiceType = "gogs"
)
// MigrateRepoOption options for migrating a repository from an external service
type MigrateRepoOption struct {
RepoName string `json:"repo_name"`
RepoOwner string `json:"repo_owner"`
// deprecated use RepoOwner
RepoOwnerID int64 `json:"uid"`
CloneAddr string `json:"clone_addr"`
Service GitServiceType `json:"service"`
AuthUsername string `json:"auth_username"`
AuthPassword string `json:"auth_password"`
AuthToken string `json:"auth_token"`
Mirror bool `json:"mirror"`
Private bool `json:"private"`
Description string `json:"description"`
Wiki bool `json:"wiki"`
Milestones bool `json:"milestones"`
Labels bool `json:"labels"`
Issues bool `json:"issues"`
PullRequests bool `json:"pull_requests"`
Releases bool `json:"releases"`
MirrorInterval string `json:"mirror_interval"`
LFS bool `json:"lfs"`
LFSEndpoint string `json:"lfs_endpoint"`
}
// Validate the MigrateRepoOption struct
func (opt *MigrateRepoOption) Validate(c *Client) error {
// check user options
if len(opt.CloneAddr) == 0 {
return fmt.Errorf("CloneAddr required")
}
if len(opt.RepoName) == 0 {
return fmt.Errorf("RepoName required")
} else if len(opt.RepoName) > 100 {
return fmt.Errorf("RepoName to long")
}
if len(opt.Description) > 2048 {
return fmt.Errorf("Description to long")
}
switch opt.Service {
case GitServiceGithub:
if len(opt.AuthToken) == 0 {
return fmt.Errorf("github requires token authentication")
}
case GitServiceGitlab, GitServiceGitea:
if len(opt.AuthToken) == 0 {
return fmt.Errorf("%s requires token authentication", opt.Service)
}
// Gitlab is supported since 1.12.0 but api cant handle it until 1.13.0
// https://github.com/go-gitea/gitea/pull/12672
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
return fmt.Errorf("migrate from service %s need gitea >= 1.13.0", opt.Service)
}
case GitServiceGogs:
if len(opt.AuthToken) == 0 {
return fmt.Errorf("gogs requires token authentication")
}
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
return fmt.Errorf("migrate from service gogs need gitea >= 1.14.0")
}
}
return nil
}
// MigrateRepo migrates a repository from other Git hosting sources for the authenticated user.
//
// To migrate a repository for a organization, the authenticated user must be a
// owner of the specified organization.
func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, *Response, error) {
if err := opt.Validate(c); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
if len(opt.AuthToken) != 0 {
// gitea <= 1.12 dont understand AuthToken
opt.AuthUsername = opt.AuthToken
opt.AuthPassword, opt.AuthToken = "", ""
}
if len(opt.RepoOwner) != 0 {
// gitea <= 1.12 dont understand RepoOwner
u, _, err := c.GetUserInfo(opt.RepoOwner)
if err != nil {
return nil, nil, err
}
opt.RepoOwnerID = u.ID
} else if opt.RepoOwnerID == 0 {
// gitea <= 1.12 require RepoOwnerID
u, _, err := c.GetMyUserInfo()
if err != nil {
return nil, nil, err
}
opt.RepoOwnerID = u.ID
}
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo)
return repo, resp, err
}

45
vendor/code.gitea.io/sdk/gitea/repo_mirror.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
type CreatePushMirrorOption struct {
Interval string `json:"interval"`
RemoteAddress string `json:"remote_address"`
RemotePassword string `json:"remote_password"`
RemoteUsername string `json:"remote_username"`
SyncONCommit bool `json:"sync_on_commit"`
}
// PushMirrorResponse returns a git push mirror
type PushMirrorResponse struct {
Created string `json:"created"`
Interval string `json:"interval"`
LastError string `json:"last_error"`
LastUpdate string `json:"last_update"`
RemoteAddress string `json:"remote_address"`
RemoteName string `json:"remote_name"`
RepoName string `json:"repo_name"`
SyncONCommit bool `json:"sync_on_commit"`
}
// PushMirrors add a push mirror to the repository
func (c *Client) PushMirrors(user, repo string, opt CreatePushMirrorOption) (*PushMirrorResponse, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
body, err := json.Marshal(opt)
if err != nil {
return nil, nil, err
}
pm := new(PushMirrorResponse)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/push_mirrors", user, repo), jsonHeader, bytes.NewReader(body), &pm)
return pm, resp, err
}

78
vendor/code.gitea.io/sdk/gitea/repo_refs.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"encoding/json"
"errors"
"fmt"
"strings"
)
// Reference represents a Git reference.
type Reference struct {
Ref string `json:"ref"`
URL string `json:"url"`
Object *GitObject `json:"object"`
}
// GitObject represents a Git object.
type GitObject struct {
Type string `json:"type"`
SHA string `json:"sha"`
URL string `json:"url"`
}
// GetRepoRef get one ref's information of one repository
func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
ref = strings.TrimPrefix(ref, "refs/")
ref = pathEscapeSegments(ref)
r := new(Reference)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil, &r)
if _, ok := err.(*json.UnmarshalTypeError); ok {
// Multiple refs
return nil, resp, errors.New("no exact match found for this ref")
} else if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// GetRepoRefs get list of ref's information of one repository
func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
ref = strings.TrimPrefix(ref, "refs/")
ref = pathEscapeSegments(ref)
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil)
if err != nil {
return nil, resp, err
}
// Attempt to unmarshal single returned ref.
r := new(Reference)
refErr := json.Unmarshal(data, r)
if refErr == nil {
return []*Reference{r}, resp, nil
}
// Attempt to unmarshal multiple refs.
var rs []*Reference
refsErr := json.Unmarshal(data, &rs)
if refsErr == nil {
if len(rs) == 0 {
return nil, resp, errors.New("unexpected response: an array of refs with length 0")
}
return rs, resp, nil
}
return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", refErr, refsErr)
}

96
vendor/code.gitea.io/sdk/gitea/repo_stars.go generated vendored Normal file
View File

@ -0,0 +1,96 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/http"
)
// ListStargazersOptions options for listing a repository's stargazers
type ListStargazersOptions struct {
ListOptions
}
// ListRepoStargazers list a repository's stargazers
func (c *Client) ListRepoStargazers(user, repo string, opt ListStargazersOptions) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
stargazers := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/stargazers?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &stargazers)
return stargazers, resp, err
}
// GetStarredRepos returns the repos that the given user has starred
func (c *Client) GetStarredRepos(user string) ([]*Repository, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
repos := make([]*Repository, 0, 10)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/starred", user), jsonHeader, nil, &repos)
return repos, resp, err
}
// GetMyStarredRepos returns the repos that the authenticated user has starred
func (c *Client) GetMyStarredRepos() ([]*Repository, *Response, error) {
repos := make([]*Repository, 0, 10)
resp, err := c.getParsedResponse("GET", "/user/starred", jsonHeader, nil, &repos)
return repos, resp, err
}
// IsRepoStarring returns whether the authenticated user has starred the repo or not
func (c *Client) IsRepoStarring(user, repo string) (bool, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return false, nil, err
}
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
if resp != nil {
switch resp.StatusCode {
case http.StatusNotFound:
return false, resp, nil
case http.StatusNoContent:
return true, resp, nil
default:
return false, resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
}
}
return false, nil, err
}
// StarRepo star specified repo as the authenticated user
func (c *Client) StarRepo(user, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
if resp != nil {
switch resp.StatusCode {
case http.StatusNoContent:
return resp, nil
default:
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
}
}
return nil, err
}
// UnStarRepo remove star to specified repo as the authenticated user
func (c *Client) UnStarRepo(user, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
if resp != nil {
switch resp.StatusCode {
case http.StatusNoContent:
return resp, nil
default:
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
}
}
return nil, err
}

130
vendor/code.gitea.io/sdk/gitea/repo_tag.go generated vendored Normal file
View File

@ -0,0 +1,130 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// Tag represents a repository tag
type Tag struct {
Name string `json:"name"`
Message string `json:"message"`
ID string `json:"id"`
Commit *CommitMeta `json:"commit"`
ZipballURL string `json:"zipball_url"`
TarballURL string `json:"tarball_url"`
}
// AnnotatedTag represents an annotated tag
type AnnotatedTag struct {
Tag string `json:"tag"`
SHA string `json:"sha"`
URL string `json:"url"`
Message string `json:"message"`
Tagger *CommitUser `json:"tagger"`
Object *AnnotatedTagObject `json:"object"`
Verification *PayloadCommitVerification `json:"verification"`
}
// AnnotatedTagObject contains meta information of the tag object
type AnnotatedTagObject struct {
Type string `json:"type"`
URL string `json:"url"`
SHA string `json:"sha"`
}
// ListRepoTagsOptions options for listing a repository's tags
type ListRepoTagsOptions struct {
ListOptions
}
// ListRepoTags list all the branches of one repository
func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
tags := make([]*Tag, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags)
return tags, resp, err
}
// GetTag get the tag of a repository
func (c *Client) GetTag(user, repo, tag string) (*Tag, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
return nil, nil, err
}
t := new(Tag)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag), nil, nil, &t)
return t, resp, err
}
// GetAnnotatedTag get the tag object of an annotated tag (not lightweight tags) of a repository
func (c *Client) GetAnnotatedTag(user, repo, sha string) (*AnnotatedTag, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
return nil, nil, err
}
t := new(AnnotatedTag)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/tags/%s", user, repo, sha), nil, nil, &t)
return t, resp, err
}
// CreateTagOption options when creating a tag
type CreateTagOption struct {
TagName string `json:"tag_name"`
Message string `json:"message"`
Target string `json:"target"`
}
// Validate validates CreateTagOption
func (opt CreateTagOption) Validate() error {
if len(opt.TagName) == 0 {
return fmt.Errorf("TagName is required")
}
return nil
}
// CreateTag create a new git tag in a repository
func (c *Client) CreateTag(user, repo string, opt CreateTagOption) (*Tag, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(opt)
if err != nil {
return nil, nil, err
}
t := new(Tag)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/tags", user, repo), jsonHeader, bytes.NewReader(body), &t)
return t, resp, err
}
// DeleteTag deletes a tag from a repository, if no release refers to it
func (c *Client) DeleteTag(user, repo, tag string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
return nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag),
nil, nil)
return resp, err
}

65
vendor/code.gitea.io/sdk/gitea/repo_team.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/http"
)
// GetRepoTeams return teams from a repository
func (c *Client) GetRepoTeams(user, repo string) ([]*Team, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
teams := make([]*Team, 0, 5)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams", user, repo), nil, nil, &teams)
return teams, resp, err
}
// AddRepoTeam add a team to a repository
func (c *Client) AddRepoTeam(user, repo, team string) (*Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, err
}
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
return resp, err
}
// RemoveRepoTeam delete a team from a repository
func (c *Client) RemoveRepoTeam(user, repo, team string) (*Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, err
}
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
return resp, err
}
// CheckRepoTeam check if team is assigned to repo by name and return it.
// If not assigned, it will return nil.
func (c *Client) CheckRepoTeam(user, repo, team string) (*Team, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
return nil, nil, err
}
t := new(Team)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil, &t)
if resp != nil && resp.StatusCode == http.StatusNotFound {
// if not found it's not an error, it indicates it's not assigned
return nil, resp, nil
}
return t, resp, err
}

65
vendor/code.gitea.io/sdk/gitea/repo_template.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// CreateRepoFromTemplateOption options when creating repository using a template
type CreateRepoFromTemplateOption struct {
// Owner is the organization or person who will own the new repository
Owner string `json:"owner"`
// Name of the repository to create
Name string `json:"name"`
// Description of the repository to create
Description string `json:"description"`
// Private is whether the repository is private
Private bool `json:"private"`
// GitContent include git content of default branch in template repo
GitContent bool `json:"git_content"`
// Topics include topics of template repo
Topics bool `json:"topics"`
// GitHooks include git hooks of template repo
GitHooks bool `json:"git_hooks"`
// Webhooks include webhooks of template repo
Webhooks bool `json:"webhooks"`
// Avatar include avatar of the template repo
Avatar bool `json:"avatar"`
// Labels include labels of template repo
Labels bool `json:"labels"`
}
// Validate validates CreateRepoFromTemplateOption
func (opt CreateRepoFromTemplateOption) Validate() error {
if len(opt.Owner) == 0 {
return fmt.Errorf("field Owner is required")
}
if len(opt.Name) == 0 {
return fmt.Errorf("field Name is required")
}
return nil
}
// CreateRepoFromTemplate create a repository using a template
func (c *Client) CreateRepoFromTemplate(templateOwner, templateRepo string, opt CreateRepoFromTemplateOption) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&templateOwner, &templateRepo); err != nil {
return nil, nil, err
}
if err := opt.Validate(); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/generate", templateOwner, templateRepo), jsonHeader, bytes.NewReader(body), &repo)
return repo, resp, err
}

68
vendor/code.gitea.io/sdk/gitea/repo_topics.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// ListRepoTopicsOptions options for listing repo's topics
type ListRepoTopicsOptions struct {
ListOptions
}
// topicsList represents a list of repo's topics
type topicsList struct {
Topics []string `json:"topics"`
}
// ListRepoTopics list all repository's topics
func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, nil, err
}
opt.setDefaults()
list := new(topicsList)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, list)
if err != nil {
return nil, resp, err
}
return list.Topics, resp, nil
}
// SetRepoTopics replaces the list of repo's topics
func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo); err != nil {
return nil, err
}
l := topicsList{Topics: list}
body, err := json.Marshal(&l)
if err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body))
return resp, err
}
// AddRepoTopic adds a topic to a repo's topics list
func (c *Client) AddRepoTopic(user, repo, topic string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
return resp, err
}
// DeleteRepoTopic deletes a topic from repo's topics list
func (c *Client) DeleteRepoTopic(user, repo, topic string) (*Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
return resp, err
}

62
vendor/code.gitea.io/sdk/gitea/repo_transfer.go generated vendored Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// TransferRepoOption options when transfer a repository's ownership
type TransferRepoOption struct {
// required: true
NewOwner string `json:"new_owner"`
// ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.
TeamIDs *[]int64 `json:"team_ids"`
}
// TransferRepo transfers the ownership of a repository
func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
return repo, resp, err
}
// AcceptRepoTransfer accepts a repo transfer.
func (c *Client) AcceptRepoTransfer(owner, reponame string) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer/accept", owner, reponame), jsonHeader, nil, repo)
return repo, resp, err
}
// RejectRepoTransfer rejects a repo transfer.
func (c *Client) RejectRepoTransfer(owner, reponame string) (*Repository, *Response, error) {
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
return nil, nil, err
}
if err := c.checkServerVersionGreaterThanOrEqual(version1_16_0); err != nil {
return nil, nil, err
}
repo := new(Repository)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer/reject", owner, reponame), jsonHeader, nil, repo)
return repo, resp, err
}

44
vendor/code.gitea.io/sdk/gitea/repo_tree.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
)
// GitEntry represents a git tree
type GitEntry struct {
Path string `json:"path"`
Mode string `json:"mode"`
Type string `json:"type"`
Size int64 `json:"size"`
SHA string `json:"sha"`
URL string `json:"url"`
}
// GitTreeResponse returns a git tree
type GitTreeResponse struct {
SHA string `json:"sha"`
URL string `json:"url"`
Entries []GitEntry `json:"tree"`
Truncated bool `json:"truncated"`
Page int `json:"page"`
TotalCount int `json:"total_count"`
}
// GetTrees downloads a file of repository, ref can be branch/tag/commit.
// e.g.: ref -> master, tree -> macaron.go(no leading slash)
func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, *Response, error) {
if err := escapeValidatePathSegments(&user, &repo, &ref); err != nil {
return nil, nil, err
}
trees := new(GitTreeResponse)
path := fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref)
if recursive {
path += "?recursive=1"
}
resp, err := c.getParsedResponse("GET", path, nil, nil, trees)
return trees, resp, err
}

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

@ -0,0 +1,87 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/http"
"time"
)
// WatchInfo represents an API watch status of one repository
type WatchInfo struct {
Subscribed bool `json:"subscribed"`
Ignored bool `json:"ignored"`
Reason interface{} `json:"reason"`
CreatedAt time.Time `json:"created_at"`
URL string `json:"url"`
RepositoryURL string `json:"repository_url"`
}
// GetWatchedRepos list all the watched repos of user
func (c *Client) GetWatchedRepos(user string) ([]*Repository, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
repos := make([]*Repository, 0, 10)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos)
return repos, resp, err
}
// GetMyWatchedRepos list repositories watched by the authenticated user
func (c *Client) GetMyWatchedRepos() ([]*Repository, *Response, error) {
repos := make([]*Repository, 0, 10)
resp, err := c.getParsedResponse("GET", "/user/subscriptions", nil, nil, &repos)
return repos, resp, err
}
// CheckRepoWatch check if the current user is watching a repo
func (c *Client) CheckRepoWatch(owner, repo string) (bool, *Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return false, nil, err
}
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
if err != nil {
return false, resp, err
}
switch status {
case http.StatusNotFound:
return false, resp, nil
case http.StatusOK:
return true, resp, nil
default:
return false, resp, fmt.Errorf("unexpected Status: %d", status)
}
}
// WatchRepo start to watch a repository
func (c *Client) WatchRepo(owner, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
if err != nil {
return resp, err
}
if status == http.StatusOK {
return resp, nil
}
return resp, fmt.Errorf("unexpected Status: %d", status)
}
// UnWatchRepo stop to watch a repository
func (c *Client) UnWatchRepo(owner, repo string) (*Response, error) {
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
return nil, err
}
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
if err != nil {
return resp, err
}
if status == http.StatusNoContent {
return resp, nil
}
return resp, fmt.Errorf("unexpected Status: %d", status)
}

16
vendor/code.gitea.io/sdk/gitea/secret.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import "time"
type Secret struct {
// the secret's name
Name string `json:"name"`
// the secret's data
Data string `json:"data"`
// Date and Time of secret creation
Created time.Time `json:"created_at"`
}

78
vendor/code.gitea.io/sdk/gitea/settings.go generated vendored Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
// GlobalUISettings represent the global ui settings of a gitea instance witch is exposed by API
type GlobalUISettings struct {
DefaultTheme string `json:"default_theme"`
AllowedReactions []string `json:"allowed_reactions"`
CustomEmojis []string `json:"custom_emojis"`
}
// GlobalRepoSettings represent the global repository settings of a gitea instance witch is exposed by API
type GlobalRepoSettings struct {
MirrorsDisabled bool `json:"mirrors_disabled"`
HTTPGitDisabled bool `json:"http_git_disabled"`
MigrationsDisabled bool `json:"migrations_disabled"`
StarsDisabled bool `json:"stars_disabled"`
TimeTrackingDisabled bool `json:"time_tracking_disabled"`
LFSDisabled bool `json:"lfs_disabled"`
}
// GlobalAPISettings contains global api settings exposed by it
type GlobalAPISettings struct {
MaxResponseItems int `json:"max_response_items"`
DefaultPagingNum int `json:"default_paging_num"`
DefaultGitTreesPerPage int `json:"default_git_trees_per_page"`
DefaultMaxBlobSize int64 `json:"default_max_blob_size"`
}
// GlobalAttachmentSettings contains global Attachment settings exposed by API
type GlobalAttachmentSettings struct {
Enabled bool `json:"enabled"`
AllowedTypes string `json:"allowed_types"`
MaxSize int64 `json:"max_size"`
MaxFiles int `json:"max_files"`
}
// GetGlobalUISettings get global ui settings witch are exposed by API
func (c *Client) GetGlobalUISettings() (*GlobalUISettings, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, nil, err
}
conf := new(GlobalUISettings)
resp, err := c.getParsedResponse("GET", "/settings/ui", jsonHeader, nil, &conf)
return conf, resp, err
}
// GetGlobalRepoSettings get global repository settings witch are exposed by API
func (c *Client) GetGlobalRepoSettings() (*GlobalRepoSettings, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, nil, err
}
conf := new(GlobalRepoSettings)
resp, err := c.getParsedResponse("GET", "/settings/repository", jsonHeader, nil, &conf)
return conf, resp, err
}
// GetGlobalAPISettings get global api settings witch are exposed by it
func (c *Client) GetGlobalAPISettings() (*GlobalAPISettings, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, nil, err
}
conf := new(GlobalAPISettings)
resp, err := c.getParsedResponse("GET", "/settings/api", jsonHeader, nil, &conf)
return conf, resp, err
}
// GetGlobalAttachmentSettings get global repository settings witch are exposed by API
func (c *Client) GetGlobalAttachmentSettings() (*GlobalAttachmentSettings, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, nil, err
}
conf := new(GlobalAttachmentSettings)
resp, err := c.getParsedResponse("GET", "/settings/attachment", jsonHeader, nil, &conf)
return conf, resp, err
}

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

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

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

@ -0,0 +1,93 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/url"
"strconv"
"time"
)
// User represents a user
type User struct {
// the user's id
ID int64 `json:"id"`
// the user's username
UserName string `json:"login"`
// The login_name of non local users (e.g. LDAP / OAuth / SMTP)
LoginName string `json:"login_name"`
// The ID of the Authentication Source for non local users.
SourceID int64 `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"`
// User locale
Language string `json:"language"`
// Is the user an administrator
IsAdmin bool `json:"is_admin"`
// Date and Time of last login
LastLogin time.Time `json:"last_login"`
// Date and Time of user creation
Created time.Time `json:"created"`
// Is user restricted
Restricted bool `json:"restricted"`
// Is user active
IsActive bool `json:"active"`
// Is user login prohibited
ProhibitLogin bool `json:"prohibit_login"`
// the user's location
Location string `json:"location"`
// the user's website
Website string `json:"website"`
// the user's description
Description string `json:"description"`
// User visibility level option
Visibility VisibleType `json:"visibility"`
// user counts
FollowerCount int `json:"followers_count"`
FollowingCount int `json:"following_count"`
StarredRepoCount int `json:"starred_repos_count"`
}
// GetUserInfo get user info by user's name
func (c *Client) GetUserInfo(user string) (*User, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
u := new(User)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
return u, resp, err
}
// GetMyUserInfo get user info of current user
func (c *Client) GetMyUserInfo() (*User, *Response, error) {
u := new(User)
resp, err := c.getParsedResponse("GET", "/user", nil, nil, u)
return u, resp, err
}
// GetUserByID returns user by a given user ID
func (c *Client) GetUserByID(id int64) (*User, *Response, error) {
if id < 0 {
return nil, nil, fmt.Errorf("invalid user id %d", id)
}
query := make(url.Values)
query.Add("uid", strconv.FormatInt(id, 10))
users, resp, err := c.searchUsers(query.Encode())
if err != nil {
return nil, resp, err
}
if len(users) == 1 {
return users[0], resp, err
}
return nil, resp, fmt.Errorf("user not found with id %d", id)
}

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

@ -0,0 +1,143 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"reflect"
)
// AccessTokenScope represents the scope for an access token.
type AccessTokenScope string
const (
AccessTokenScopeAll AccessTokenScope = "all"
AccessTokenScopeRepo AccessTokenScope = "repo"
AccessTokenScopeRepoStatus AccessTokenScope = "repo:status"
AccessTokenScopePublicRepo AccessTokenScope = "public_repo"
AccessTokenScopeAdminOrg AccessTokenScope = "admin:org"
AccessTokenScopeWriteOrg AccessTokenScope = "write:org"
AccessTokenScopeReadOrg AccessTokenScope = "read:org"
AccessTokenScopeAdminPublicKey AccessTokenScope = "admin:public_key"
AccessTokenScopeWritePublicKey AccessTokenScope = "write:public_key"
AccessTokenScopeReadPublicKey AccessTokenScope = "read:public_key"
AccessTokenScopeAdminRepoHook AccessTokenScope = "admin:repo_hook"
AccessTokenScopeWriteRepoHook AccessTokenScope = "write:repo_hook"
AccessTokenScopeReadRepoHook AccessTokenScope = "read:repo_hook"
AccessTokenScopeAdminOrgHook AccessTokenScope = "admin:org_hook"
AccessTokenScopeAdminUserHook AccessTokenScope = "admin:user_hook"
AccessTokenScopeNotification AccessTokenScope = "notification"
AccessTokenScopeUser AccessTokenScope = "user"
AccessTokenScopeReadUser AccessTokenScope = "read:user"
AccessTokenScopeUserEmail AccessTokenScope = "user:email"
AccessTokenScopeUserFollow AccessTokenScope = "user:follow"
AccessTokenScopeDeleteRepo AccessTokenScope = "delete_repo"
AccessTokenScopePackage AccessTokenScope = "package"
AccessTokenScopeWritePackage AccessTokenScope = "write:package"
AccessTokenScopeReadPackage AccessTokenScope = "read:package"
AccessTokenScopeDeletePackage AccessTokenScope = "delete:package"
AccessTokenScopeAdminGPGKey AccessTokenScope = "admin:gpg_key"
AccessTokenScopeWriteGPGKey AccessTokenScope = "write:gpg_key"
AccessTokenScopeReadGPGKey AccessTokenScope = "read:gpg_key"
AccessTokenScopeAdminApplication AccessTokenScope = "admin:application"
AccessTokenScopeWriteApplication AccessTokenScope = "write:application"
AccessTokenScopeReadApplication AccessTokenScope = "read:application"
AccessTokenScopeSudo AccessTokenScope = "sudo"
)
// AccessToken represents an API access token.
type AccessToken struct {
ID int64 `json:"id"`
Name string `json:"name"`
Token string `json:"sha1"`
TokenLastEight string `json:"token_last_eight"`
Scopes []AccessTokenScope `json:"scopes"`
}
// ListAccessTokensOptions options for listing a users's access tokens
type ListAccessTokensOptions struct {
ListOptions
}
// ListAccessTokens lists all the access tokens of user
func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, *Response, error) {
c.mutex.RLock()
username := c.username
c.mutex.RUnlock()
if len(username) == 0 {
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
}
opts.setDefaults()
tokens := make([]*AccessToken, 0, opts.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", url.PathEscape(username), opts.getURLQuery().Encode()), jsonHeader, nil, &tokens)
return tokens, resp, err
}
// CreateAccessTokenOption options when create access token
type CreateAccessTokenOption struct {
Name string `json:"name"`
Scopes []AccessTokenScope `json:"scopes"`
}
// CreateAccessToken create one access token with options
func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, *Response, error) {
c.mutex.RLock()
username := c.username
c.mutex.RUnlock()
if len(username) == 0 {
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
t := new(AccessToken)
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", url.PathEscape(username)), jsonHeader, bytes.NewReader(body), t)
return t, resp, err
}
// DeleteAccessToken delete token, identified by ID and if not available by name
func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) {
c.mutex.RLock()
username := c.username
c.mutex.RUnlock()
if len(username) == 0 {
return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
}
token := ""
switch reflect.ValueOf(value).Kind() {
case reflect.Int64:
token = fmt.Sprintf("%d", value.(int64))
case reflect.String:
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
return nil, err
}
token = value.(string)
default:
return nil, fmt.Errorf("only string and int64 supported")
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", url.PathEscape(username), url.PathEscape(token)), jsonHeader, nil)
return resp, err
}

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

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

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

@ -0,0 +1,93 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import "fmt"
// ListFollowersOptions options for listing followers
type ListFollowersOptions struct {
ListOptions
}
// ListMyFollowers list all the followers of current user
func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, *Response, error) {
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/followers?%s", opt.getURLQuery().Encode()), nil, nil, &users)
return users, resp, err
}
// ListFollowers list all the followers of one user
func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
return users, resp, err
}
// ListFollowingOptions options for listing a user's users being followed
type ListFollowingOptions struct {
ListOptions
}
// ListMyFollowing list all the users current user followed
func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, *Response, error) {
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/following?%s", opt.getURLQuery().Encode()), nil, nil, &users)
return users, resp, err
}
// ListFollowing list all the users the user followed
func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
return users, resp, err
}
// IsFollowing if current user followed the target
func (c *Client) IsFollowing(target string) (bool, *Response) {
if err := escapeValidatePathSegments(&target); err != nil {
// ToDo return err
return false, nil
}
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil)
return err == nil, resp
}
// IsUserFollowing if the user followed the target
func (c *Client) IsUserFollowing(user, target string) (bool, *Response) {
if err := escapeValidatePathSegments(&user, &target); err != nil {
// ToDo return err
return false, nil
}
_, resp, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil)
return err == nil, resp
}
// Follow set current user follow the target
func (c *Client) Follow(target string) (*Response, error) {
if err := escapeValidatePathSegments(&target); err != nil {
return nil, err
}
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil)
return resp, err
}
// Unfollow set current user unfollow the target
func (c *Client) Unfollow(target string) (*Response, error) {
if err := escapeValidatePathSegments(&target); err != nil {
return nil, err
}
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
return resp, err
}

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

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

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

@ -0,0 +1,83 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// PublicKey publickey is a user key to push code to repository
type PublicKey struct {
ID int64 `json:"id"`
Key string `json:"key"`
URL string `json:"url,omitempty"`
Title string `json:"title,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
Created time.Time `json:"created_at,omitempty"`
Owner *User `json:"user,omitempty"`
ReadOnly bool `json:"read_only,omitempty"`
KeyType string `json:"key_type,omitempty"`
}
// ListPublicKeysOptions options for listing a user's PublicKeys
type ListPublicKeysOptions struct {
ListOptions
}
// ListPublicKeys list all the public keys of the user
func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
if err := escapeValidatePathSegments(&user); err != nil {
return nil, nil, err
}
opt.setDefaults()
keys := make([]*PublicKey, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
return keys, resp, err
}
// ListMyPublicKeys list all the public keys of current user
func (c *Client) ListMyPublicKeys(opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
opt.setDefaults()
keys := make([]*PublicKey, 0, opt.PageSize)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
return keys, resp, err
}
// GetPublicKey get current user's public key by key id
func (c *Client) GetPublicKey(keyID int64) (*PublicKey, *Response, error) {
key := new(PublicKey)
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key)
return key, resp, err
}
// CreateKeyOption options when creating a key
type CreateKeyOption struct {
// Title of the key to add
Title string `json:"title"`
// An armored SSH key to add
Key string `json:"key"`
// Describe if the key has only read access or read/write
ReadOnly bool `json:"read_only"`
}
// CreatePublicKey create public key with options
func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, *Response, error) {
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
key := new(PublicKey)
resp, err := c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key)
return key, resp, err
}
// DeletePublicKey delete public key with key id
func (c *Client) DeletePublicKey(keyID int64) (*Response, error) {
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil)
return resp, err
}

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

@ -0,0 +1,48 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"net/url"
)
type searchUsersResponse struct {
Users []*User `json:"data"`
}
// SearchUsersOption options for SearchUsers
type SearchUsersOption struct {
ListOptions
KeyWord string
}
// QueryEncode turns options into querystring argument
func (opt *SearchUsersOption) QueryEncode() string {
query := make(url.Values)
if opt.Page > 0 {
query.Add("page", fmt.Sprintf("%d", opt.Page))
}
if opt.PageSize > 0 {
query.Add("limit", fmt.Sprintf("%d", opt.PageSize))
}
if len(opt.KeyWord) > 0 {
query.Add("q", opt.KeyWord)
}
return query.Encode()
}
func (c *Client) searchUsers(rawQuery string) ([]*User, *Response, error) {
link, _ := url.Parse("/users/search")
link.RawQuery = rawQuery
userResp := new(searchUsersResponse)
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &userResp)
return userResp.Users, resp, err
}
// SearchUsers finds users by query
func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, *Response, error) {
return c.searchUsers(opt.QueryEncode())
}

62
vendor/code.gitea.io/sdk/gitea/user_settings.go generated vendored Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"bytes"
"encoding/json"
)
// UserSettings represents user settings
type UserSettings struct {
FullName string `json:"full_name"`
Website string `json:"website"`
Description string `json:"description"`
Location string `json:"location"`
Language string `json:"language"`
Theme string `json:"theme"`
DiffViewStyle string `json:"diff_view_style"`
// Privacy
HideEmail bool `json:"hide_email"`
HideActivity bool `json:"hide_activity"`
}
// UserSettingsOptions represents options to change user settings
type UserSettingsOptions struct {
FullName *string `json:"full_name,omitempty"`
Website *string `json:"website,omitempty"`
Description *string `json:"description,omitempty"`
Location *string `json:"location,omitempty"`
Language *string `json:"language,omitempty"`
Theme *string `json:"theme,omitempty"`
DiffViewStyle *string `json:"diff_view_style,omitempty"`
// Privacy
HideEmail *bool `json:"hide_email,omitempty"`
HideActivity *bool `json:"hide_activity,omitempty"`
}
// GetUserSettings returns user settings
func (c *Client) GetUserSettings() (*UserSettings, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
userConfig := new(UserSettings)
resp, err := c.getParsedResponse("GET", "/user/settings", nil, nil, userConfig)
return userConfig, resp, err
}
// UpdateUserSettings returns user settings
func (c *Client) UpdateUserSettings(opt UserSettingsOptions) (*UserSettings, *Response, error) {
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
return nil, nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, nil, err
}
userConfig := new(UserSettings)
resp, err := c.getParsedResponse("PATCH", "/user/settings", jsonHeader, bytes.NewReader(body), userConfig)
return userConfig, resp, err
}

126
vendor/code.gitea.io/sdk/gitea/version.go generated vendored Normal file
View File

@ -0,0 +1,126 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package gitea
import (
"fmt"
"strings"
"github.com/hashicorp/go-version"
)
// ServerVersion returns the version of the server
func (c *Client) ServerVersion() (string, *Response, error) {
v := struct {
Version string `json:"version"`
}{}
resp, err := c.getParsedResponse("GET", "/version", nil, nil, &v)
return v.Version, resp, err
}
// CheckServerVersionConstraint validates that the login's server satisfies a
// given version constraint such as ">= 1.11.0+dev"
func (c *Client) CheckServerVersionConstraint(constraint string) error {
if err := c.loadServerVersion(); err != nil {
return err
}
check, err := version.NewConstraint(constraint)
if err != nil {
return err
}
if !check.Check(c.serverVersion) {
c.mutex.RLock()
url := c.url
c.mutex.RUnlock()
return fmt.Errorf("gitea server at %s does not satisfy version constraint %s", url, constraint)
}
return nil
}
// SetGiteaVersion configures the Client to assume the given version of the
// Gitea server, instead of querying the server for it when initializing.
// Use "" to skip all canonical ways in the SDK to check for versions
func SetGiteaVersion(v string) ClientOption {
if v == "" {
return func(c *Client) error {
c.ignoreVersion = true
return nil
}
}
return func(c *Client) (err error) {
c.getVersionOnce.Do(func() {
c.serverVersion, err = version.NewVersion(v)
})
return
}
}
// predefined versions only have to be parsed by library once
var (
version1_11_0 = version.Must(version.NewVersion("1.11.0"))
version1_11_5 = version.Must(version.NewVersion("1.11.5"))
version1_12_0 = version.Must(version.NewVersion("1.12.0"))
version1_12_3 = version.Must(version.NewVersion("1.12.3"))
version1_13_0 = version.Must(version.NewVersion("1.13.0"))
version1_14_0 = version.Must(version.NewVersion("1.14.0"))
version1_15_0 = version.Must(version.NewVersion("1.15.0"))
version1_16_0 = version.Must(version.NewVersion("1.16.0"))
version1_17_0 = version.Must(version.NewVersion("1.17.0"))
version1_22_0 = version.Must(version.NewVersion("1.22.0"))
)
// ErrUnknownVersion is an unknown version from the API
type ErrUnknownVersion struct {
raw string
}
// Error fulfills error
func (e *ErrUnknownVersion) Error() string {
return fmt.Sprintf("unknown version: %s", e.raw)
}
func (*ErrUnknownVersion) Is(target error) bool {
_, ok := target.(*ErrUnknownVersion)
return ok
}
// checkServerVersionGreaterThanOrEqual is the canonical way in the SDK to check for versions for API compatibility reasons
func (c *Client) checkServerVersionGreaterThanOrEqual(v *version.Version) error {
if c.ignoreVersion {
return nil
}
if err := c.loadServerVersion(); err != nil {
return err
}
if !c.serverVersion.GreaterThanOrEqual(v) {
c.mutex.RLock()
url := c.url
c.mutex.RUnlock()
return fmt.Errorf("gitea server at %s is older than %s", url, v.Original())
}
return nil
}
// loadServerVersion init the serverVersion variable
func (c *Client) loadServerVersion() (err error) {
c.getVersionOnce.Do(func() {
raw, _, err2 := c.ServerVersion()
if err2 != nil {
err = err2
return
}
if c.serverVersion, err = version.NewVersion(raw); err != nil {
if strings.TrimSpace(raw) != "" {
// Version was something, just not recognized
c.serverVersion = version1_11_0
err = &ErrUnknownVersion{raw: raw}
}
return
}
})
return
}

16
vendor/github.com/davidmz/go-pageant/LICENSE.txt generated vendored Normal file
View File

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

9
vendor/github.com/davidmz/go-pageant/README.md generated vendored Normal file
View File

@ -0,0 +1,9 @@
[![GoDoc](https://godoc.org/github.com/davidmz/go-pageant?status.svg)](https://godoc.org/github.com/davidmz/go-pageant)
Package pageant provides an interface to PyTTY pageant.exe utility.
This package is windows-only.
See documentation on [GoDoc](http://godoc.org/github.com/davidmz/go-pageant)
License: MIT

42
vendor/github.com/davidmz/go-pageant/io_windows.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
package pageant
import (
"io"
"sync"
"golang.org/x/crypto/ssh/agent"
)
// New returns new ssh-agent instance (see http://golang.org/x/crypto/ssh/agent)
func New() agent.Agent {
return agent.NewClient(&conn{})
}
type conn struct {
sync.Mutex
buf []byte
}
func (c *conn) Write(p []byte) (int, error) {
c.Lock()
defer c.Unlock()
resp, err := query(p)
if err != nil {
return 0, err
}
c.buf = append(c.buf, resp...)
return len(p), nil
}
func (c *conn) Read(p []byte) (int, error) {
c.Lock()
defer c.Unlock()
if len(c.buf) == 0 {
return 0, io.EOF
}
n := copy(p, c.buf)
c.buf = c.buf[n:]
return n, nil
}

134
vendor/github.com/davidmz/go-pageant/pageant_windows.go generated vendored Normal file
View File

@ -0,0 +1,134 @@
// Package pageant provides an interface to PyTTY pageant.exe utility.
// This package is windows-only
package pageant
// see https://github.com/Yasushi/putty/blob/master/windows/winpgntc.c#L155
// see https://github.com/paramiko/paramiko/blob/master/paramiko/win_pageant.py
import (
"encoding/binary"
"errors"
"fmt"
"sync"
"syscall"
"unsafe"
)
// MaxMessageLen defines maximum size of message can be sent to pageant
const MaxMessageLen = 8192
var (
// ErrPageantNotFound returns when pageant process not found
ErrPageantNotFound = errors.New("pageant process not found")
// ErrSendMessage returns when message to pageant cannt be sent
ErrSendMessage = errors.New("error sending message")
// ErrMessageTooLong returns when message is too long (see MaxMessageLen)
ErrMessageTooLong = errors.New("message too long")
// ErrInvalidMessageFormat returns when message have invalid fomat
ErrInvalidMessageFormat = errors.New("invalid message format")
// ErrResponseTooLong returns when response from pageant is too long
ErrResponseTooLong = errors.New("response too long")
)
/////////////////////////
const (
agentCopydataID = 0x804e50ba
wmCopydata = 74
)
type copyData struct {
dwData uintptr
cbData uint32
lpData unsafe.Pointer
}
var (
lock sync.Mutex
winFindWindow = winAPI("user32.dll", "FindWindowW")
winGetCurrentThreadID = winAPI("kernel32.dll", "GetCurrentThreadId")
winSendMessage = winAPI("user32.dll", "SendMessageW")
)
func winAPI(dllName, funcName string) func(...uintptr) (uintptr, uintptr, error) {
proc := syscall.MustLoadDLL(dllName).MustFindProc(funcName)
return func(a ...uintptr) (uintptr, uintptr, error) { return proc.Call(a...) }
}
// Available returns true if Pageant is started
func Available() bool { return pageantWindow() != 0 }
// Query sends message msg to Pageant and returns response or error.
// 'msg' is raw agent request with length prefix
// Response is raw agent response with length prefix
func query(msg []byte) ([]byte, error) {
if len(msg) > MaxMessageLen {
return nil, ErrMessageTooLong
}
msgLen := binary.BigEndian.Uint32(msg[:4])
if len(msg) != int(msgLen)+4 {
return nil, ErrInvalidMessageFormat
}
lock.Lock()
defer lock.Unlock()
paWin := pageantWindow()
if paWin == 0 {
return nil, ErrPageantNotFound
}
thID, _, _ := winGetCurrentThreadID()
mapName := fmt.Sprintf("PageantRequest%08x", thID)
pMapName, _ := syscall.UTF16PtrFromString(mapName)
mmap, err := syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, 0, MaxMessageLen+4, pMapName)
if err != nil {
return nil, err
}
defer syscall.CloseHandle(mmap)
ptr, err := syscall.MapViewOfFile(mmap, syscall.FILE_MAP_WRITE, 0, 0, 0)
if err != nil {
return nil, err
}
defer syscall.UnmapViewOfFile(ptr)
mmSlice := (*(*[MaxMessageLen]byte)(unsafe.Pointer(ptr)))[:]
copy(mmSlice, msg)
mapNameBytesZ := append([]byte(mapName), 0)
cds := copyData{
dwData: agentCopydataID,
cbData: uint32(len(mapNameBytesZ)),
lpData: unsafe.Pointer(&(mapNameBytesZ[0])),
}
resp, _, _ := winSendMessage(paWin, wmCopydata, 0, uintptr(unsafe.Pointer(&cds)))
if resp == 0 {
return nil, ErrSendMessage
}
respLen := binary.BigEndian.Uint32(mmSlice[:4])
if respLen > MaxMessageLen-4 {
return nil, ErrResponseTooLong
}
respData := make([]byte, respLen+4)
copy(respData, mmSlice)
return respData, nil
}
func pageantWindow() uintptr {
nameP, _ := syscall.UTF16PtrFromString("Pageant")
h, _, _ := winFindWindow(uintptr(unsafe.Pointer(nameP)), uintptr(unsafe.Pointer(nameP)))
return h
}

29
vendor/github.com/go-fed/httpsig/LICENSE generated vendored Normal file
View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2018, go-fed
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

94
vendor/github.com/go-fed/httpsig/README.md generated vendored Normal file
View File

@ -0,0 +1,94 @@
# httpsig
`go get github.com/go-fed/httpsig`
Implementation of [HTTP Signatures](https://tools.ietf.org/html/draft-cavage-http-signatures).
Supports many different combinations of MAC, HMAC signing of hash, or RSA
signing of hash schemes. Its goals are:
* Have a very simple interface for signing and validating
* Support a variety of signing algorithms and combinations
* Support setting either headers (`Authorization` or `Signature`)
* Remaining flexible with headers included in the signing string
* Support both HTTP requests and responses
* Explicitly not support known-cryptographically weak algorithms
* Support automatic signing and validating Digest headers
## How to use
`import "github.com/go-fed/httpsig"`
### Signing
Signing a request or response requires creating a new `Signer` and using it:
```
func sign(privateKey crypto.PrivateKey, pubKeyId string, r *http.Request) error {
prefs := []httpsig.Algorithm{httpsig.RSA_SHA512, httpsig.RSA_SHA256}
digestAlgorithm := DigestSha256
// The "Date" and "Digest" headers must already be set on r, as well as r.URL.
headersToSign := []string{httpsig.RequestTarget, "date", "digest"}
signer, chosenAlgo, err := httpsig.NewSigner(prefs, digestAlgorithm, headersToSign, httpsig.Signature)
if err != nil {
return err
}
// To sign the digest, we need to give the signer a copy of the body...
// ...but it is optional, no digest will be signed if given "nil"
body := ...
// If r were a http.ResponseWriter, call SignResponse instead.
return signer.SignRequest(privateKey, pubKeyId, r, body)
}
```
`Signer`s are not safe for concurrent use by goroutines, so be sure to guard
access:
```
type server struct {
signer httpsig.Signer
mu *sync.Mutex
}
func (s *server) handlerFunc(w http.ResponseWriter, r *http.Request) {
privateKey := ...
pubKeyId := ...
// Set headers and such on w
s.mu.Lock()
defer s.mu.Unlock()
// To sign the digest, we need to give the signer a copy of the response body...
// ...but it is optional, no digest will be signed if given "nil"
body := ...
err := s.signer.SignResponse(privateKey, pubKeyId, w, body)
if err != nil {
...
}
...
}
```
The `pubKeyId` will be used at verification time.
### Verifying
Verifying requires an application to use the `pubKeyId` to both retrieve the key
needed for verification as well as determine the algorithm to use. Use a
`Verifier`:
```
func verify(r *http.Request) error {
verifier, err := httpsig.NewVerifier(r)
if err != nil {
return err
}
pubKeyId := verifier.KeyId()
var algo httpsig.Algorithm = ...
var pubKey crypto.PublicKey = ...
// The verifier will verify the Digest in addition to the HTTP signature
return verifier.Verify(pubKey, algo)
}
```
`Verifier`s are not safe for concurrent use by goroutines, but since they are
constructed on a per-request or per-response basis it should not be a common
restriction.

532
vendor/github.com/go-fed/httpsig/algorithms.go generated vendored Normal file
View File

@ -0,0 +1,532 @@
package httpsig
import (
"crypto"
"crypto/ecdsa"
"crypto/hmac"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"crypto/subtle" // Use should trigger great care
"encoding/asn1"
"errors"
"fmt"
"hash"
"io"
"math/big"
"strings"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/ripemd160"
"golang.org/x/crypto/sha3"
"golang.org/x/crypto/ssh"
)
const (
hmacPrefix = "hmac"
rsaPrefix = "rsa"
sshPrefix = "ssh"
ecdsaPrefix = "ecdsa"
ed25519Prefix = "ed25519"
md4String = "md4"
md5String = "md5"
sha1String = "sha1"
sha224String = "sha224"
sha256String = "sha256"
sha384String = "sha384"
sha512String = "sha512"
md5sha1String = "md5sha1"
ripemd160String = "ripemd160"
sha3_224String = "sha3-224"
sha3_256String = "sha3-256"
sha3_384String = "sha3-384"
sha3_512String = "sha3-512"
sha512_224String = "sha512-224"
sha512_256String = "sha512-256"
blake2s_256String = "blake2s-256"
blake2b_256String = "blake2b-256"
blake2b_384String = "blake2b-384"
blake2b_512String = "blake2b-512"
)
var blake2Algorithms = map[crypto.Hash]bool{
crypto.BLAKE2s_256: true,
crypto.BLAKE2b_256: true,
crypto.BLAKE2b_384: true,
crypto.BLAKE2b_512: true,
}
var hashToDef = map[crypto.Hash]struct {
name string
new func(key []byte) (hash.Hash, error) // Only MACers will accept a key
}{
// Which standard names these?
// The spec lists the following as a canonical reference, which is dead:
// http://www.iana.org/assignments/signature-algorithms
//
// Note that the forbidden hashes have an invalid 'new' function.
crypto.MD4: {md4String, func(key []byte) (hash.Hash, error) { return nil, nil }},
crypto.MD5: {md5String, func(key []byte) (hash.Hash, error) { return nil, nil }},
// Temporarily enable SHA1 because of issue https://github.com/golang/go/issues/37278
crypto.SHA1: {sha1String, func(key []byte) (hash.Hash, error) { return sha1.New(), nil }},
crypto.SHA224: {sha224String, func(key []byte) (hash.Hash, error) { return sha256.New224(), nil }},
crypto.SHA256: {sha256String, func(key []byte) (hash.Hash, error) { return sha256.New(), nil }},
crypto.SHA384: {sha384String, func(key []byte) (hash.Hash, error) { return sha512.New384(), nil }},
crypto.SHA512: {sha512String, func(key []byte) (hash.Hash, error) { return sha512.New(), nil }},
crypto.MD5SHA1: {md5sha1String, func(key []byte) (hash.Hash, error) { return nil, nil }},
crypto.RIPEMD160: {ripemd160String, func(key []byte) (hash.Hash, error) { return ripemd160.New(), nil }},
crypto.SHA3_224: {sha3_224String, func(key []byte) (hash.Hash, error) { return sha3.New224(), nil }},
crypto.SHA3_256: {sha3_256String, func(key []byte) (hash.Hash, error) { return sha3.New256(), nil }},
crypto.SHA3_384: {sha3_384String, func(key []byte) (hash.Hash, error) { return sha3.New384(), nil }},
crypto.SHA3_512: {sha3_512String, func(key []byte) (hash.Hash, error) { return sha3.New512(), nil }},
crypto.SHA512_224: {sha512_224String, func(key []byte) (hash.Hash, error) { return sha512.New512_224(), nil }},
crypto.SHA512_256: {sha512_256String, func(key []byte) (hash.Hash, error) { return sha512.New512_256(), nil }},
crypto.BLAKE2s_256: {blake2s_256String, func(key []byte) (hash.Hash, error) { return blake2s.New256(key) }},
crypto.BLAKE2b_256: {blake2b_256String, func(key []byte) (hash.Hash, error) { return blake2b.New256(key) }},
crypto.BLAKE2b_384: {blake2b_384String, func(key []byte) (hash.Hash, error) { return blake2b.New384(key) }},
crypto.BLAKE2b_512: {blake2b_512String, func(key []byte) (hash.Hash, error) { return blake2b.New512(key) }},
}
var stringToHash map[string]crypto.Hash
const (
defaultAlgorithm = RSA_SHA256
defaultAlgorithmHashing = sha256String
)
func init() {
stringToHash = make(map[string]crypto.Hash, len(hashToDef))
for k, v := range hashToDef {
stringToHash[v.name] = k
}
// This should guarantee that at runtime the defaultAlgorithm will not
// result in errors when fetching a macer or signer (see algorithms.go)
if ok, err := isAvailable(string(defaultAlgorithmHashing)); err != nil {
panic(err)
} else if !ok {
panic(fmt.Sprintf("the default httpsig algorithm is unavailable: %q", defaultAlgorithm))
}
}
func isForbiddenHash(h crypto.Hash) bool {
switch h {
// Not actually cryptographically secure
case crypto.MD4:
fallthrough
case crypto.MD5:
fallthrough
case crypto.MD5SHA1: // shorthand for crypto/tls, not actually implemented
return true
}
// Still cryptographically secure
return false
}
// signer is an internally public type.
type signer interface {
Sign(rand io.Reader, p crypto.PrivateKey, sig []byte) ([]byte, error)
Verify(pub crypto.PublicKey, toHash, signature []byte) error
String() string
}
// macer is an internally public type.
type macer interface {
Sign(sig, key []byte) ([]byte, error)
Equal(sig, actualMAC, key []byte) (bool, error)
String() string
}
var _ macer = &hmacAlgorithm{}
type hmacAlgorithm struct {
fn func(key []byte) (hash.Hash, error)
kind crypto.Hash
}
func (h *hmacAlgorithm) Sign(sig, key []byte) ([]byte, error) {
hs, err := h.fn(key)
if err = setSig(hs, sig); err != nil {
return nil, err
}
return hs.Sum(nil), nil
}
func (h *hmacAlgorithm) Equal(sig, actualMAC, key []byte) (bool, error) {
hs, err := h.fn(key)
if err != nil {
return false, err
}
defer hs.Reset()
err = setSig(hs, sig)
if err != nil {
return false, err
}
expected := hs.Sum(nil)
return hmac.Equal(actualMAC, expected), nil
}
func (h *hmacAlgorithm) String() string {
return fmt.Sprintf("%s-%s", hmacPrefix, hashToDef[h.kind].name)
}
var _ signer = &rsaAlgorithm{}
type rsaAlgorithm struct {
hash.Hash
kind crypto.Hash
sshSigner ssh.Signer
}
func (r *rsaAlgorithm) setSig(b []byte) error {
n, err := r.Write(b)
if err != nil {
r.Reset()
return err
} else if n != len(b) {
r.Reset()
return fmt.Errorf("could only write %d of %d bytes of signature to hash", n, len(b))
}
return nil
}
func (r *rsaAlgorithm) Sign(rand io.Reader, p crypto.PrivateKey, sig []byte) ([]byte, error) {
if r.sshSigner != nil {
sshsig, err := r.sshSigner.Sign(rand, sig)
if err != nil {
return nil, err
}
return sshsig.Blob, nil
}
defer r.Reset()
if err := r.setSig(sig); err != nil {
return nil, err
}
rsaK, ok := p.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("crypto.PrivateKey is not *rsa.PrivateKey")
}
return rsa.SignPKCS1v15(rand, rsaK, r.kind, r.Sum(nil))
}
func (r *rsaAlgorithm) Verify(pub crypto.PublicKey, toHash, signature []byte) error {
defer r.Reset()
rsaK, ok := pub.(*rsa.PublicKey)
if !ok {
return errors.New("crypto.PublicKey is not *rsa.PublicKey")
}
if err := r.setSig(toHash); err != nil {
return err
}
return rsa.VerifyPKCS1v15(rsaK, r.kind, r.Sum(nil), signature)
}
func (r *rsaAlgorithm) String() string {
return fmt.Sprintf("%s-%s", rsaPrefix, hashToDef[r.kind].name)
}
var _ signer = &ed25519Algorithm{}
type ed25519Algorithm struct {
sshSigner ssh.Signer
}
func (r *ed25519Algorithm) Sign(rand io.Reader, p crypto.PrivateKey, sig []byte) ([]byte, error) {
if r.sshSigner != nil {
sshsig, err := r.sshSigner.Sign(rand, sig)
if err != nil {
return nil, err
}
return sshsig.Blob, nil
}
ed25519K, ok := p.(ed25519.PrivateKey)
if !ok {
return nil, errors.New("crypto.PrivateKey is not ed25519.PrivateKey")
}
return ed25519.Sign(ed25519K, sig), nil
}
func (r *ed25519Algorithm) Verify(pub crypto.PublicKey, toHash, signature []byte) error {
ed25519K, ok := pub.(ed25519.PublicKey)
if !ok {
return errors.New("crypto.PublicKey is not ed25519.PublicKey")
}
if ed25519.Verify(ed25519K, toHash, signature) {
return nil
}
return errors.New("ed25519 verify failed")
}
func (r *ed25519Algorithm) String() string {
return fmt.Sprintf("%s", ed25519Prefix)
}
var _ signer = &ecdsaAlgorithm{}
type ecdsaAlgorithm struct {
hash.Hash
kind crypto.Hash
}
func (r *ecdsaAlgorithm) setSig(b []byte) error {
n, err := r.Write(b)
if err != nil {
r.Reset()
return err
} else if n != len(b) {
r.Reset()
return fmt.Errorf("could only write %d of %d bytes of signature to hash", n, len(b))
}
return nil
}
type ECDSASignature struct {
R, S *big.Int
}
func (r *ecdsaAlgorithm) Sign(rand io.Reader, p crypto.PrivateKey, sig []byte) ([]byte, error) {
defer r.Reset()
if err := r.setSig(sig); err != nil {
return nil, err
}
ecdsaK, ok := p.(*ecdsa.PrivateKey)
if !ok {
return nil, errors.New("crypto.PrivateKey is not *ecdsa.PrivateKey")
}
R, S, err := ecdsa.Sign(rand, ecdsaK, r.Sum(nil))
if err != nil {
return nil, err
}
signature := ECDSASignature{R: R, S: S}
bytes, err := asn1.Marshal(signature)
return bytes, err
}
func (r *ecdsaAlgorithm) Verify(pub crypto.PublicKey, toHash, signature []byte) error {
defer r.Reset()
ecdsaK, ok := pub.(*ecdsa.PublicKey)
if !ok {
return errors.New("crypto.PublicKey is not *ecdsa.PublicKey")
}
if err := r.setSig(toHash); err != nil {
return err
}
sig := new(ECDSASignature)
_, err := asn1.Unmarshal(signature, sig)
if err != nil {
return err
}
if ecdsa.Verify(ecdsaK, r.Sum(nil), sig.R, sig.S) {
return nil
} else {
return errors.New("Invalid signature")
}
}
func (r *ecdsaAlgorithm) String() string {
return fmt.Sprintf("%s-%s", ecdsaPrefix, hashToDef[r.kind].name)
}
var _ macer = &blakeMacAlgorithm{}
type blakeMacAlgorithm struct {
fn func(key []byte) (hash.Hash, error)
kind crypto.Hash
}
func (r *blakeMacAlgorithm) Sign(sig, key []byte) ([]byte, error) {
hs, err := r.fn(key)
if err != nil {
return nil, err
}
if err = setSig(hs, sig); err != nil {
return nil, err
}
return hs.Sum(nil), nil
}
func (r *blakeMacAlgorithm) Equal(sig, actualMAC, key []byte) (bool, error) {
hs, err := r.fn(key)
if err != nil {
return false, err
}
defer hs.Reset()
err = setSig(hs, sig)
if err != nil {
return false, err
}
expected := hs.Sum(nil)
return subtle.ConstantTimeCompare(actualMAC, expected) == 1, nil
}
func (r *blakeMacAlgorithm) String() string {
return fmt.Sprintf("%s", hashToDef[r.kind].name)
}
func setSig(a hash.Hash, b []byte) error {
n, err := a.Write(b)
if err != nil {
a.Reset()
return err
} else if n != len(b) {
a.Reset()
return fmt.Errorf("could only write %d of %d bytes of signature to hash", n, len(b))
}
return nil
}
// IsSupportedHttpSigAlgorithm returns true if the string is supported by this
// library, is not a hash known to be weak, and is supported by the hardware.
func IsSupportedHttpSigAlgorithm(algo string) bool {
a, err := isAvailable(algo)
return a && err == nil
}
// isAvailable is an internally public function
func isAvailable(algo string) (bool, error) {
c, ok := stringToHash[algo]
if !ok {
return false, fmt.Errorf("no match for %q", algo)
}
if isForbiddenHash(c) {
return false, fmt.Errorf("forbidden hash type in %q", algo)
}
return c.Available(), nil
}
func newAlgorithmConstructor(algo string) (fn func(k []byte) (hash.Hash, error), c crypto.Hash, e error) {
ok := false
c, ok = stringToHash[algo]
if !ok {
e = fmt.Errorf("no match for %q", algo)
return
}
if isForbiddenHash(c) {
e = fmt.Errorf("forbidden hash type in %q", algo)
return
}
algoDef, ok := hashToDef[c]
if !ok {
e = fmt.Errorf("have crypto.Hash %v but no definition", c)
return
}
fn = func(key []byte) (hash.Hash, error) {
h, err := algoDef.new(key)
if err != nil {
return nil, err
}
return h, nil
}
return
}
func newAlgorithm(algo string, key []byte) (hash.Hash, crypto.Hash, error) {
fn, c, err := newAlgorithmConstructor(algo)
if err != nil {
return nil, c, err
}
h, err := fn(key)
return h, c, err
}
func signerFromSSHSigner(sshSigner ssh.Signer, s string) (signer, error) {
switch {
case strings.HasPrefix(s, rsaPrefix):
return &rsaAlgorithm{
sshSigner: sshSigner,
}, nil
case strings.HasPrefix(s, ed25519Prefix):
return &ed25519Algorithm{
sshSigner: sshSigner,
}, nil
default:
return nil, fmt.Errorf("no signer matching %q", s)
}
}
// signerFromString is an internally public method constructor
func signerFromString(s string) (signer, error) {
s = strings.ToLower(s)
isEcdsa := false
isEd25519 := false
var algo string = ""
if strings.HasPrefix(s, ecdsaPrefix) {
algo = strings.TrimPrefix(s, ecdsaPrefix+"-")
isEcdsa = true
} else if strings.HasPrefix(s, rsaPrefix) {
algo = strings.TrimPrefix(s, rsaPrefix+"-")
} else if strings.HasPrefix(s, ed25519Prefix) {
isEd25519 = true
algo = "sha512"
} else {
return nil, fmt.Errorf("no signer matching %q", s)
}
hash, cHash, err := newAlgorithm(algo, nil)
if err != nil {
return nil, err
}
if isEd25519 {
return &ed25519Algorithm{}, nil
}
if isEcdsa {
return &ecdsaAlgorithm{
Hash: hash,
kind: cHash,
}, nil
}
return &rsaAlgorithm{
Hash: hash,
kind: cHash,
}, nil
}
// macerFromString is an internally public method constructor
func macerFromString(s string) (macer, error) {
s = strings.ToLower(s)
if strings.HasPrefix(s, hmacPrefix) {
algo := strings.TrimPrefix(s, hmacPrefix+"-")
hashFn, cHash, err := newAlgorithmConstructor(algo)
if err != nil {
return nil, err
}
// Ensure below does not panic
_, err = hashFn(nil)
if err != nil {
return nil, err
}
return &hmacAlgorithm{
fn: func(key []byte) (hash.Hash, error) {
return hmac.New(func() hash.Hash {
h, e := hashFn(nil)
if e != nil {
panic(e)
}
return h
}, key), nil
},
kind: cHash,
}, nil
} else if bl, ok := stringToHash[s]; ok && blake2Algorithms[bl] {
hashFn, cHash, err := newAlgorithmConstructor(s)
if err != nil {
return nil, err
}
return &blakeMacAlgorithm{
fn: hashFn,
kind: cHash,
}, nil
} else {
return nil, fmt.Errorf("no MACer matching %q", s)
}
}

120
vendor/github.com/go-fed/httpsig/digest.go generated vendored Normal file
View File

@ -0,0 +1,120 @@
package httpsig
import (
"bytes"
"crypto"
"encoding/base64"
"fmt"
"hash"
"net/http"
"strings"
)
type DigestAlgorithm string
const (
DigestSha256 DigestAlgorithm = "SHA-256"
DigestSha512 = "SHA-512"
)
var digestToDef = map[DigestAlgorithm]crypto.Hash{
DigestSha256: crypto.SHA256,
DigestSha512: crypto.SHA512,
}
// IsSupportedDigestAlgorithm returns true if hte string is supported by this
// library, is not a hash known to be weak, and is supported by the hardware.
func IsSupportedDigestAlgorithm(algo string) bool {
uc := DigestAlgorithm(strings.ToUpper(algo))
c, ok := digestToDef[uc]
return ok && c.Available()
}
func getHash(alg DigestAlgorithm) (h hash.Hash, toUse DigestAlgorithm, err error) {
upper := DigestAlgorithm(strings.ToUpper(string(alg)))
c, ok := digestToDef[upper]
if !ok {
err = fmt.Errorf("unknown or unsupported Digest algorithm: %s", alg)
} else if !c.Available() {
err = fmt.Errorf("unavailable Digest algorithm: %s", alg)
} else {
h = c.New()
toUse = upper
}
return
}
const (
digestHeader = "Digest"
digestDelim = "="
)
func addDigest(r *http.Request, algo DigestAlgorithm, b []byte) (err error) {
_, ok := r.Header[digestHeader]
if ok {
err = fmt.Errorf("cannot add Digest: Digest is already set")
return
}
var h hash.Hash
var a DigestAlgorithm
h, a, err = getHash(algo)
if err != nil {
return
}
h.Write(b)
sum := h.Sum(nil)
r.Header.Add(digestHeader,
fmt.Sprintf("%s%s%s",
a,
digestDelim,
base64.StdEncoding.EncodeToString(sum[:])))
return
}
func addDigestResponse(r http.ResponseWriter, algo DigestAlgorithm, b []byte) (err error) {
_, ok := r.Header()[digestHeader]
if ok {
err = fmt.Errorf("cannot add Digest: Digest is already set")
return
}
var h hash.Hash
var a DigestAlgorithm
h, a, err = getHash(algo)
if err != nil {
return
}
h.Write(b)
sum := h.Sum(nil)
r.Header().Add(digestHeader,
fmt.Sprintf("%s%s%s",
a,
digestDelim,
base64.StdEncoding.EncodeToString(sum[:])))
return
}
func verifyDigest(r *http.Request, body *bytes.Buffer) (err error) {
d := r.Header.Get(digestHeader)
if len(d) == 0 {
err = fmt.Errorf("cannot verify Digest: request has no Digest header")
return
}
elem := strings.SplitN(d, digestDelim, 2)
if len(elem) != 2 {
err = fmt.Errorf("cannot verify Digest: malformed Digest: %s", d)
return
}
var h hash.Hash
h, _, err = getHash(DigestAlgorithm(elem[0]))
if err != nil {
return
}
h.Write(body.Bytes())
sum := h.Sum(nil)
encSum := base64.StdEncoding.EncodeToString(sum[:])
if encSum != elem[1] {
err = fmt.Errorf("cannot verify Digest: header Digest does not match the digest of the request body")
return
}
return
}

361
vendor/github.com/go-fed/httpsig/httpsig.go generated vendored Normal file
View File

@ -0,0 +1,361 @@
// Implements HTTP request and response signing and verification. Supports the
// major MAC and asymmetric key signature algorithms. It has several safety
// restrictions: One, none of the widely known non-cryptographically safe
// algorithms are permitted; Two, the RSA SHA256 algorithms must be available in
// the binary (and it should, barring export restrictions); Finally, the library
// assumes either the 'Authorizationn' or 'Signature' headers are to be set (but
// not both).
package httpsig
import (
"crypto"
"fmt"
"net/http"
"strings"
"time"
"golang.org/x/crypto/ssh"
)
// Algorithm specifies a cryptography secure algorithm for signing HTTP requests
// and responses.
type Algorithm string
const (
// MAC-based algoirthms.
HMAC_SHA224 Algorithm = hmacPrefix + "-" + sha224String
HMAC_SHA256 Algorithm = hmacPrefix + "-" + sha256String
HMAC_SHA384 Algorithm = hmacPrefix + "-" + sha384String
HMAC_SHA512 Algorithm = hmacPrefix + "-" + sha512String
HMAC_RIPEMD160 Algorithm = hmacPrefix + "-" + ripemd160String
HMAC_SHA3_224 Algorithm = hmacPrefix + "-" + sha3_224String
HMAC_SHA3_256 Algorithm = hmacPrefix + "-" + sha3_256String
HMAC_SHA3_384 Algorithm = hmacPrefix + "-" + sha3_384String
HMAC_SHA3_512 Algorithm = hmacPrefix + "-" + sha3_512String
HMAC_SHA512_224 Algorithm = hmacPrefix + "-" + sha512_224String
HMAC_SHA512_256 Algorithm = hmacPrefix + "-" + sha512_256String
HMAC_BLAKE2S_256 Algorithm = hmacPrefix + "-" + blake2s_256String
HMAC_BLAKE2B_256 Algorithm = hmacPrefix + "-" + blake2b_256String
HMAC_BLAKE2B_384 Algorithm = hmacPrefix + "-" + blake2b_384String
HMAC_BLAKE2B_512 Algorithm = hmacPrefix + "-" + blake2b_512String
BLAKE2S_256 Algorithm = blake2s_256String
BLAKE2B_256 Algorithm = blake2b_256String
BLAKE2B_384 Algorithm = blake2b_384String
BLAKE2B_512 Algorithm = blake2b_512String
// RSA-based algorithms.
RSA_SHA1 Algorithm = rsaPrefix + "-" + sha1String
RSA_SHA224 Algorithm = rsaPrefix + "-" + sha224String
// RSA_SHA256 is the default algorithm.
RSA_SHA256 Algorithm = rsaPrefix + "-" + sha256String
RSA_SHA384 Algorithm = rsaPrefix + "-" + sha384String
RSA_SHA512 Algorithm = rsaPrefix + "-" + sha512String
RSA_RIPEMD160 Algorithm = rsaPrefix + "-" + ripemd160String
// ECDSA algorithms
ECDSA_SHA224 Algorithm = ecdsaPrefix + "-" + sha224String
ECDSA_SHA256 Algorithm = ecdsaPrefix + "-" + sha256String
ECDSA_SHA384 Algorithm = ecdsaPrefix + "-" + sha384String
ECDSA_SHA512 Algorithm = ecdsaPrefix + "-" + sha512String
ECDSA_RIPEMD160 Algorithm = ecdsaPrefix + "-" + ripemd160String
// ED25519 algorithms
// can only be SHA512
ED25519 Algorithm = ed25519Prefix
// Just because you can glue things together, doesn't mean they will
// work. The following options are not supported.
rsa_SHA3_224 Algorithm = rsaPrefix + "-" + sha3_224String
rsa_SHA3_256 Algorithm = rsaPrefix + "-" + sha3_256String
rsa_SHA3_384 Algorithm = rsaPrefix + "-" + sha3_384String
rsa_SHA3_512 Algorithm = rsaPrefix + "-" + sha3_512String
rsa_SHA512_224 Algorithm = rsaPrefix + "-" + sha512_224String
rsa_SHA512_256 Algorithm = rsaPrefix + "-" + sha512_256String
rsa_BLAKE2S_256 Algorithm = rsaPrefix + "-" + blake2s_256String
rsa_BLAKE2B_256 Algorithm = rsaPrefix + "-" + blake2b_256String
rsa_BLAKE2B_384 Algorithm = rsaPrefix + "-" + blake2b_384String
rsa_BLAKE2B_512 Algorithm = rsaPrefix + "-" + blake2b_512String
)
// HTTP Signatures can be applied to different HTTP headers, depending on the
// expected application behavior.
type SignatureScheme string
const (
// Signature will place the HTTP Signature into the 'Signature' HTTP
// header.
Signature SignatureScheme = "Signature"
// Authorization will place the HTTP Signature into the 'Authorization'
// HTTP header.
Authorization SignatureScheme = "Authorization"
)
const (
// The HTTP Signatures specification uses the "Signature" auth-scheme
// for the Authorization header. This is coincidentally named, but not
// semantically the same, as the "Signature" HTTP header value.
signatureAuthScheme = "Signature"
)
// There are subtle differences to the values in the header. The Authorization
// header has an 'auth-scheme' value that must be prefixed to the rest of the
// key and values.
func (s SignatureScheme) authScheme() string {
switch s {
case Authorization:
return signatureAuthScheme
default:
return ""
}
}
// Signers will sign HTTP requests or responses based on the algorithms and
// headers selected at creation time.
//
// Signers are not safe to use between multiple goroutines.
//
// Note that signatures do set the deprecated 'algorithm' parameter for
// backwards compatibility.
type Signer interface {
// SignRequest signs the request using a private key. The public key id
// is used by the HTTP server to identify which key to use to verify the
// signature.
//
// If the Signer was created using a MAC based algorithm, then the key
// is expected to be of type []byte. If the Signer was created using an
// RSA based algorithm, then the private key is expected to be of type
// *rsa.PrivateKey.
//
// A Digest (RFC 3230) will be added to the request. The body provided
// must match the body used in the request, and is allowed to be nil.
// The Digest ensures the request body is not tampered with in flight,
// and if the signer is created to also sign the "Digest" header, the
// HTTP Signature will then ensure both the Digest and body are not both
// modified to maliciously represent different content.
SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http.Request, body []byte) error
// SignResponse signs the response using a private key. The public key
// id is used by the HTTP client to identify which key to use to verify
// the signature.
//
// If the Signer was created using a MAC based algorithm, then the key
// is expected to be of type []byte. If the Signer was created using an
// RSA based algorithm, then the private key is expected to be of type
// *rsa.PrivateKey.
//
// A Digest (RFC 3230) will be added to the response. The body provided
// must match the body written in the response, and is allowed to be
// nil. The Digest ensures the response body is not tampered with in
// flight, and if the signer is created to also sign the "Digest"
// header, the HTTP Signature will then ensure both the Digest and body
// are not both modified to maliciously represent different content.
SignResponse(pKey crypto.PrivateKey, pubKeyId string, r http.ResponseWriter, body []byte) error
}
// NewSigner creates a new Signer with the provided algorithm preferences to
// make HTTP signatures. Only the first available algorithm will be used, which
// is returned by this function along with the Signer. If none of the preferred
// algorithms were available, then the default algorithm is used. The headers
// specified will be included into the HTTP signatures.
//
// The Digest will also be calculated on a request's body using the provided
// digest algorithm, if "Digest" is one of the headers listed.
//
// The provided scheme determines which header is populated with the HTTP
// Signature.
//
// An error is returned if an unknown or a known cryptographically insecure
// Algorithm is provided.
func NewSigner(prefs []Algorithm, dAlgo DigestAlgorithm, headers []string, scheme SignatureScheme, expiresIn int64) (Signer, Algorithm, error) {
for _, pref := range prefs {
s, err := newSigner(pref, dAlgo, headers, scheme, expiresIn)
if err != nil {
continue
}
return s, pref, err
}
s, err := newSigner(defaultAlgorithm, dAlgo, headers, scheme, expiresIn)
return s, defaultAlgorithm, err
}
// Signers will sign HTTP requests or responses based on the algorithms and
// headers selected at creation time.
//
// Signers are not safe to use between multiple goroutines.
//
// Note that signatures do set the deprecated 'algorithm' parameter for
// backwards compatibility.
type SSHSigner interface {
// SignRequest signs the request using ssh.Signer.
// The public key id is used by the HTTP server to identify which key to use
// to verify the signature.
//
// A Digest (RFC 3230) will be added to the request. The body provided
// must match the body used in the request, and is allowed to be nil.
// The Digest ensures the request body is not tampered with in flight,
// and if the signer is created to also sign the "Digest" header, the
// HTTP Signature will then ensure both the Digest and body are not both
// modified to maliciously represent different content.
SignRequest(pubKeyId string, r *http.Request, body []byte) error
// SignResponse signs the response using ssh.Signer. The public key
// id is used by the HTTP client to identify which key to use to verify
// the signature.
//
// A Digest (RFC 3230) will be added to the response. The body provided
// must match the body written in the response, and is allowed to be
// nil. The Digest ensures the response body is not tampered with in
// flight, and if the signer is created to also sign the "Digest"
// header, the HTTP Signature will then ensure both the Digest and body
// are not both modified to maliciously represent different content.
SignResponse(pubKeyId string, r http.ResponseWriter, body []byte) error
}
// NewwSSHSigner creates a new Signer using the specified ssh.Signer
// At the moment only ed25519 ssh keys are supported.
// The headers specified will be included into the HTTP signatures.
//
// The Digest will also be calculated on a request's body using the provided
// digest algorithm, if "Digest" is one of the headers listed.
//
// The provided scheme determines which header is populated with the HTTP
// Signature.
func NewSSHSigner(s ssh.Signer, dAlgo DigestAlgorithm, headers []string, scheme SignatureScheme, expiresIn int64) (SSHSigner, Algorithm, error) {
sshAlgo := getSSHAlgorithm(s.PublicKey().Type())
if sshAlgo == "" {
return nil, "", fmt.Errorf("key type: %s not supported yet.", s.PublicKey().Type())
}
signer, err := newSSHSigner(s, sshAlgo, dAlgo, headers, scheme, expiresIn)
if err != nil {
return nil, "", err
}
return signer, sshAlgo, nil
}
func getSSHAlgorithm(pkType string) Algorithm {
switch {
case strings.HasPrefix(pkType, sshPrefix+"-"+ed25519Prefix):
return ED25519
case strings.HasPrefix(pkType, sshPrefix+"-"+rsaPrefix):
return RSA_SHA1
}
return ""
}
// Verifier verifies HTTP Signatures.
//
// It will determine which of the supported headers has the parameters
// that define the signature.
//
// Verifiers are not safe to use between multiple goroutines.
//
// Note that verification ignores the deprecated 'algorithm' parameter.
type Verifier interface {
// KeyId gets the public key id that the signature is signed with.
//
// Note that the application is expected to determine the algorithm
// used based on metadata or out-of-band information for this key id.
KeyId() string
// Verify accepts the public key specified by KeyId and returns an
// error if verification fails or if the signature is malformed. The
// algorithm must be the one used to create the signature in order to
// pass verification. The algorithm is determined based on metadata or
// out-of-band information for the key id.
//
// If the signature was created using a MAC based algorithm, then the
// key is expected to be of type []byte. If the signature was created
// using an RSA based algorithm, then the public key is expected to be
// of type *rsa.PublicKey.
Verify(pKey crypto.PublicKey, algo Algorithm) error
}
const (
// host is treated specially because golang may not include it in the
// request header map on the server side of a request.
hostHeader = "Host"
)
// NewVerifier verifies the given request. It returns an error if the HTTP
// Signature parameters are not present in any headers, are present in more than
// one header, are malformed, or are missing required parameters. It ignores
// unknown HTTP Signature parameters.
func NewVerifier(r *http.Request) (Verifier, error) {
h := r.Header
if _, hasHostHeader := h[hostHeader]; len(r.Host) > 0 && !hasHostHeader {
h[hostHeader] = []string{r.Host}
}
return newVerifier(h, func(h http.Header, toInclude []string, created int64, expires int64) (string, error) {
return signatureString(h, toInclude, addRequestTarget(r), created, expires)
})
}
// NewResponseVerifier verifies the given response. It returns errors under the
// same conditions as NewVerifier.
func NewResponseVerifier(r *http.Response) (Verifier, error) {
return newVerifier(r.Header, func(h http.Header, toInclude []string, created int64, expires int64) (string, error) {
return signatureString(h, toInclude, requestTargetNotPermitted, created, expires)
})
}
func newSSHSigner(sshSigner ssh.Signer, algo Algorithm, dAlgo DigestAlgorithm, headers []string, scheme SignatureScheme, expiresIn int64) (SSHSigner, error) {
var expires, created int64 = 0, 0
if expiresIn != 0 {
created = time.Now().Unix()
expires = created + expiresIn
}
s, err := signerFromSSHSigner(sshSigner, string(algo))
if err != nil {
return nil, fmt.Errorf("no crypto implementation available for ssh algo %q", algo)
}
a := &asymmSSHSigner{
asymmSigner: &asymmSigner{
s: s,
dAlgo: dAlgo,
headers: headers,
targetHeader: scheme,
prefix: scheme.authScheme(),
created: created,
expires: expires,
},
}
return a, nil
}
func newSigner(algo Algorithm, dAlgo DigestAlgorithm, headers []string, scheme SignatureScheme, expiresIn int64) (Signer, error) {
var expires, created int64 = 0, 0
if expiresIn != 0 {
created = time.Now().Unix()
expires = created + expiresIn
}
s, err := signerFromString(string(algo))
if err == nil {
a := &asymmSigner{
s: s,
dAlgo: dAlgo,
headers: headers,
targetHeader: scheme,
prefix: scheme.authScheme(),
created: created,
expires: expires,
}
return a, nil
}
m, err := macerFromString(string(algo))
if err != nil {
return nil, fmt.Errorf("no crypto implementation available for %q", algo)
}
c := &macSigner{
m: m,
dAlgo: dAlgo,
headers: headers,
targetHeader: scheme,
prefix: scheme.authScheme(),
created: created,
expires: expires,
}
return c, nil
}

334
vendor/github.com/go-fed/httpsig/signing.go generated vendored Normal file
View File

@ -0,0 +1,334 @@
package httpsig
import (
"bytes"
"crypto"
"crypto/rand"
"encoding/base64"
"fmt"
"net/http"
"net/textproto"
"strconv"
"strings"
)
const (
// Signature Parameters
keyIdParameter = "keyId"
algorithmParameter = "algorithm"
headersParameter = "headers"
signatureParameter = "signature"
prefixSeparater = " "
parameterKVSeparater = "="
parameterValueDelimiter = "\""
parameterSeparater = ","
headerParameterValueDelim = " "
// RequestTarget specifies to include the http request method and
// entire URI in the signature. Pass it as a header to NewSigner.
RequestTarget = "(request-target)"
createdKey = "created"
expiresKey = "expires"
dateHeader = "date"
// Signature String Construction
headerFieldDelimiter = ": "
headersDelimiter = "\n"
headerValueDelimiter = ", "
requestTargetSeparator = " "
)
var defaultHeaders = []string{dateHeader}
var _ Signer = &macSigner{}
type macSigner struct {
m macer
makeDigest bool
dAlgo DigestAlgorithm
headers []string
targetHeader SignatureScheme
prefix string
created int64
expires int64
}
func (m *macSigner) SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http.Request, body []byte) error {
if body != nil {
err := addDigest(r, m.dAlgo, body)
if err != nil {
return err
}
}
s, err := m.signatureString(r)
if err != nil {
return err
}
enc, err := m.signSignature(pKey, s)
if err != nil {
return err
}
setSignatureHeader(r.Header, string(m.targetHeader), m.prefix, pubKeyId, m.m.String(), enc, m.headers, m.created, m.expires)
return nil
}
func (m *macSigner) SignResponse(pKey crypto.PrivateKey, pubKeyId string, r http.ResponseWriter, body []byte) error {
if body != nil {
err := addDigestResponse(r, m.dAlgo, body)
if err != nil {
return err
}
}
s, err := m.signatureStringResponse(r)
if err != nil {
return err
}
enc, err := m.signSignature(pKey, s)
if err != nil {
return err
}
setSignatureHeader(r.Header(), string(m.targetHeader), m.prefix, pubKeyId, m.m.String(), enc, m.headers, m.created, m.expires)
return nil
}
func (m *macSigner) signSignature(pKey crypto.PrivateKey, s string) (string, error) {
pKeyBytes, ok := pKey.([]byte)
if !ok {
return "", fmt.Errorf("private key for MAC signing must be of type []byte")
}
sig, err := m.m.Sign([]byte(s), pKeyBytes)
if err != nil {
return "", err
}
enc := base64.StdEncoding.EncodeToString(sig)
return enc, nil
}
func (m *macSigner) signatureString(r *http.Request) (string, error) {
return signatureString(r.Header, m.headers, addRequestTarget(r), m.created, m.expires)
}
func (m *macSigner) signatureStringResponse(r http.ResponseWriter) (string, error) {
return signatureString(r.Header(), m.headers, requestTargetNotPermitted, m.created, m.expires)
}
var _ Signer = &asymmSigner{}
type asymmSigner struct {
s signer
makeDigest bool
dAlgo DigestAlgorithm
headers []string
targetHeader SignatureScheme
prefix string
created int64
expires int64
}
func (a *asymmSigner) SignRequest(pKey crypto.PrivateKey, pubKeyId string, r *http.Request, body []byte) error {
if body != nil {
err := addDigest(r, a.dAlgo, body)
if err != nil {
return err
}
}
s, err := a.signatureString(r)
if err != nil {
return err
}
enc, err := a.signSignature(pKey, s)
if err != nil {
return err
}
setSignatureHeader(r.Header, string(a.targetHeader), a.prefix, pubKeyId, a.s.String(), enc, a.headers, a.created, a.expires)
return nil
}
func (a *asymmSigner) SignResponse(pKey crypto.PrivateKey, pubKeyId string, r http.ResponseWriter, body []byte) error {
if body != nil {
err := addDigestResponse(r, a.dAlgo, body)
if err != nil {
return err
}
}
s, err := a.signatureStringResponse(r)
if err != nil {
return err
}
enc, err := a.signSignature(pKey, s)
if err != nil {
return err
}
setSignatureHeader(r.Header(), string(a.targetHeader), a.prefix, pubKeyId, a.s.String(), enc, a.headers, a.created, a.expires)
return nil
}
func (a *asymmSigner) signSignature(pKey crypto.PrivateKey, s string) (string, error) {
sig, err := a.s.Sign(rand.Reader, pKey, []byte(s))
if err != nil {
return "", err
}
enc := base64.StdEncoding.EncodeToString(sig)
return enc, nil
}
func (a *asymmSigner) signatureString(r *http.Request) (string, error) {
return signatureString(r.Header, a.headers, addRequestTarget(r), a.created, a.expires)
}
func (a *asymmSigner) signatureStringResponse(r http.ResponseWriter) (string, error) {
return signatureString(r.Header(), a.headers, requestTargetNotPermitted, a.created, a.expires)
}
var _ SSHSigner = &asymmSSHSigner{}
type asymmSSHSigner struct {
*asymmSigner
}
func (a *asymmSSHSigner) SignRequest(pubKeyId string, r *http.Request, body []byte) error {
return a.asymmSigner.SignRequest(nil, pubKeyId, r, body)
}
func (a *asymmSSHSigner) SignResponse(pubKeyId string, r http.ResponseWriter, body []byte) error {
return a.asymmSigner.SignResponse(nil, pubKeyId, r, body)
}
func setSignatureHeader(h http.Header, targetHeader, prefix, pubKeyId, algo, enc string, headers []string, created int64, expires int64) {
if len(headers) == 0 {
headers = defaultHeaders
}
var b bytes.Buffer
// KeyId
b.WriteString(prefix)
if len(prefix) > 0 {
b.WriteString(prefixSeparater)
}
b.WriteString(keyIdParameter)
b.WriteString(parameterKVSeparater)
b.WriteString(parameterValueDelimiter)
b.WriteString(pubKeyId)
b.WriteString(parameterValueDelimiter)
b.WriteString(parameterSeparater)
// Algorithm
b.WriteString(algorithmParameter)
b.WriteString(parameterKVSeparater)
b.WriteString(parameterValueDelimiter)
b.WriteString("hs2019") //real algorithm is hidden, see newest version of spec draft
b.WriteString(parameterValueDelimiter)
b.WriteString(parameterSeparater)
hasCreated := false
hasExpires := false
for _, h := range headers {
val := strings.ToLower(h)
if val == "("+createdKey+")" {
hasCreated = true
} else if val == "("+expiresKey+")" {
hasExpires = true
}
}
// Created
if hasCreated == true {
b.WriteString(createdKey)
b.WriteString(parameterKVSeparater)
b.WriteString(strconv.FormatInt(created, 10))
b.WriteString(parameterSeparater)
}
// Expires
if hasExpires == true {
b.WriteString(expiresKey)
b.WriteString(parameterKVSeparater)
b.WriteString(strconv.FormatInt(expires, 10))
b.WriteString(parameterSeparater)
}
// Headers
b.WriteString(headersParameter)
b.WriteString(parameterKVSeparater)
b.WriteString(parameterValueDelimiter)
for i, h := range headers {
b.WriteString(strings.ToLower(h))
if i != len(headers)-1 {
b.WriteString(headerParameterValueDelim)
}
}
b.WriteString(parameterValueDelimiter)
b.WriteString(parameterSeparater)
// Signature
b.WriteString(signatureParameter)
b.WriteString(parameterKVSeparater)
b.WriteString(parameterValueDelimiter)
b.WriteString(enc)
b.WriteString(parameterValueDelimiter)
h.Add(targetHeader, b.String())
}
func requestTargetNotPermitted(b *bytes.Buffer) error {
return fmt.Errorf("cannot sign with %q on anything other than an http request", RequestTarget)
}
func addRequestTarget(r *http.Request) func(b *bytes.Buffer) error {
return func(b *bytes.Buffer) error {
b.WriteString(RequestTarget)
b.WriteString(headerFieldDelimiter)
b.WriteString(strings.ToLower(r.Method))
b.WriteString(requestTargetSeparator)
b.WriteString(r.URL.Path)
if r.URL.RawQuery != "" {
b.WriteString("?")
b.WriteString(r.URL.RawQuery)
}
return nil
}
}
func signatureString(values http.Header, include []string, requestTargetFn func(b *bytes.Buffer) error, created int64, expires int64) (string, error) {
if len(include) == 0 {
include = defaultHeaders
}
var b bytes.Buffer
for n, i := range include {
i := strings.ToLower(i)
if i == RequestTarget {
err := requestTargetFn(&b)
if err != nil {
return "", err
}
} else if i == "("+expiresKey+")" {
if expires == 0 {
return "", fmt.Errorf("missing expires value")
}
b.WriteString(i)
b.WriteString(headerFieldDelimiter)
b.WriteString(strconv.FormatInt(expires, 10))
} else if i == "("+createdKey+")" {
if created == 0 {
return "", fmt.Errorf("missing created value")
}
b.WriteString(i)
b.WriteString(headerFieldDelimiter)
b.WriteString(strconv.FormatInt(created, 10))
} else {
hv, ok := values[textproto.CanonicalMIMEHeaderKey(i)]
if !ok {
return "", fmt.Errorf("missing header %q", i)
}
b.WriteString(i)
b.WriteString(headerFieldDelimiter)
for i, v := range hv {
b.WriteString(strings.TrimSpace(v))
if i < len(hv)-1 {
b.WriteString(headerValueDelimiter)
}
}
}
if n < len(include)-1 {
b.WriteString(headersDelimiter)
}
}
return b.String(), nil
}

184
vendor/github.com/go-fed/httpsig/verifying.go generated vendored Normal file
View File

@ -0,0 +1,184 @@
package httpsig
import (
"crypto"
"encoding/base64"
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"time"
)
var _ Verifier = &verifier{}
type verifier struct {
header http.Header
kId string
signature string
created int64
expires int64
headers []string
sigStringFn func(http.Header, []string, int64, int64) (string, error)
}
func newVerifier(h http.Header, sigStringFn func(http.Header, []string, int64, int64) (string, error)) (*verifier, error) {
scheme, s, err := getSignatureScheme(h)
if err != nil {
return nil, err
}
kId, sig, headers, created, expires, err := getSignatureComponents(scheme, s)
if created != 0 {
//check if created is not in the future, we assume a maximum clock offset of 10 seconds
now := time.Now().Unix()
if created-now > 10 {
return nil, errors.New("created is in the future")
}
}
if expires != 0 {
//check if expires is in the past, we assume a maximum clock offset of 10 seconds
now := time.Now().Unix()
if now-expires > 10 {
return nil, errors.New("signature expired")
}
}
if err != nil {
return nil, err
}
return &verifier{
header: h,
kId: kId,
signature: sig,
created: created,
expires: expires,
headers: headers,
sigStringFn: sigStringFn,
}, nil
}
func (v *verifier) KeyId() string {
return v.kId
}
func (v *verifier) Verify(pKey crypto.PublicKey, algo Algorithm) error {
s, err := signerFromString(string(algo))
if err == nil {
return v.asymmVerify(s, pKey)
}
m, err := macerFromString(string(algo))
if err == nil {
return v.macVerify(m, pKey)
}
return fmt.Errorf("no crypto implementation available for %q", algo)
}
func (v *verifier) macVerify(m macer, pKey crypto.PublicKey) error {
key, ok := pKey.([]byte)
if !ok {
return fmt.Errorf("public key for MAC verifying must be of type []byte")
}
signature, err := v.sigStringFn(v.header, v.headers, v.created, v.expires)
if err != nil {
return err
}
actualMAC, err := base64.StdEncoding.DecodeString(v.signature)
if err != nil {
return err
}
ok, err = m.Equal([]byte(signature), actualMAC, key)
if err != nil {
return err
} else if !ok {
return fmt.Errorf("invalid http signature")
}
return nil
}
func (v *verifier) asymmVerify(s signer, pKey crypto.PublicKey) error {
toHash, err := v.sigStringFn(v.header, v.headers, v.created, v.expires)
if err != nil {
return err
}
signature, err := base64.StdEncoding.DecodeString(v.signature)
if err != nil {
return err
}
err = s.Verify(pKey, []byte(toHash), signature)
if err != nil {
return err
}
return nil
}
func getSignatureScheme(h http.Header) (scheme SignatureScheme, val string, err error) {
s := h.Get(string(Signature))
sigHasAll := strings.Contains(s, keyIdParameter) ||
strings.Contains(s, headersParameter) ||
strings.Contains(s, signatureParameter)
a := h.Get(string(Authorization))
authHasAll := strings.Contains(a, keyIdParameter) ||
strings.Contains(a, headersParameter) ||
strings.Contains(a, signatureParameter)
if sigHasAll && authHasAll {
err = fmt.Errorf("both %q and %q have signature parameters", Signature, Authorization)
return
} else if !sigHasAll && !authHasAll {
err = fmt.Errorf("neither %q nor %q have signature parameters", Signature, Authorization)
return
} else if sigHasAll {
val = s
scheme = Signature
return
} else { // authHasAll
val = a
scheme = Authorization
return
}
}
func getSignatureComponents(scheme SignatureScheme, s string) (kId, sig string, headers []string, created int64, expires int64, err error) {
if as := scheme.authScheme(); len(as) > 0 {
s = strings.TrimPrefix(s, as+prefixSeparater)
}
params := strings.Split(s, parameterSeparater)
for _, p := range params {
kv := strings.SplitN(p, parameterKVSeparater, 2)
if len(kv) != 2 {
err = fmt.Errorf("malformed http signature parameter: %v", kv)
return
}
k := kv[0]
v := strings.Trim(kv[1], parameterValueDelimiter)
switch k {
case keyIdParameter:
kId = v
case createdKey:
created, err = strconv.ParseInt(v, 10, 64)
if err != nil {
return
}
case expiresKey:
expires, err = strconv.ParseInt(v, 10, 64)
if err != nil {
return
}
case algorithmParameter:
// Deprecated, ignore
case headersParameter:
headers = strings.Split(v, headerParameterValueDelim)
case signatureParameter:
sig = v
default:
// Ignore unrecognized parameters
}
}
if len(kId) == 0 {
err = fmt.Errorf("missing %q parameter in http signature", keyIdParameter)
} else if len(sig) == 0 {
err = fmt.Errorf("missing %q parameter in http signature", signatureParameter)
} else if len(headers) == 0 { // Optional
headers = defaultHeaders
}
return
}

45
vendor/github.com/hashicorp/go-version/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,45 @@
# 1.6.0 (June 28, 2022)
FEATURES:
- Add `Prerelease` function to `Constraint` to return true if the version includes a prerelease field ([#100](https://github.com/hashicorp/go-version/pull/100))
# 1.5.0 (May 18, 2022)
FEATURES:
- Use `encoding` `TextMarshaler` & `TextUnmarshaler` instead of JSON equivalents ([#95](https://github.com/hashicorp/go-version/pull/95))
- Add JSON handlers to allow parsing from/to JSON ([#93](https://github.com/hashicorp/go-version/pull/93))
# 1.4.0 (January 5, 2022)
FEATURES:
- Introduce `MustConstraints()` ([#87](https://github.com/hashicorp/go-version/pull/87))
- `Constraints`: Introduce `Equals()` and `sort.Interface` methods ([#88](https://github.com/hashicorp/go-version/pull/88))
# 1.3.0 (March 31, 2021)
Please note that CHANGELOG.md does not exist in the source code prior to this release.
FEATURES:
- Add `Core` function to return a version without prerelease or metadata ([#85](https://github.com/hashicorp/go-version/pull/85))
# 1.2.1 (June 17, 2020)
BUG FIXES:
- Prevent `Version.Equal` method from panicking on `nil` encounter ([#73](https://github.com/hashicorp/go-version/pull/73))
# 1.2.0 (April 23, 2019)
FEATURES:
- Add `GreaterThanOrEqual` and `LessThanOrEqual` helper methods ([#53](https://github.com/hashicorp/go-version/pull/53))
# 1.1.0 (Jan 07, 2019)
FEATURES:
- Add `NewSemver` constructor ([#45](https://github.com/hashicorp/go-version/pull/45))
# 1.0.0 (August 24, 2018)
Initial release.

354
vendor/github.com/hashicorp/go-version/LICENSE generated vendored Normal file
View File

@ -0,0 +1,354 @@
Mozilla Public License, version 2.0
1. Definitions
1.1. “Contributor”
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. “Contributor Version”
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributors Contribution.
1.3. “Contribution”
means Covered Software of a particular Contributor.
1.4. “Covered Software”
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. “Incompatible With Secondary Licenses”
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of version
1.1 or earlier of the License, but not also under the terms of a
Secondary License.
1.6. “Executable Form”
means any form of the work other than Source Code Form.
1.7. “Larger Work”
means a work that combines Covered Software with other material, in a separate
file or files, that is not Covered Software.
1.8. “License”
means this document.
1.9. “Licensable”
means having the right to grant, to the maximum extent possible, whether at the
time of the initial grant or subsequently, any and all of the rights conveyed by
this License.
1.10. “Modifications”
means any of the following:
a. any file in Source Code Form that results from an addition to, deletion
from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. “Patent Claims” of a Contributor
means any patent claim(s), including without limitation, method, process,
and apparatus claims, in any patent Licensable by such Contributor that
would be infringed, but for the grant of the License, by the making,
using, selling, offering for sale, having made, import, or transfer of
either its Contributions or its Contributor Version.
1.12. “Secondary License”
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. “Source Code Form”
means the form of the work preferred for making modifications.
1.14. “You” (or “Your”)
means an individual or a legal entity exercising rights under this
License. For legal entities, “You” includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, “control” means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or as
part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its Contributions
or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution become
effective for each Contribution on the date the Contributor first distributes
such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under this
License. No additional rights or licenses will be implied from the distribution
or licensing of Covered Software under this License. Notwithstanding Section
2.1(b) above, no patent license is granted by a Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third partys
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of its
Contributions.
This License does not grant any rights in the trademarks, service marks, or
logos of any Contributor (except as may be necessary to comply with the
notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this License
(see Section 10.2) or under the terms of a Secondary License (if permitted
under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its Contributions
are its original creation(s) or it has sufficient rights to grant the
rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under applicable
copyright doctrines of fair use, fair dealing, or other equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under the
terms of this License. You must inform recipients that the Source Code Form
of the Covered Software is governed by the terms of this License, and how
they can obtain a copy of this License. You may not attempt to alter or
restrict the recipients rights in the Source Code Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this License,
or sublicense it under different terms, provided that the license for
the Executable Form does not attempt to limit or alter the recipients
rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for the
Covered Software. If the Larger Work is a combination of Covered Software
with a work governed by one or more Secondary Licenses, and the Covered
Software is not Incompatible With Secondary Licenses, this License permits
You to additionally distribute such Covered Software under the terms of
such Secondary License(s), so that the recipient of the Larger Work may, at
their option, further distribute the Covered Software under the terms of
either this License or such Secondary License(s).
3.4. Notices
You may not remove or alter the substance of any license notices (including
copyright notices, patent notices, disclaimers of warranty, or limitations
of liability) contained within the Source Code Form of the Covered
Software, except that You may alter any license notices to the extent
required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on behalf
of any Contributor. You must make it absolutely clear that any such
warranty, support, indemnity, or liability obligation is offered by You
alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute, judicial
order, or regulation then You must: (a) comply with the terms of this License
to the maximum extent possible; and (b) describe the limitations and the code
they affect. Such description must be placed in a text file included with all
distributions of the Covered Software under this License. Except to the
extent prohibited by statute or regulation, such description must be
sufficiently detailed for a recipient of ordinary skill to be able to
understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
if such Contributor fails to notify You of the non-compliance by some
reasonable means prior to 60 days after You have come back into compliance.
Moreover, Your grants from a particular Contributor are reinstated on an
ongoing basis if such Contributor notifies You of the non-compliance by
some reasonable means, this is the first time You have received notice of
non-compliance with this License from such Contributor, and You become
compliant prior to 30 days after Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions, counter-claims,
and cross-claims) alleging that a Contributor Version directly or
indirectly infringes any patent, then the rights granted to You by any and
all Contributors for the Covered Software under Section 2.1 of this License
shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an “as is” basis, without
warranty of any kind, either expressed, implied, or statutory, including,
without limitation, warranties that the Covered Software is free of defects,
merchantable, fit for a particular purpose or non-infringing. The entire
risk as to the quality and performance of the Covered Software is with You.
Should any Covered Software prove defective in any respect, You (not any
Contributor) assume the cost of any necessary servicing, repair, or
correction. This disclaimer of warranty constitutes an essential part of this
License. No use of any Covered Software is authorized under this License
except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from such
partys negligence to the extent applicable law prohibits such limitation.
Some jurisdictions do not allow the exclusion or limitation of incidental or
consequential damages, so this exclusion and limitation may not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts of
a jurisdiction where the defendant maintains its principal place of business
and such litigation shall be governed by laws of that jurisdiction, without
reference to its conflict-of-law provisions. Nothing in this Section shall
prevent a partys ability to bring cross-claims or counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject matter
hereof. If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable. Any law or regulation which provides that the language of a
contract shall be construed against the drafter shall not be used to construe
this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version of
the License under which You originally received the Covered Software, or
under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a modified
version of this License if you rename the license and remove any
references to the name of the license steward (except to note that such
modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a relevant
directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - “Incompatible With Secondary Licenses” Notice
This Source Code Form is “Incompatible
With Secondary Licenses”, as defined by
the Mozilla Public License, v. 2.0.

66
vendor/github.com/hashicorp/go-version/README.md generated vendored Normal file
View File

@ -0,0 +1,66 @@
# Versioning Library for Go
[![Build Status](https://circleci.com/gh/hashicorp/go-version/tree/main.svg?style=svg)](https://circleci.com/gh/hashicorp/go-version/tree/main)
[![GoDoc](https://godoc.org/github.com/hashicorp/go-version?status.svg)](https://godoc.org/github.com/hashicorp/go-version)
go-version is a library for parsing versions and version constraints,
and verifying versions against a set of constraints. go-version
can sort a collection of versions properly, handles prerelease/beta
versions, can increment versions, etc.
Versions used with go-version must follow [SemVer](http://semver.org/).
## Installation and Usage
Package documentation can be found on
[GoDoc](http://godoc.org/github.com/hashicorp/go-version).
Installation can be done with a normal `go get`:
```
$ go get github.com/hashicorp/go-version
```
#### Version Parsing and Comparison
```go
v1, err := version.NewVersion("1.2")
v2, err := version.NewVersion("1.5+metadata")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}
```
#### Version Constraints
```go
v1, err := version.NewVersion("1.2")
// Constraints example.
constraints, err := version.NewConstraint(">= 1.0, < 1.4")
if constraints.Check(v1) {
fmt.Printf("%s satisfies constraints %s", v1, constraints)
}
```
#### Version Sorting
```go
versionsRaw := []string{"1.1", "0.7.1", "1.4-beta", "1.4", "2"}
versions := make([]*version.Version, len(versionsRaw))
for i, raw := range versionsRaw {
v, _ := version.NewVersion(raw)
versions[i] = v
}
// After this, the versions are properly sorted
sort.Sort(version.Collection(versions))
```
## Issues and Contributing
If you find an issue with this library, please report an issue. If you'd
like, we welcome any contributions. Fork this library and submit a pull
request.

296
vendor/github.com/hashicorp/go-version/constraint.go generated vendored Normal file
View File

@ -0,0 +1,296 @@
package version
import (
"fmt"
"reflect"
"regexp"
"sort"
"strings"
)
// Constraint represents a single constraint for a version, such as
// ">= 1.0".
type Constraint struct {
f constraintFunc
op operator
check *Version
original string
}
func (c *Constraint) Equals(con *Constraint) bool {
return c.op == con.op && c.check.Equal(con.check)
}
// Constraints is a slice of constraints. We make a custom type so that
// we can add methods to it.
type Constraints []*Constraint
type constraintFunc func(v, c *Version) bool
var constraintOperators map[string]constraintOperation
type constraintOperation struct {
op operator
f constraintFunc
}
var constraintRegexp *regexp.Regexp
func init() {
constraintOperators = map[string]constraintOperation{
"": {op: equal, f: constraintEqual},
"=": {op: equal, f: constraintEqual},
"!=": {op: notEqual, f: constraintNotEqual},
">": {op: greaterThan, f: constraintGreaterThan},
"<": {op: lessThan, f: constraintLessThan},
">=": {op: greaterThanEqual, f: constraintGreaterThanEqual},
"<=": {op: lessThanEqual, f: constraintLessThanEqual},
"~>": {op: pessimistic, f: constraintPessimistic},
}
ops := make([]string, 0, len(constraintOperators))
for k := range constraintOperators {
ops = append(ops, regexp.QuoteMeta(k))
}
constraintRegexp = regexp.MustCompile(fmt.Sprintf(
`^\s*(%s)\s*(%s)\s*$`,
strings.Join(ops, "|"),
VersionRegexpRaw))
}
// NewConstraint will parse one or more constraints from the given
// constraint string. The string must be a comma-separated list of
// constraints.
func NewConstraint(v string) (Constraints, error) {
vs := strings.Split(v, ",")
result := make([]*Constraint, len(vs))
for i, single := range vs {
c, err := parseSingle(single)
if err != nil {
return nil, err
}
result[i] = c
}
return Constraints(result), nil
}
// MustConstraints is a helper that wraps a call to a function
// returning (Constraints, error) and panics if error is non-nil.
func MustConstraints(c Constraints, err error) Constraints {
if err != nil {
panic(err)
}
return c
}
// Check tests if a version satisfies all the constraints.
func (cs Constraints) Check(v *Version) bool {
for _, c := range cs {
if !c.Check(v) {
return false
}
}
return true
}
// Equals compares Constraints with other Constraints
// for equality. This may not represent logical equivalence
// of compared constraints.
// e.g. even though '>0.1,>0.2' is logically equivalent
// to '>0.2' it is *NOT* treated as equal.
//
// Missing operator is treated as equal to '=', whitespaces
// are ignored and constraints are sorted before comaparison.
func (cs Constraints) Equals(c Constraints) bool {
if len(cs) != len(c) {
return false
}
// make copies to retain order of the original slices
left := make(Constraints, len(cs))
copy(left, cs)
sort.Stable(left)
right := make(Constraints, len(c))
copy(right, c)
sort.Stable(right)
// compare sorted slices
for i, con := range left {
if !con.Equals(right[i]) {
return false
}
}
return true
}
func (cs Constraints) Len() int {
return len(cs)
}
func (cs Constraints) Less(i, j int) bool {
if cs[i].op < cs[j].op {
return true
}
if cs[i].op > cs[j].op {
return false
}
return cs[i].check.LessThan(cs[j].check)
}
func (cs Constraints) Swap(i, j int) {
cs[i], cs[j] = cs[j], cs[i]
}
// Returns the string format of the constraints
func (cs Constraints) String() string {
csStr := make([]string, len(cs))
for i, c := range cs {
csStr[i] = c.String()
}
return strings.Join(csStr, ",")
}
// Check tests if a constraint is validated by the given version.
func (c *Constraint) Check(v *Version) bool {
return c.f(v, c.check)
}
// Prerelease returns true if the version underlying this constraint
// contains a prerelease field.
func (c *Constraint) Prerelease() bool {
return len(c.check.Prerelease()) > 0
}
func (c *Constraint) String() string {
return c.original
}
func parseSingle(v string) (*Constraint, error) {
matches := constraintRegexp.FindStringSubmatch(v)
if matches == nil {
return nil, fmt.Errorf("Malformed constraint: %s", v)
}
check, err := NewVersion(matches[2])
if err != nil {
return nil, err
}
cop := constraintOperators[matches[1]]
return &Constraint{
f: cop.f,
op: cop.op,
check: check,
original: v,
}, nil
}
func prereleaseCheck(v, c *Version) bool {
switch vPre, cPre := v.Prerelease() != "", c.Prerelease() != ""; {
case cPre && vPre:
// A constraint with a pre-release can only match a pre-release version
// with the same base segments.
return reflect.DeepEqual(c.Segments64(), v.Segments64())
case !cPre && vPre:
// A constraint without a pre-release can only match a version without a
// pre-release.
return false
case cPre && !vPre:
// OK, except with the pessimistic operator
case !cPre && !vPre:
// OK
}
return true
}
//-------------------------------------------------------------------
// Constraint functions
//-------------------------------------------------------------------
type operator rune
const (
equal operator = '='
notEqual operator = '≠'
greaterThan operator = '>'
lessThan operator = '<'
greaterThanEqual operator = '≥'
lessThanEqual operator = '≤'
pessimistic operator = '~'
)
func constraintEqual(v, c *Version) bool {
return v.Equal(c)
}
func constraintNotEqual(v, c *Version) bool {
return !v.Equal(c)
}
func constraintGreaterThan(v, c *Version) bool {
return prereleaseCheck(v, c) && v.Compare(c) == 1
}
func constraintLessThan(v, c *Version) bool {
return prereleaseCheck(v, c) && v.Compare(c) == -1
}
func constraintGreaterThanEqual(v, c *Version) bool {
return prereleaseCheck(v, c) && v.Compare(c) >= 0
}
func constraintLessThanEqual(v, c *Version) bool {
return prereleaseCheck(v, c) && v.Compare(c) <= 0
}
func constraintPessimistic(v, c *Version) bool {
// Using a pessimistic constraint with a pre-release, restricts versions to pre-releases
if !prereleaseCheck(v, c) || (c.Prerelease() != "" && v.Prerelease() == "") {
return false
}
// If the version being checked is naturally less than the constraint, then there
// is no way for the version to be valid against the constraint
if v.LessThan(c) {
return false
}
// We'll use this more than once, so grab the length now so it's a little cleaner
// to write the later checks
cs := len(c.segments)
// If the version being checked has less specificity than the constraint, then there
// is no way for the version to be valid against the constraint
if cs > len(v.segments) {
return false
}
// Check the segments in the constraint against those in the version. If the version
// being checked, at any point, does not have the same values in each index of the
// constraints segments, then it cannot be valid against the constraint.
for i := 0; i < c.si-1; i++ {
if v.segments[i] != c.segments[i] {
return false
}
}
// Check the last part of the segment in the constraint. If the version segment at
// this index is less than the constraints segment at this index, then it cannot
// be valid against the constraint
if c.segments[cs-1] > v.segments[cs-1] {
return false
}
// If nothing has rejected the version by now, it's valid
return true
}

407
vendor/github.com/hashicorp/go-version/version.go generated vendored Normal file
View File

@ -0,0 +1,407 @@
package version
import (
"bytes"
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
)
// The compiled regular expression used to test the validity of a version.
var (
versionRegexp *regexp.Regexp
semverRegexp *regexp.Regexp
)
// The raw regular expression string used for testing the validity
// of a version.
const (
VersionRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
`?`
// SemverRegexpRaw requires a separator between version and prerelease
SemverRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
`?`
)
// Version represents a single version.
type Version struct {
metadata string
pre string
segments []int64
si int
original string
}
func init() {
versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$")
semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$")
}
// NewVersion parses the given version and returns a new
// Version.
func NewVersion(v string) (*Version, error) {
return newVersion(v, versionRegexp)
}
// NewSemver parses the given version and returns a new
// Version that adheres strictly to SemVer specs
// https://semver.org/
func NewSemver(v string) (*Version, error) {
return newVersion(v, semverRegexp)
}
func newVersion(v string, pattern *regexp.Regexp) (*Version, error) {
matches := pattern.FindStringSubmatch(v)
if matches == nil {
return nil, fmt.Errorf("Malformed version: %s", v)
}
segmentsStr := strings.Split(matches[1], ".")
segments := make([]int64, len(segmentsStr))
for i, str := range segmentsStr {
val, err := strconv.ParseInt(str, 10, 64)
if err != nil {
return nil, fmt.Errorf(
"Error parsing version: %s", err)
}
segments[i] = val
}
// Even though we could support more than three segments, if we
// got less than three, pad it with 0s. This is to cover the basic
// default usecase of semver, which is MAJOR.MINOR.PATCH at the minimum
for i := len(segments); i < 3; i++ {
segments = append(segments, 0)
}
pre := matches[7]
if pre == "" {
pre = matches[4]
}
return &Version{
metadata: matches[10],
pre: pre,
segments: segments,
si: len(segmentsStr),
original: v,
}, nil
}
// Must is a helper that wraps a call to a function returning (*Version, error)
// and panics if error is non-nil.
func Must(v *Version, err error) *Version {
if err != nil {
panic(err)
}
return v
}
// Compare compares this version to another version. This
// returns -1, 0, or 1 if this version is smaller, equal,
// or larger than the other version, respectively.
//
// If you want boolean results, use the LessThan, Equal,
// GreaterThan, GreaterThanOrEqual or LessThanOrEqual methods.
func (v *Version) Compare(other *Version) int {
// A quick, efficient equality check
if v.String() == other.String() {
return 0
}
segmentsSelf := v.Segments64()
segmentsOther := other.Segments64()
// If the segments are the same, we must compare on prerelease info
if reflect.DeepEqual(segmentsSelf, segmentsOther) {
preSelf := v.Prerelease()
preOther := other.Prerelease()
if preSelf == "" && preOther == "" {
return 0
}
if preSelf == "" {
return 1
}
if preOther == "" {
return -1
}
return comparePrereleases(preSelf, preOther)
}
// Get the highest specificity (hS), or if they're equal, just use segmentSelf length
lenSelf := len(segmentsSelf)
lenOther := len(segmentsOther)
hS := lenSelf
if lenSelf < lenOther {
hS = lenOther
}
// Compare the segments
// Because a constraint could have more/less specificity than the version it's
// checking, we need to account for a lopsided or jagged comparison
for i := 0; i < hS; i++ {
if i > lenSelf-1 {
// This means Self had the lower specificity
// Check to see if the remaining segments in Other are all zeros
if !allZero(segmentsOther[i:]) {
// if not, it means that Other has to be greater than Self
return -1
}
break
} else if i > lenOther-1 {
// this means Other had the lower specificity
// Check to see if the remaining segments in Self are all zeros -
if !allZero(segmentsSelf[i:]) {
//if not, it means that Self has to be greater than Other
return 1
}
break
}
lhs := segmentsSelf[i]
rhs := segmentsOther[i]
if lhs == rhs {
continue
} else if lhs < rhs {
return -1
}
// Otherwis, rhs was > lhs, they're not equal
return 1
}
// if we got this far, they're equal
return 0
}
func allZero(segs []int64) bool {
for _, s := range segs {
if s != 0 {
return false
}
}
return true
}
func comparePart(preSelf string, preOther string) int {
if preSelf == preOther {
return 0
}
var selfInt int64
selfNumeric := true
selfInt, err := strconv.ParseInt(preSelf, 10, 64)
if err != nil {
selfNumeric = false
}
var otherInt int64
otherNumeric := true
otherInt, err = strconv.ParseInt(preOther, 10, 64)
if err != nil {
otherNumeric = false
}
// if a part is empty, we use the other to decide
if preSelf == "" {
if otherNumeric {
return -1
}
return 1
}
if preOther == "" {
if selfNumeric {
return 1
}
return -1
}
if selfNumeric && !otherNumeric {
return -1
} else if !selfNumeric && otherNumeric {
return 1
} else if !selfNumeric && !otherNumeric && preSelf > preOther {
return 1
} else if selfInt > otherInt {
return 1
}
return -1
}
func comparePrereleases(v string, other string) int {
// the same pre release!
if v == other {
return 0
}
// split both pre releases for analyse their parts
selfPreReleaseMeta := strings.Split(v, ".")
otherPreReleaseMeta := strings.Split(other, ".")
selfPreReleaseLen := len(selfPreReleaseMeta)
otherPreReleaseLen := len(otherPreReleaseMeta)
biggestLen := otherPreReleaseLen
if selfPreReleaseLen > otherPreReleaseLen {
biggestLen = selfPreReleaseLen
}
// loop for parts to find the first difference
for i := 0; i < biggestLen; i = i + 1 {
partSelfPre := ""
if i < selfPreReleaseLen {
partSelfPre = selfPreReleaseMeta[i]
}
partOtherPre := ""
if i < otherPreReleaseLen {
partOtherPre = otherPreReleaseMeta[i]
}
compare := comparePart(partSelfPre, partOtherPre)
// if parts are equals, continue the loop
if compare != 0 {
return compare
}
}
return 0
}
// Core returns a new version constructed from only the MAJOR.MINOR.PATCH
// segments of the version, without prerelease or metadata.
func (v *Version) Core() *Version {
segments := v.Segments64()
segmentsOnly := fmt.Sprintf("%d.%d.%d", segments[0], segments[1], segments[2])
return Must(NewVersion(segmentsOnly))
}
// Equal tests if two versions are equal.
func (v *Version) Equal(o *Version) bool {
if v == nil || o == nil {
return v == o
}
return v.Compare(o) == 0
}
// GreaterThan tests if this version is greater than another version.
func (v *Version) GreaterThan(o *Version) bool {
return v.Compare(o) > 0
}
// GreaterThanOrEqual tests if this version is greater than or equal to another version.
func (v *Version) GreaterThanOrEqual(o *Version) bool {
return v.Compare(o) >= 0
}
// LessThan tests if this version is less than another version.
func (v *Version) LessThan(o *Version) bool {
return v.Compare(o) < 0
}
// LessThanOrEqual tests if this version is less than or equal to another version.
func (v *Version) LessThanOrEqual(o *Version) bool {
return v.Compare(o) <= 0
}
// Metadata returns any metadata that was part of the version
// string.
//
// Metadata is anything that comes after the "+" in the version.
// For example, with "1.2.3+beta", the metadata is "beta".
func (v *Version) Metadata() string {
return v.metadata
}
// Prerelease returns any prerelease data that is part of the version,
// or blank if there is no prerelease data.
//
// Prerelease information is anything that comes after the "-" in the
// version (but before any metadata). For example, with "1.2.3-beta",
// the prerelease information is "beta".
func (v *Version) Prerelease() string {
return v.pre
}
// Segments returns the numeric segments of the version as a slice of ints.
//
// This excludes any metadata or pre-release information. For example,
// for a version "1.2.3-beta", segments will return a slice of
// 1, 2, 3.
func (v *Version) Segments() []int {
segmentSlice := make([]int, len(v.segments))
for i, v := range v.segments {
segmentSlice[i] = int(v)
}
return segmentSlice
}
// Segments64 returns the numeric segments of the version as a slice of int64s.
//
// This excludes any metadata or pre-release information. For example,
// for a version "1.2.3-beta", segments will return a slice of
// 1, 2, 3.
func (v *Version) Segments64() []int64 {
result := make([]int64, len(v.segments))
copy(result, v.segments)
return result
}
// String returns the full version string included pre-release
// and metadata information.
//
// This value is rebuilt according to the parsed segments and other
// information. Therefore, ambiguities in the version string such as
// prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and
// missing parts (1.0 => 1.0.0) will be made into a canonicalized form
// as shown in the parenthesized examples.
func (v *Version) String() string {
var buf bytes.Buffer
fmtParts := make([]string, len(v.segments))
for i, s := range v.segments {
// We can ignore err here since we've pre-parsed the values in segments
str := strconv.FormatInt(s, 10)
fmtParts[i] = str
}
fmt.Fprintf(&buf, strings.Join(fmtParts, "."))
if v.pre != "" {
fmt.Fprintf(&buf, "-%s", v.pre)
}
if v.metadata != "" {
fmt.Fprintf(&buf, "+%s", v.metadata)
}
return buf.String()
}
// Original returns the original parsed version as-is, including any
// potential whitespace, `v` prefix, etc.
func (v *Version) Original() string {
return v.original
}
// UnmarshalText implements encoding.TextUnmarshaler interface.
func (v *Version) UnmarshalText(b []byte) error {
temp, err := NewVersion(string(b))
if err != nil {
return err
}
*v = *temp
return nil
}
// MarshalText implements encoding.TextMarshaler interface.
func (v *Version) MarshalText() ([]byte, error) {
return []byte(v.String()), nil
}

View File

@ -0,0 +1,17 @@
package version
// Collection is a type that implements the sort.Interface interface
// so that versions can be sorted.
type Collection []*Version
func (v Collection) Len() int {
return len(v)
}
func (v Collection) Less(i, j int) bool {
return v[i].LessThan(v[j])
}
func (v Collection) Swap(i, j int) {
v[i], v[j] = v[j], v[i]
}

27
vendor/golang.org/x/crypto/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/crypto/PATENTS generated vendored Normal file
View File

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

291
vendor/golang.org/x/crypto/blake2b/blake2b.go generated vendored Normal file
View File

@ -0,0 +1,291 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package blake2b implements the BLAKE2b hash algorithm defined by RFC 7693
// and the extendable output function (XOF) BLAKE2Xb.
//
// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and
// produces digests of any size between 1 and 64 bytes.
// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf
// and for BLAKE2Xb see https://blake2.net/blake2x.pdf
//
// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512).
// If you need a secret-key MAC (message authentication code), use the New512
// function with a non-nil key.
//
// BLAKE2X is a construction to compute hash values larger than 64 bytes. It
// can produce hash values between 0 and 4 GiB.
package blake2b
import (
"encoding/binary"
"errors"
"hash"
)
const (
// The blocksize of BLAKE2b in bytes.
BlockSize = 128
// The hash size of BLAKE2b-512 in bytes.
Size = 64
// The hash size of BLAKE2b-384 in bytes.
Size384 = 48
// The hash size of BLAKE2b-256 in bytes.
Size256 = 32
)
var (
useAVX2 bool
useAVX bool
useSSE4 bool
)
var (
errKeySize = errors.New("blake2b: invalid key size")
errHashSize = errors.New("blake2b: invalid hash size")
)
var iv = [8]uint64{
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
}
// Sum512 returns the BLAKE2b-512 checksum of the data.
func Sum512(data []byte) [Size]byte {
var sum [Size]byte
checkSum(&sum, Size, data)
return sum
}
// Sum384 returns the BLAKE2b-384 checksum of the data.
func Sum384(data []byte) [Size384]byte {
var sum [Size]byte
var sum384 [Size384]byte
checkSum(&sum, Size384, data)
copy(sum384[:], sum[:Size384])
return sum384
}
// Sum256 returns the BLAKE2b-256 checksum of the data.
func Sum256(data []byte) [Size256]byte {
var sum [Size]byte
var sum256 [Size256]byte
checkSum(&sum, Size256, data)
copy(sum256[:], sum[:Size256])
return sum256
}
// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length.
// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long.
// The hash size can be a value between 1 and 64 but it is highly recommended to use
// values equal or greater than:
// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).
// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long).
// When the key is nil, the returned hash.Hash implements BinaryMarshaler
// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) }
func newDigest(hashSize int, key []byte) (*digest, error) {
if hashSize < 1 || hashSize > Size {
return nil, errHashSize
}
if len(key) > Size {
return nil, errKeySize
}
d := &digest{
size: hashSize,
keyLen: len(key),
}
copy(d.key[:], key)
d.Reset()
return d, nil
}
func checkSum(sum *[Size]byte, hashSize int, data []byte) {
h := iv
h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24)
var c [2]uint64
if length := len(data); length > BlockSize {
n := length &^ (BlockSize - 1)
if length == n {
n -= BlockSize
}
hashBlocks(&h, &c, 0, data[:n])
data = data[n:]
}
var block [BlockSize]byte
offset := copy(block[:], data)
remaining := uint64(BlockSize - offset)
if c[0] < remaining {
c[1]--
}
c[0] -= remaining
hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
for i, v := range h[:(hashSize+7)/8] {
binary.LittleEndian.PutUint64(sum[8*i:], v)
}
}
type digest struct {
h [8]uint64
c [2]uint64
size int
block [BlockSize]byte
offset int
key [BlockSize]byte
keyLen int
}
const (
magic = "b2b"
marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1
)
func (d *digest) MarshalBinary() ([]byte, error) {
if d.keyLen != 0 {
return nil, errors.New("crypto/blake2b: cannot marshal MACs")
}
b := make([]byte, 0, marshaledSize)
b = append(b, magic...)
for i := 0; i < 8; i++ {
b = appendUint64(b, d.h[i])
}
b = appendUint64(b, d.c[0])
b = appendUint64(b, d.c[1])
// Maximum value for size is 64
b = append(b, byte(d.size))
b = append(b, d.block[:]...)
b = append(b, byte(d.offset))
return b, nil
}
func (d *digest) UnmarshalBinary(b []byte) error {
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
return errors.New("crypto/blake2b: invalid hash state identifier")
}
if len(b) != marshaledSize {
return errors.New("crypto/blake2b: invalid hash state size")
}
b = b[len(magic):]
for i := 0; i < 8; i++ {
b, d.h[i] = consumeUint64(b)
}
b, d.c[0] = consumeUint64(b)
b, d.c[1] = consumeUint64(b)
d.size = int(b[0])
b = b[1:]
copy(d.block[:], b[:BlockSize])
b = b[BlockSize:]
d.offset = int(b[0])
return nil
}
func (d *digest) BlockSize() int { return BlockSize }
func (d *digest) Size() int { return d.size }
func (d *digest) Reset() {
d.h = iv
d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24)
d.offset, d.c[0], d.c[1] = 0, 0, 0
if d.keyLen > 0 {
d.block = d.key
d.offset = BlockSize
}
}
func (d *digest) Write(p []byte) (n int, err error) {
n = len(p)
if d.offset > 0 {
remaining := BlockSize - d.offset
if n <= remaining {
d.offset += copy(d.block[d.offset:], p)
return
}
copy(d.block[d.offset:], p[:remaining])
hashBlocks(&d.h, &d.c, 0, d.block[:])
d.offset = 0
p = p[remaining:]
}
if length := len(p); length > BlockSize {
nn := length &^ (BlockSize - 1)
if length == nn {
nn -= BlockSize
}
hashBlocks(&d.h, &d.c, 0, p[:nn])
p = p[nn:]
}
if len(p) > 0 {
d.offset += copy(d.block[:], p)
}
return
}
func (d *digest) Sum(sum []byte) []byte {
var hash [Size]byte
d.finalize(&hash)
return append(sum, hash[:d.size]...)
}
func (d *digest) finalize(hash *[Size]byte) {
var block [BlockSize]byte
copy(block[:], d.block[:d.offset])
remaining := uint64(BlockSize - d.offset)
c := d.c
if c[0] < remaining {
c[1]--
}
c[0] -= remaining
h := d.h
hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
for i, v := range h {
binary.LittleEndian.PutUint64(hash[8*i:], v)
}
}
func appendUint64(b []byte, x uint64) []byte {
var a [8]byte
binary.BigEndian.PutUint64(a[:], x)
return append(b, a[:]...)
}
func appendUint32(b []byte, x uint32) []byte {
var a [4]byte
binary.BigEndian.PutUint32(a[:], x)
return append(b, a[:]...)
}
func consumeUint64(b []byte) ([]byte, uint64) {
x := binary.BigEndian.Uint64(b)
return b[8:], x
}
func consumeUint32(b []byte) ([]byte, uint32) {
x := binary.BigEndian.Uint32(b)
return b[4:], x
}

View File

@ -0,0 +1,37 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build amd64 && gc && !purego
package blake2b
import "golang.org/x/sys/cpu"
func init() {
useAVX2 = cpu.X86.HasAVX2
useAVX = cpu.X86.HasAVX
useSSE4 = cpu.X86.HasSSE41
}
//go:noescape
func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
//go:noescape
func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
//go:noescape
func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
switch {
case useAVX2:
hashBlocksAVX2(h, c, flag, blocks)
case useAVX:
hashBlocksAVX(h, c, flag, blocks)
case useSSE4:
hashBlocksSSE4(h, c, flag, blocks)
default:
hashBlocksGeneric(h, c, flag, blocks)
}
}

744
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s generated vendored Normal file
View File

@ -0,0 +1,744 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build amd64 && gc && !purego
#include "textflag.h"
DATA ·AVX2_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
DATA ·AVX2_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
DATA ·AVX2_iv0<>+0x10(SB)/8, $0x3c6ef372fe94f82b
DATA ·AVX2_iv0<>+0x18(SB)/8, $0xa54ff53a5f1d36f1
GLOBL ·AVX2_iv0<>(SB), (NOPTR+RODATA), $32
DATA ·AVX2_iv1<>+0x00(SB)/8, $0x510e527fade682d1
DATA ·AVX2_iv1<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
DATA ·AVX2_iv1<>+0x10(SB)/8, $0x1f83d9abfb41bd6b
DATA ·AVX2_iv1<>+0x18(SB)/8, $0x5be0cd19137e2179
GLOBL ·AVX2_iv1<>(SB), (NOPTR+RODATA), $32
DATA ·AVX2_c40<>+0x00(SB)/8, $0x0201000706050403
DATA ·AVX2_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
DATA ·AVX2_c40<>+0x10(SB)/8, $0x0201000706050403
DATA ·AVX2_c40<>+0x18(SB)/8, $0x0a09080f0e0d0c0b
GLOBL ·AVX2_c40<>(SB), (NOPTR+RODATA), $32
DATA ·AVX2_c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·AVX2_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
DATA ·AVX2_c48<>+0x10(SB)/8, $0x0100070605040302
DATA ·AVX2_c48<>+0x18(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·AVX2_c48<>(SB), (NOPTR+RODATA), $32
DATA ·AVX_iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
DATA ·AVX_iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
GLOBL ·AVX_iv0<>(SB), (NOPTR+RODATA), $16
DATA ·AVX_iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b
DATA ·AVX_iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1
GLOBL ·AVX_iv1<>(SB), (NOPTR+RODATA), $16
DATA ·AVX_iv2<>+0x00(SB)/8, $0x510e527fade682d1
DATA ·AVX_iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
GLOBL ·AVX_iv2<>(SB), (NOPTR+RODATA), $16
DATA ·AVX_iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b
DATA ·AVX_iv3<>+0x08(SB)/8, $0x5be0cd19137e2179
GLOBL ·AVX_iv3<>(SB), (NOPTR+RODATA), $16
DATA ·AVX_c40<>+0x00(SB)/8, $0x0201000706050403
DATA ·AVX_c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
GLOBL ·AVX_c40<>(SB), (NOPTR+RODATA), $16
DATA ·AVX_c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·AVX_c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·AVX_c48<>(SB), (NOPTR+RODATA), $16
#define VPERMQ_0x39_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x39
#define VPERMQ_0x93_Y1_Y1 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xc9; BYTE $0x93
#define VPERMQ_0x4E_Y2_Y2 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xd2; BYTE $0x4e
#define VPERMQ_0x93_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x93
#define VPERMQ_0x39_Y3_Y3 BYTE $0xc4; BYTE $0xe3; BYTE $0xfd; BYTE $0x00; BYTE $0xdb; BYTE $0x39
#define ROUND_AVX2(m0, m1, m2, m3, t, c40, c48) \
VPADDQ m0, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFD $-79, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPSHUFB c40, Y1, Y1; \
VPADDQ m1, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFB c48, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPADDQ Y1, Y1, t; \
VPSRLQ $63, Y1, Y1; \
VPXOR t, Y1, Y1; \
VPERMQ_0x39_Y1_Y1; \
VPERMQ_0x4E_Y2_Y2; \
VPERMQ_0x93_Y3_Y3; \
VPADDQ m2, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFD $-79, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPSHUFB c40, Y1, Y1; \
VPADDQ m3, Y0, Y0; \
VPADDQ Y1, Y0, Y0; \
VPXOR Y0, Y3, Y3; \
VPSHUFB c48, Y3, Y3; \
VPADDQ Y3, Y2, Y2; \
VPXOR Y2, Y1, Y1; \
VPADDQ Y1, Y1, t; \
VPSRLQ $63, Y1, Y1; \
VPXOR t, Y1, Y1; \
VPERMQ_0x39_Y3_Y3; \
VPERMQ_0x4E_Y2_Y2; \
VPERMQ_0x93_Y1_Y1
#define VMOVQ_SI_X11_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x1E
#define VMOVQ_SI_X12_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x26
#define VMOVQ_SI_X13_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x2E
#define VMOVQ_SI_X14_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x36
#define VMOVQ_SI_X15_0 BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x3E
#define VMOVQ_SI_X11(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x5E; BYTE $n
#define VMOVQ_SI_X12(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x66; BYTE $n
#define VMOVQ_SI_X13(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x6E; BYTE $n
#define VMOVQ_SI_X14(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x76; BYTE $n
#define VMOVQ_SI_X15(n) BYTE $0xC5; BYTE $0x7A; BYTE $0x7E; BYTE $0x7E; BYTE $n
#define VPINSRQ_1_SI_X11_0 BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x1E; BYTE $0x01
#define VPINSRQ_1_SI_X12_0 BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x26; BYTE $0x01
#define VPINSRQ_1_SI_X13_0 BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x2E; BYTE $0x01
#define VPINSRQ_1_SI_X14_0 BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x36; BYTE $0x01
#define VPINSRQ_1_SI_X15_0 BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x3E; BYTE $0x01
#define VPINSRQ_1_SI_X11(n) BYTE $0xC4; BYTE $0x63; BYTE $0xA1; BYTE $0x22; BYTE $0x5E; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X12(n) BYTE $0xC4; BYTE $0x63; BYTE $0x99; BYTE $0x22; BYTE $0x66; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X13(n) BYTE $0xC4; BYTE $0x63; BYTE $0x91; BYTE $0x22; BYTE $0x6E; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X14(n) BYTE $0xC4; BYTE $0x63; BYTE $0x89; BYTE $0x22; BYTE $0x76; BYTE $n; BYTE $0x01
#define VPINSRQ_1_SI_X15(n) BYTE $0xC4; BYTE $0x63; BYTE $0x81; BYTE $0x22; BYTE $0x7E; BYTE $n; BYTE $0x01
#define VMOVQ_R8_X15 BYTE $0xC4; BYTE $0x41; BYTE $0xF9; BYTE $0x6E; BYTE $0xF8
#define VPINSRQ_1_R9_X15 BYTE $0xC4; BYTE $0x43; BYTE $0x81; BYTE $0x22; BYTE $0xF9; BYTE $0x01
// load msg: Y12 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y12(i0, i1, i2, i3) \
VMOVQ_SI_X12(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X12(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y12, Y12
// load msg: Y13 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y13(i0, i1, i2, i3) \
VMOVQ_SI_X13(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X13(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y13, Y13
// load msg: Y14 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y14(i0, i1, i2, i3) \
VMOVQ_SI_X14(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X14(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y14, Y14
// load msg: Y15 = (i0, i1, i2, i3)
// i0, i1, i2, i3 must not be 0
#define LOAD_MSG_AVX2_Y15(i0, i1, i2, i3) \
VMOVQ_SI_X15(i0*8); \
VMOVQ_SI_X11(i2*8); \
VPINSRQ_1_SI_X15(i1*8); \
VPINSRQ_1_SI_X11(i3*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15() \
VMOVQ_SI_X12_0; \
VMOVQ_SI_X11(4*8); \
VPINSRQ_1_SI_X12(2*8); \
VPINSRQ_1_SI_X11(6*8); \
VINSERTI128 $1, X11, Y12, Y12; \
LOAD_MSG_AVX2_Y13(1, 3, 5, 7); \
LOAD_MSG_AVX2_Y14(8, 10, 12, 14); \
LOAD_MSG_AVX2_Y15(9, 11, 13, 15)
#define LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3() \
LOAD_MSG_AVX2_Y12(14, 4, 9, 13); \
LOAD_MSG_AVX2_Y13(10, 8, 15, 6); \
VMOVQ_SI_X11(11*8); \
VPSHUFD $0x4E, 0*8(SI), X14; \
VPINSRQ_1_SI_X11(5*8); \
VINSERTI128 $1, X11, Y14, Y14; \
LOAD_MSG_AVX2_Y15(12, 2, 7, 3)
#define LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4() \
VMOVQ_SI_X11(5*8); \
VMOVDQU 11*8(SI), X12; \
VPINSRQ_1_SI_X11(15*8); \
VINSERTI128 $1, X11, Y12, Y12; \
VMOVQ_SI_X13(8*8); \
VMOVQ_SI_X11(2*8); \
VPINSRQ_1_SI_X13_0; \
VPINSRQ_1_SI_X11(13*8); \
VINSERTI128 $1, X11, Y13, Y13; \
LOAD_MSG_AVX2_Y14(10, 3, 7, 9); \
LOAD_MSG_AVX2_Y15(14, 6, 1, 4)
#define LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8() \
LOAD_MSG_AVX2_Y12(7, 3, 13, 11); \
LOAD_MSG_AVX2_Y13(9, 1, 12, 14); \
LOAD_MSG_AVX2_Y14(2, 5, 4, 15); \
VMOVQ_SI_X15(6*8); \
VMOVQ_SI_X11_0; \
VPINSRQ_1_SI_X15(10*8); \
VPINSRQ_1_SI_X11(8*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13() \
LOAD_MSG_AVX2_Y12(9, 5, 2, 10); \
VMOVQ_SI_X13_0; \
VMOVQ_SI_X11(4*8); \
VPINSRQ_1_SI_X13(7*8); \
VPINSRQ_1_SI_X11(15*8); \
VINSERTI128 $1, X11, Y13, Y13; \
LOAD_MSG_AVX2_Y14(14, 11, 6, 3); \
LOAD_MSG_AVX2_Y15(1, 12, 8, 13)
#define LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9() \
VMOVQ_SI_X12(2*8); \
VMOVQ_SI_X11_0; \
VPINSRQ_1_SI_X12(6*8); \
VPINSRQ_1_SI_X11(8*8); \
VINSERTI128 $1, X11, Y12, Y12; \
LOAD_MSG_AVX2_Y13(12, 10, 11, 3); \
LOAD_MSG_AVX2_Y14(4, 7, 15, 1); \
LOAD_MSG_AVX2_Y15(13, 5, 14, 9)
#define LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11() \
LOAD_MSG_AVX2_Y12(12, 1, 14, 4); \
LOAD_MSG_AVX2_Y13(5, 15, 13, 10); \
VMOVQ_SI_X14_0; \
VPSHUFD $0x4E, 8*8(SI), X11; \
VPINSRQ_1_SI_X14(6*8); \
VINSERTI128 $1, X11, Y14, Y14; \
LOAD_MSG_AVX2_Y15(7, 3, 2, 11)
#define LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10() \
LOAD_MSG_AVX2_Y12(13, 7, 12, 3); \
LOAD_MSG_AVX2_Y13(11, 14, 1, 9); \
LOAD_MSG_AVX2_Y14(5, 15, 8, 2); \
VMOVQ_SI_X15_0; \
VMOVQ_SI_X11(6*8); \
VPINSRQ_1_SI_X15(4*8); \
VPINSRQ_1_SI_X11(10*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5() \
VMOVQ_SI_X12(6*8); \
VMOVQ_SI_X11(11*8); \
VPINSRQ_1_SI_X12(14*8); \
VPINSRQ_1_SI_X11_0; \
VINSERTI128 $1, X11, Y12, Y12; \
LOAD_MSG_AVX2_Y13(15, 9, 3, 8); \
VMOVQ_SI_X11(1*8); \
VMOVDQU 12*8(SI), X14; \
VPINSRQ_1_SI_X11(10*8); \
VINSERTI128 $1, X11, Y14, Y14; \
VMOVQ_SI_X15(2*8); \
VMOVDQU 4*8(SI), X11; \
VPINSRQ_1_SI_X15(7*8); \
VINSERTI128 $1, X11, Y15, Y15
#define LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0() \
LOAD_MSG_AVX2_Y12(10, 8, 7, 1); \
VMOVQ_SI_X13(2*8); \
VPSHUFD $0x4E, 5*8(SI), X11; \
VPINSRQ_1_SI_X13(4*8); \
VINSERTI128 $1, X11, Y13, Y13; \
LOAD_MSG_AVX2_Y14(15, 9, 3, 13); \
VMOVQ_SI_X15(11*8); \
VMOVQ_SI_X11(12*8); \
VPINSRQ_1_SI_X15(14*8); \
VPINSRQ_1_SI_X11_0; \
VINSERTI128 $1, X11, Y15, Y15
// func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
TEXT ·hashBlocksAVX2(SB), 4, $320-48 // frame size = 288 + 32 byte alignment
MOVQ h+0(FP), AX
MOVQ c+8(FP), BX
MOVQ flag+16(FP), CX
MOVQ blocks_base+24(FP), SI
MOVQ blocks_len+32(FP), DI
MOVQ SP, DX
ADDQ $31, DX
ANDQ $~31, DX
MOVQ CX, 16(DX)
XORQ CX, CX
MOVQ CX, 24(DX)
VMOVDQU ·AVX2_c40<>(SB), Y4
VMOVDQU ·AVX2_c48<>(SB), Y5
VMOVDQU 0(AX), Y8
VMOVDQU 32(AX), Y9
VMOVDQU ·AVX2_iv0<>(SB), Y6
VMOVDQU ·AVX2_iv1<>(SB), Y7
MOVQ 0(BX), R8
MOVQ 8(BX), R9
MOVQ R9, 8(DX)
loop:
ADDQ $128, R8
MOVQ R8, 0(DX)
CMPQ R8, $128
JGE noinc
INCQ R9
MOVQ R9, 8(DX)
noinc:
VMOVDQA Y8, Y0
VMOVDQA Y9, Y1
VMOVDQA Y6, Y2
VPXOR 0(DX), Y7, Y3
LOAD_MSG_AVX2_0_2_4_6_1_3_5_7_8_10_12_14_9_11_13_15()
VMOVDQA Y12, 32(DX)
VMOVDQA Y13, 64(DX)
VMOVDQA Y14, 96(DX)
VMOVDQA Y15, 128(DX)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_14_4_9_13_10_8_15_6_1_0_11_5_12_2_7_3()
VMOVDQA Y12, 160(DX)
VMOVDQA Y13, 192(DX)
VMOVDQA Y14, 224(DX)
VMOVDQA Y15, 256(DX)
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_11_12_5_15_8_0_2_13_10_3_7_9_14_6_1_4()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_7_3_13_11_9_1_12_14_2_5_4_15_6_10_0_8()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_9_5_2_10_0_7_4_15_14_11_6_3_1_12_8_13()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_2_6_0_8_12_10_11_3_4_7_15_1_13_5_14_9()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_12_1_14_4_5_15_13_10_0_6_9_8_7_3_2_11()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_13_7_12_3_11_14_1_9_5_15_8_2_0_4_6_10()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_6_14_11_0_15_9_3_8_12_13_1_10_2_7_4_5()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
LOAD_MSG_AVX2_10_8_7_1_2_4_6_5_15_9_3_13_11_14_12_0()
ROUND_AVX2(Y12, Y13, Y14, Y15, Y10, Y4, Y5)
ROUND_AVX2(32(DX), 64(DX), 96(DX), 128(DX), Y10, Y4, Y5)
ROUND_AVX2(160(DX), 192(DX), 224(DX), 256(DX), Y10, Y4, Y5)
VPXOR Y0, Y8, Y8
VPXOR Y1, Y9, Y9
VPXOR Y2, Y8, Y8
VPXOR Y3, Y9, Y9
LEAQ 128(SI), SI
SUBQ $128, DI
JNE loop
MOVQ R8, 0(BX)
MOVQ R9, 8(BX)
VMOVDQU Y8, 0(AX)
VMOVDQU Y9, 32(AX)
VZEROUPPER
RET
#define VPUNPCKLQDQ_X2_X2_X15 BYTE $0xC5; BYTE $0x69; BYTE $0x6C; BYTE $0xFA
#define VPUNPCKLQDQ_X3_X3_X15 BYTE $0xC5; BYTE $0x61; BYTE $0x6C; BYTE $0xFB
#define VPUNPCKLQDQ_X7_X7_X15 BYTE $0xC5; BYTE $0x41; BYTE $0x6C; BYTE $0xFF
#define VPUNPCKLQDQ_X13_X13_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x11; BYTE $0x6C; BYTE $0xFD
#define VPUNPCKLQDQ_X14_X14_X15 BYTE $0xC4; BYTE $0x41; BYTE $0x09; BYTE $0x6C; BYTE $0xFE
#define VPUNPCKHQDQ_X15_X2_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x69; BYTE $0x6D; BYTE $0xD7
#define VPUNPCKHQDQ_X15_X3_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xDF
#define VPUNPCKHQDQ_X15_X6_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x49; BYTE $0x6D; BYTE $0xF7
#define VPUNPCKHQDQ_X15_X7_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xFF
#define VPUNPCKHQDQ_X15_X3_X2 BYTE $0xC4; BYTE $0xC1; BYTE $0x61; BYTE $0x6D; BYTE $0xD7
#define VPUNPCKHQDQ_X15_X7_X6 BYTE $0xC4; BYTE $0xC1; BYTE $0x41; BYTE $0x6D; BYTE $0xF7
#define VPUNPCKHQDQ_X15_X13_X3 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xDF
#define VPUNPCKHQDQ_X15_X13_X7 BYTE $0xC4; BYTE $0xC1; BYTE $0x11; BYTE $0x6D; BYTE $0xFF
#define SHUFFLE_AVX() \
VMOVDQA X6, X13; \
VMOVDQA X2, X14; \
VMOVDQA X4, X6; \
VPUNPCKLQDQ_X13_X13_X15; \
VMOVDQA X5, X4; \
VMOVDQA X6, X5; \
VPUNPCKHQDQ_X15_X7_X6; \
VPUNPCKLQDQ_X7_X7_X15; \
VPUNPCKHQDQ_X15_X13_X7; \
VPUNPCKLQDQ_X3_X3_X15; \
VPUNPCKHQDQ_X15_X2_X2; \
VPUNPCKLQDQ_X14_X14_X15; \
VPUNPCKHQDQ_X15_X3_X3; \
#define SHUFFLE_AVX_INV() \
VMOVDQA X2, X13; \
VMOVDQA X4, X14; \
VPUNPCKLQDQ_X2_X2_X15; \
VMOVDQA X5, X4; \
VPUNPCKHQDQ_X15_X3_X2; \
VMOVDQA X14, X5; \
VPUNPCKLQDQ_X3_X3_X15; \
VMOVDQA X6, X14; \
VPUNPCKHQDQ_X15_X13_X3; \
VPUNPCKLQDQ_X7_X7_X15; \
VPUNPCKHQDQ_X15_X6_X6; \
VPUNPCKLQDQ_X14_X14_X15; \
VPUNPCKHQDQ_X15_X7_X7; \
#define HALF_ROUND_AVX(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
VPADDQ m0, v0, v0; \
VPADDQ v2, v0, v0; \
VPADDQ m1, v1, v1; \
VPADDQ v3, v1, v1; \
VPXOR v0, v6, v6; \
VPXOR v1, v7, v7; \
VPSHUFD $-79, v6, v6; \
VPSHUFD $-79, v7, v7; \
VPADDQ v6, v4, v4; \
VPADDQ v7, v5, v5; \
VPXOR v4, v2, v2; \
VPXOR v5, v3, v3; \
VPSHUFB c40, v2, v2; \
VPSHUFB c40, v3, v3; \
VPADDQ m2, v0, v0; \
VPADDQ v2, v0, v0; \
VPADDQ m3, v1, v1; \
VPADDQ v3, v1, v1; \
VPXOR v0, v6, v6; \
VPXOR v1, v7, v7; \
VPSHUFB c48, v6, v6; \
VPSHUFB c48, v7, v7; \
VPADDQ v6, v4, v4; \
VPADDQ v7, v5, v5; \
VPXOR v4, v2, v2; \
VPXOR v5, v3, v3; \
VPADDQ v2, v2, t0; \
VPSRLQ $63, v2, v2; \
VPXOR t0, v2, v2; \
VPADDQ v3, v3, t0; \
VPSRLQ $63, v3, v3; \
VPXOR t0, v3, v3
// load msg: X12 = (i0, i1), X13 = (i2, i3), X14 = (i4, i5), X15 = (i6, i7)
// i0, i1, i2, i3, i4, i5, i6, i7 must not be 0
#define LOAD_MSG_AVX(i0, i1, i2, i3, i4, i5, i6, i7) \
VMOVQ_SI_X12(i0*8); \
VMOVQ_SI_X13(i2*8); \
VMOVQ_SI_X14(i4*8); \
VMOVQ_SI_X15(i6*8); \
VPINSRQ_1_SI_X12(i1*8); \
VPINSRQ_1_SI_X13(i3*8); \
VPINSRQ_1_SI_X14(i5*8); \
VPINSRQ_1_SI_X15(i7*8)
// load msg: X12 = (0, 2), X13 = (4, 6), X14 = (1, 3), X15 = (5, 7)
#define LOAD_MSG_AVX_0_2_4_6_1_3_5_7() \
VMOVQ_SI_X12_0; \
VMOVQ_SI_X13(4*8); \
VMOVQ_SI_X14(1*8); \
VMOVQ_SI_X15(5*8); \
VPINSRQ_1_SI_X12(2*8); \
VPINSRQ_1_SI_X13(6*8); \
VPINSRQ_1_SI_X14(3*8); \
VPINSRQ_1_SI_X15(7*8)
// load msg: X12 = (1, 0), X13 = (11, 5), X14 = (12, 2), X15 = (7, 3)
#define LOAD_MSG_AVX_1_0_11_5_12_2_7_3() \
VPSHUFD $0x4E, 0*8(SI), X12; \
VMOVQ_SI_X13(11*8); \
VMOVQ_SI_X14(12*8); \
VMOVQ_SI_X15(7*8); \
VPINSRQ_1_SI_X13(5*8); \
VPINSRQ_1_SI_X14(2*8); \
VPINSRQ_1_SI_X15(3*8)
// load msg: X12 = (11, 12), X13 = (5, 15), X14 = (8, 0), X15 = (2, 13)
#define LOAD_MSG_AVX_11_12_5_15_8_0_2_13() \
VMOVDQU 11*8(SI), X12; \
VMOVQ_SI_X13(5*8); \
VMOVQ_SI_X14(8*8); \
VMOVQ_SI_X15(2*8); \
VPINSRQ_1_SI_X13(15*8); \
VPINSRQ_1_SI_X14_0; \
VPINSRQ_1_SI_X15(13*8)
// load msg: X12 = (2, 5), X13 = (4, 15), X14 = (6, 10), X15 = (0, 8)
#define LOAD_MSG_AVX_2_5_4_15_6_10_0_8() \
VMOVQ_SI_X12(2*8); \
VMOVQ_SI_X13(4*8); \
VMOVQ_SI_X14(6*8); \
VMOVQ_SI_X15_0; \
VPINSRQ_1_SI_X12(5*8); \
VPINSRQ_1_SI_X13(15*8); \
VPINSRQ_1_SI_X14(10*8); \
VPINSRQ_1_SI_X15(8*8)
// load msg: X12 = (9, 5), X13 = (2, 10), X14 = (0, 7), X15 = (4, 15)
#define LOAD_MSG_AVX_9_5_2_10_0_7_4_15() \
VMOVQ_SI_X12(9*8); \
VMOVQ_SI_X13(2*8); \
VMOVQ_SI_X14_0; \
VMOVQ_SI_X15(4*8); \
VPINSRQ_1_SI_X12(5*8); \
VPINSRQ_1_SI_X13(10*8); \
VPINSRQ_1_SI_X14(7*8); \
VPINSRQ_1_SI_X15(15*8)
// load msg: X12 = (2, 6), X13 = (0, 8), X14 = (12, 10), X15 = (11, 3)
#define LOAD_MSG_AVX_2_6_0_8_12_10_11_3() \
VMOVQ_SI_X12(2*8); \
VMOVQ_SI_X13_0; \
VMOVQ_SI_X14(12*8); \
VMOVQ_SI_X15(11*8); \
VPINSRQ_1_SI_X12(6*8); \
VPINSRQ_1_SI_X13(8*8); \
VPINSRQ_1_SI_X14(10*8); \
VPINSRQ_1_SI_X15(3*8)
// load msg: X12 = (0, 6), X13 = (9, 8), X14 = (7, 3), X15 = (2, 11)
#define LOAD_MSG_AVX_0_6_9_8_7_3_2_11() \
MOVQ 0*8(SI), X12; \
VPSHUFD $0x4E, 8*8(SI), X13; \
MOVQ 7*8(SI), X14; \
MOVQ 2*8(SI), X15; \
VPINSRQ_1_SI_X12(6*8); \
VPINSRQ_1_SI_X14(3*8); \
VPINSRQ_1_SI_X15(11*8)
// load msg: X12 = (6, 14), X13 = (11, 0), X14 = (15, 9), X15 = (3, 8)
#define LOAD_MSG_AVX_6_14_11_0_15_9_3_8() \
MOVQ 6*8(SI), X12; \
MOVQ 11*8(SI), X13; \
MOVQ 15*8(SI), X14; \
MOVQ 3*8(SI), X15; \
VPINSRQ_1_SI_X12(14*8); \
VPINSRQ_1_SI_X13_0; \
VPINSRQ_1_SI_X14(9*8); \
VPINSRQ_1_SI_X15(8*8)
// load msg: X12 = (5, 15), X13 = (8, 2), X14 = (0, 4), X15 = (6, 10)
#define LOAD_MSG_AVX_5_15_8_2_0_4_6_10() \
MOVQ 5*8(SI), X12; \
MOVQ 8*8(SI), X13; \
MOVQ 0*8(SI), X14; \
MOVQ 6*8(SI), X15; \
VPINSRQ_1_SI_X12(15*8); \
VPINSRQ_1_SI_X13(2*8); \
VPINSRQ_1_SI_X14(4*8); \
VPINSRQ_1_SI_X15(10*8)
// load msg: X12 = (12, 13), X13 = (1, 10), X14 = (2, 7), X15 = (4, 5)
#define LOAD_MSG_AVX_12_13_1_10_2_7_4_5() \
VMOVDQU 12*8(SI), X12; \
MOVQ 1*8(SI), X13; \
MOVQ 2*8(SI), X14; \
VPINSRQ_1_SI_X13(10*8); \
VPINSRQ_1_SI_X14(7*8); \
VMOVDQU 4*8(SI), X15
// load msg: X12 = (15, 9), X13 = (3, 13), X14 = (11, 14), X15 = (12, 0)
#define LOAD_MSG_AVX_15_9_3_13_11_14_12_0() \
MOVQ 15*8(SI), X12; \
MOVQ 3*8(SI), X13; \
MOVQ 11*8(SI), X14; \
MOVQ 12*8(SI), X15; \
VPINSRQ_1_SI_X12(9*8); \
VPINSRQ_1_SI_X13(13*8); \
VPINSRQ_1_SI_X14(14*8); \
VPINSRQ_1_SI_X15_0
// func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
TEXT ·hashBlocksAVX(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
MOVQ h+0(FP), AX
MOVQ c+8(FP), BX
MOVQ flag+16(FP), CX
MOVQ blocks_base+24(FP), SI
MOVQ blocks_len+32(FP), DI
MOVQ SP, R10
ADDQ $15, R10
ANDQ $~15, R10
VMOVDQU ·AVX_c40<>(SB), X0
VMOVDQU ·AVX_c48<>(SB), X1
VMOVDQA X0, X8
VMOVDQA X1, X9
VMOVDQU ·AVX_iv3<>(SB), X0
VMOVDQA X0, 0(R10)
XORQ CX, 0(R10) // 0(R10) = ·AVX_iv3 ^ (CX || 0)
VMOVDQU 0(AX), X10
VMOVDQU 16(AX), X11
VMOVDQU 32(AX), X2
VMOVDQU 48(AX), X3
MOVQ 0(BX), R8
MOVQ 8(BX), R9
loop:
ADDQ $128, R8
CMPQ R8, $128
JGE noinc
INCQ R9
noinc:
VMOVQ_R8_X15
VPINSRQ_1_R9_X15
VMOVDQA X10, X0
VMOVDQA X11, X1
VMOVDQU ·AVX_iv0<>(SB), X4
VMOVDQU ·AVX_iv1<>(SB), X5
VMOVDQU ·AVX_iv2<>(SB), X6
VPXOR X15, X6, X6
VMOVDQA 0(R10), X7
LOAD_MSG_AVX_0_2_4_6_1_3_5_7()
VMOVDQA X12, 16(R10)
VMOVDQA X13, 32(R10)
VMOVDQA X14, 48(R10)
VMOVDQA X15, 64(R10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(8, 10, 12, 14, 9, 11, 13, 15)
VMOVDQA X12, 80(R10)
VMOVDQA X13, 96(R10)
VMOVDQA X14, 112(R10)
VMOVDQA X15, 128(R10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(14, 4, 9, 13, 10, 8, 15, 6)
VMOVDQA X12, 144(R10)
VMOVDQA X13, 160(R10)
VMOVDQA X14, 176(R10)
VMOVDQA X15, 192(R10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX_1_0_11_5_12_2_7_3()
VMOVDQA X12, 208(R10)
VMOVDQA X13, 224(R10)
VMOVDQA X14, 240(R10)
VMOVDQA X15, 256(R10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX_11_12_5_15_8_0_2_13()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(10, 3, 7, 9, 14, 6, 1, 4)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(7, 3, 13, 11, 9, 1, 12, 14)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX_2_5_4_15_6_10_0_8()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX_9_5_2_10_0_7_4_15()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(14, 11, 6, 3, 1, 12, 8, 13)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX_2_6_0_8_12_10_11_3()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX(4, 7, 15, 1, 13, 5, 14, 9)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(12, 1, 14, 4, 5, 15, 13, 10)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX_0_6_9_8_7_3_2_11()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(13, 7, 12, 3, 11, 14, 1, 9)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX_5_15_8_2_0_4_6_10()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX_6_14_11_0_15_9_3_8()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX_12_13_1_10_2_7_4_5()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
LOAD_MSG_AVX(10, 8, 7, 1, 2, 4, 6, 5)
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX()
LOAD_MSG_AVX_15_9_3_13_11_14_12_0()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, X12, X13, X14, X15, X15, X8, X9)
SHUFFLE_AVX_INV()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X15, X8, X9)
SHUFFLE_AVX()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X15, X8, X9)
SHUFFLE_AVX_INV()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X15, X8, X9)
SHUFFLE_AVX()
HALF_ROUND_AVX(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X15, X8, X9)
SHUFFLE_AVX_INV()
VMOVDQU 32(AX), X14
VMOVDQU 48(AX), X15
VPXOR X0, X10, X10
VPXOR X1, X11, X11
VPXOR X2, X14, X14
VPXOR X3, X15, X15
VPXOR X4, X10, X10
VPXOR X5, X11, X11
VPXOR X6, X14, X2
VPXOR X7, X15, X3
VMOVDQU X2, 32(AX)
VMOVDQU X3, 48(AX)
LEAQ 128(SI), SI
SUBQ $128, DI
JNE loop
VMOVDQU X10, 0(AX)
VMOVDQU X11, 16(AX)
MOVQ R8, 0(BX)
MOVQ R9, 8(BX)
VZEROUPPER
RET

278
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s generated vendored Normal file
View File

@ -0,0 +1,278 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build amd64 && gc && !purego
#include "textflag.h"
DATA ·iv0<>+0x00(SB)/8, $0x6a09e667f3bcc908
DATA ·iv0<>+0x08(SB)/8, $0xbb67ae8584caa73b
GLOBL ·iv0<>(SB), (NOPTR+RODATA), $16
DATA ·iv1<>+0x00(SB)/8, $0x3c6ef372fe94f82b
DATA ·iv1<>+0x08(SB)/8, $0xa54ff53a5f1d36f1
GLOBL ·iv1<>(SB), (NOPTR+RODATA), $16
DATA ·iv2<>+0x00(SB)/8, $0x510e527fade682d1
DATA ·iv2<>+0x08(SB)/8, $0x9b05688c2b3e6c1f
GLOBL ·iv2<>(SB), (NOPTR+RODATA), $16
DATA ·iv3<>+0x00(SB)/8, $0x1f83d9abfb41bd6b
DATA ·iv3<>+0x08(SB)/8, $0x5be0cd19137e2179
GLOBL ·iv3<>(SB), (NOPTR+RODATA), $16
DATA ·c40<>+0x00(SB)/8, $0x0201000706050403
DATA ·c40<>+0x08(SB)/8, $0x0a09080f0e0d0c0b
GLOBL ·c40<>(SB), (NOPTR+RODATA), $16
DATA ·c48<>+0x00(SB)/8, $0x0100070605040302
DATA ·c48<>+0x08(SB)/8, $0x09080f0e0d0c0b0a
GLOBL ·c48<>(SB), (NOPTR+RODATA), $16
#define SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2) \
MOVO v4, t1; \
MOVO v5, v4; \
MOVO t1, v5; \
MOVO v6, t1; \
PUNPCKLQDQ v6, t2; \
PUNPCKHQDQ v7, v6; \
PUNPCKHQDQ t2, v6; \
PUNPCKLQDQ v7, t2; \
MOVO t1, v7; \
MOVO v2, t1; \
PUNPCKHQDQ t2, v7; \
PUNPCKLQDQ v3, t2; \
PUNPCKHQDQ t2, v2; \
PUNPCKLQDQ t1, t2; \
PUNPCKHQDQ t2, v3
#define SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2) \
MOVO v4, t1; \
MOVO v5, v4; \
MOVO t1, v5; \
MOVO v2, t1; \
PUNPCKLQDQ v2, t2; \
PUNPCKHQDQ v3, v2; \
PUNPCKHQDQ t2, v2; \
PUNPCKLQDQ v3, t2; \
MOVO t1, v3; \
MOVO v6, t1; \
PUNPCKHQDQ t2, v3; \
PUNPCKLQDQ v7, t2; \
PUNPCKHQDQ t2, v6; \
PUNPCKLQDQ t1, t2; \
PUNPCKHQDQ t2, v7
#define HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, m0, m1, m2, m3, t0, c40, c48) \
PADDQ m0, v0; \
PADDQ m1, v1; \
PADDQ v2, v0; \
PADDQ v3, v1; \
PXOR v0, v6; \
PXOR v1, v7; \
PSHUFD $0xB1, v6, v6; \
PSHUFD $0xB1, v7, v7; \
PADDQ v6, v4; \
PADDQ v7, v5; \
PXOR v4, v2; \
PXOR v5, v3; \
PSHUFB c40, v2; \
PSHUFB c40, v3; \
PADDQ m2, v0; \
PADDQ m3, v1; \
PADDQ v2, v0; \
PADDQ v3, v1; \
PXOR v0, v6; \
PXOR v1, v7; \
PSHUFB c48, v6; \
PSHUFB c48, v7; \
PADDQ v6, v4; \
PADDQ v7, v5; \
PXOR v4, v2; \
PXOR v5, v3; \
MOVOU v2, t0; \
PADDQ v2, t0; \
PSRLQ $63, v2; \
PXOR t0, v2; \
MOVOU v3, t0; \
PADDQ v3, t0; \
PSRLQ $63, v3; \
PXOR t0, v3
#define LOAD_MSG(m0, m1, m2, m3, src, i0, i1, i2, i3, i4, i5, i6, i7) \
MOVQ i0*8(src), m0; \
PINSRQ $1, i1*8(src), m0; \
MOVQ i2*8(src), m1; \
PINSRQ $1, i3*8(src), m1; \
MOVQ i4*8(src), m2; \
PINSRQ $1, i5*8(src), m2; \
MOVQ i6*8(src), m3; \
PINSRQ $1, i7*8(src), m3
// func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
TEXT ·hashBlocksSSE4(SB), 4, $288-48 // frame size = 272 + 16 byte alignment
MOVQ h+0(FP), AX
MOVQ c+8(FP), BX
MOVQ flag+16(FP), CX
MOVQ blocks_base+24(FP), SI
MOVQ blocks_len+32(FP), DI
MOVQ SP, R10
ADDQ $15, R10
ANDQ $~15, R10
MOVOU ·iv3<>(SB), X0
MOVO X0, 0(R10)
XORQ CX, 0(R10) // 0(R10) = ·iv3 ^ (CX || 0)
MOVOU ·c40<>(SB), X13
MOVOU ·c48<>(SB), X14
MOVOU 0(AX), X12
MOVOU 16(AX), X15
MOVQ 0(BX), R8
MOVQ 8(BX), R9
loop:
ADDQ $128, R8
CMPQ R8, $128
JGE noinc
INCQ R9
noinc:
MOVQ R8, X8
PINSRQ $1, R9, X8
MOVO X12, X0
MOVO X15, X1
MOVOU 32(AX), X2
MOVOU 48(AX), X3
MOVOU ·iv0<>(SB), X4
MOVOU ·iv1<>(SB), X5
MOVOU ·iv2<>(SB), X6
PXOR X8, X6
MOVO 0(R10), X7
LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7)
MOVO X8, 16(R10)
MOVO X9, 32(R10)
MOVO X10, 48(R10)
MOVO X11, 64(R10)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 8, 10, 12, 14, 9, 11, 13, 15)
MOVO X8, 80(R10)
MOVO X9, 96(R10)
MOVO X10, 112(R10)
MOVO X11, 128(R10)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 14, 4, 9, 13, 10, 8, 15, 6)
MOVO X8, 144(R10)
MOVO X9, 160(R10)
MOVO X10, 176(R10)
MOVO X11, 192(R10)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 1, 0, 11, 5, 12, 2, 7, 3)
MOVO X8, 208(R10)
MOVO X9, 224(R10)
MOVO X10, 240(R10)
MOVO X11, 256(R10)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 11, 12, 5, 15, 8, 0, 2, 13)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 10, 3, 7, 9, 14, 6, 1, 4)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 7, 3, 13, 11, 9, 1, 12, 14)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 2, 5, 4, 15, 6, 10, 0, 8)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 9, 5, 2, 10, 0, 7, 4, 15)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 14, 11, 6, 3, 1, 12, 8, 13)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 2, 6, 0, 8, 12, 10, 11, 3)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 4, 7, 15, 1, 13, 5, 14, 9)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 12, 1, 14, 4, 5, 15, 13, 10)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 0, 6, 9, 8, 7, 3, 2, 11)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 13, 7, 12, 3, 11, 14, 1, 9)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 5, 15, 8, 2, 0, 4, 6, 10)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 6, 14, 11, 0, 15, 9, 3, 8)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 12, 13, 1, 10, 2, 7, 4, 5)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 10, 8, 7, 1, 2, 4, 6, 5)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
LOAD_MSG(X8, X9, X10, X11, SI, 15, 9, 3, 13, 11, 14, 12, 0)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 16(R10), 32(R10), 48(R10), 64(R10), X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 80(R10), 96(R10), 112(R10), 128(R10), X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 144(R10), 160(R10), 176(R10), 192(R10), X11, X13, X14)
SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9)
HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, 208(R10), 224(R10), 240(R10), 256(R10), X11, X13, X14)
SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9)
MOVOU 32(AX), X10
MOVOU 48(AX), X11
PXOR X0, X12
PXOR X1, X15
PXOR X2, X10
PXOR X3, X11
PXOR X4, X12
PXOR X5, X15
PXOR X6, X10
PXOR X7, X11
MOVOU X10, 32(AX)
MOVOU X11, 48(AX)
LEAQ 128(SI), SI
SUBQ $128, DI
JNE loop
MOVOU X12, 0(AX)
MOVOU X15, 16(AX)
MOVQ R8, 0(BX)
MOVQ R9, 8(BX)
RET

182
vendor/golang.org/x/crypto/blake2b/blake2b_generic.go generated vendored Normal file
View File

@ -0,0 +1,182 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package blake2b
import (
"encoding/binary"
"math/bits"
)
// the precomputed values for BLAKE2b
// there are 12 16-byte arrays - one for each round
// the entries are calculated from the sigma constants.
var precomputed = [12][16]byte{
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
{11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
{7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
{9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
{2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
{12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
{13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
{6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
{10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second
}
func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
var m [16]uint64
c0, c1 := c[0], c[1]
for i := 0; i < len(blocks); {
c0 += BlockSize
if c0 < BlockSize {
c1++
}
v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]
v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]
v12 ^= c0
v13 ^= c1
v14 ^= flag
for j := range m {
m[j] = binary.LittleEndian.Uint64(blocks[i:])
i += 8
}
for j := range precomputed {
s := &(precomputed[j])
v0 += m[s[0]]
v0 += v4
v12 ^= v0
v12 = bits.RotateLeft64(v12, -32)
v8 += v12
v4 ^= v8
v4 = bits.RotateLeft64(v4, -24)
v1 += m[s[1]]
v1 += v5
v13 ^= v1
v13 = bits.RotateLeft64(v13, -32)
v9 += v13
v5 ^= v9
v5 = bits.RotateLeft64(v5, -24)
v2 += m[s[2]]
v2 += v6
v14 ^= v2
v14 = bits.RotateLeft64(v14, -32)
v10 += v14
v6 ^= v10
v6 = bits.RotateLeft64(v6, -24)
v3 += m[s[3]]
v3 += v7
v15 ^= v3
v15 = bits.RotateLeft64(v15, -32)
v11 += v15
v7 ^= v11
v7 = bits.RotateLeft64(v7, -24)
v0 += m[s[4]]
v0 += v4
v12 ^= v0
v12 = bits.RotateLeft64(v12, -16)
v8 += v12
v4 ^= v8
v4 = bits.RotateLeft64(v4, -63)
v1 += m[s[5]]
v1 += v5
v13 ^= v1
v13 = bits.RotateLeft64(v13, -16)
v9 += v13
v5 ^= v9
v5 = bits.RotateLeft64(v5, -63)
v2 += m[s[6]]
v2 += v6
v14 ^= v2
v14 = bits.RotateLeft64(v14, -16)
v10 += v14
v6 ^= v10
v6 = bits.RotateLeft64(v6, -63)
v3 += m[s[7]]
v3 += v7
v15 ^= v3
v15 = bits.RotateLeft64(v15, -16)
v11 += v15
v7 ^= v11
v7 = bits.RotateLeft64(v7, -63)
v0 += m[s[8]]
v0 += v5
v15 ^= v0
v15 = bits.RotateLeft64(v15, -32)
v10 += v15
v5 ^= v10
v5 = bits.RotateLeft64(v5, -24)
v1 += m[s[9]]
v1 += v6
v12 ^= v1
v12 = bits.RotateLeft64(v12, -32)
v11 += v12
v6 ^= v11
v6 = bits.RotateLeft64(v6, -24)
v2 += m[s[10]]
v2 += v7
v13 ^= v2
v13 = bits.RotateLeft64(v13, -32)
v8 += v13
v7 ^= v8
v7 = bits.RotateLeft64(v7, -24)
v3 += m[s[11]]
v3 += v4
v14 ^= v3
v14 = bits.RotateLeft64(v14, -32)
v9 += v14
v4 ^= v9
v4 = bits.RotateLeft64(v4, -24)
v0 += m[s[12]]
v0 += v5
v15 ^= v0
v15 = bits.RotateLeft64(v15, -16)
v10 += v15
v5 ^= v10
v5 = bits.RotateLeft64(v5, -63)
v1 += m[s[13]]
v1 += v6
v12 ^= v1
v12 = bits.RotateLeft64(v12, -16)
v11 += v12
v6 ^= v11
v6 = bits.RotateLeft64(v6, -63)
v2 += m[s[14]]
v2 += v7
v13 ^= v2
v13 = bits.RotateLeft64(v13, -16)
v8 += v13
v7 ^= v8
v7 = bits.RotateLeft64(v7, -63)
v3 += m[s[15]]
v3 += v4
v14 ^= v3
v14 = bits.RotateLeft64(v14, -16)
v9 += v14
v4 ^= v9
v4 = bits.RotateLeft64(v4, -63)
}
h[0] ^= v0 ^ v8
h[1] ^= v1 ^ v9
h[2] ^= v2 ^ v10
h[3] ^= v3 ^ v11
h[4] ^= v4 ^ v12
h[5] ^= v5 ^ v13
h[6] ^= v6 ^ v14
h[7] ^= v7 ^ v15
}
c[0], c[1] = c0, c1
}

11
vendor/golang.org/x/crypto/blake2b/blake2b_ref.go generated vendored Normal file
View File

@ -0,0 +1,11 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !amd64 || purego || !gc
package blake2b
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
hashBlocksGeneric(h, c, flag, blocks)
}

177
vendor/golang.org/x/crypto/blake2b/blake2x.go generated vendored Normal file
View File

@ -0,0 +1,177 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package blake2b
import (
"encoding/binary"
"errors"
"io"
)
// XOF defines the interface to hash functions that
// support arbitrary-length output.
type XOF interface {
// Write absorbs more data into the hash's state. It panics if called
// after Read.
io.Writer
// Read reads more output from the hash. It returns io.EOF if the limit
// has been reached.
io.Reader
// Clone returns a copy of the XOF in its current state.
Clone() XOF
// Reset resets the XOF to its initial state.
Reset()
}
// OutputLengthUnknown can be used as the size argument to NewXOF to indicate
// the length of the output is not known in advance.
const OutputLengthUnknown = 0
// magicUnknownOutputLength is a magic value for the output size that indicates
// an unknown number of output bytes.
const magicUnknownOutputLength = (1 << 32) - 1
// maxOutputLength is the absolute maximum number of bytes to produce when the
// number of output bytes is unknown.
const maxOutputLength = (1 << 32) * 64
// NewXOF creates a new variable-output-length hash. The hash either produce a
// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes
// (size == OutputLengthUnknown). In the latter case, an absolute limit of
// 256GiB applies.
//
// A non-nil key turns the hash into a MAC. The key must between
// zero and 32 bytes long.
func NewXOF(size uint32, key []byte) (XOF, error) {
if len(key) > Size {
return nil, errKeySize
}
if size == magicUnknownOutputLength {
// 2^32-1 indicates an unknown number of bytes and thus isn't a
// valid length.
return nil, errors.New("blake2b: XOF length too large")
}
if size == OutputLengthUnknown {
size = magicUnknownOutputLength
}
x := &xof{
d: digest{
size: Size,
keyLen: len(key),
},
length: size,
}
copy(x.d.key[:], key)
x.Reset()
return x, nil
}
type xof struct {
d digest
length uint32
remaining uint64
cfg, root, block [Size]byte
offset int
nodeOffset uint32
readMode bool
}
func (x *xof) Write(p []byte) (n int, err error) {
if x.readMode {
panic("blake2b: write to XOF after read")
}
return x.d.Write(p)
}
func (x *xof) Clone() XOF {
clone := *x
return &clone
}
func (x *xof) Reset() {
x.cfg[0] = byte(Size)
binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length
binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length
x.cfg[17] = byte(Size) // inner hash size
x.d.Reset()
x.d.h[1] ^= uint64(x.length) << 32
x.remaining = uint64(x.length)
if x.remaining == magicUnknownOutputLength {
x.remaining = maxOutputLength
}
x.offset, x.nodeOffset = 0, 0
x.readMode = false
}
func (x *xof) Read(p []byte) (n int, err error) {
if !x.readMode {
x.d.finalize(&x.root)
x.readMode = true
}
if x.remaining == 0 {
return 0, io.EOF
}
n = len(p)
if uint64(n) > x.remaining {
n = int(x.remaining)
p = p[:n]
}
if x.offset > 0 {
blockRemaining := Size - x.offset
if n < blockRemaining {
x.offset += copy(p, x.block[x.offset:])
x.remaining -= uint64(n)
return
}
copy(p, x.block[x.offset:])
p = p[blockRemaining:]
x.offset = 0
x.remaining -= uint64(blockRemaining)
}
for len(p) >= Size {
binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
x.nodeOffset++
x.d.initConfig(&x.cfg)
x.d.Write(x.root[:])
x.d.finalize(&x.block)
copy(p, x.block[:])
p = p[Size:]
x.remaining -= uint64(Size)
}
if todo := len(p); todo > 0 {
if x.remaining < uint64(Size) {
x.cfg[0] = byte(x.remaining)
}
binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
x.nodeOffset++
x.d.initConfig(&x.cfg)
x.d.Write(x.root[:])
x.d.finalize(&x.block)
x.offset = copy(p, x.block[:todo])
x.remaining -= uint64(todo)
}
return
}
func (d *digest) initConfig(cfg *[Size]byte) {
d.offset, d.c[0], d.c[1] = 0, 0, 0
for i := range d.h {
d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:])
}
}

Some files were not shown because too many files have changed in this diff Show More