add vendor
This commit is contained in:
parent
f96ba5f172
commit
00ebcd295e
202
vendor/cloud.google.com/go/LICENSE
generated
vendored
Normal file
202
vendor/cloud.google.com/go/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
526
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
Normal file
526
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
// Copyright 2014 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package metadata provides access to Google Compute Engine (GCE)
|
||||||
|
// metadata and API service accounts.
|
||||||
|
//
|
||||||
|
// This package is a wrapper around the GCE metadata service,
|
||||||
|
// as documented at https://developers.google.com/compute/docs/metadata.
|
||||||
|
package metadata // import "cloud.google.com/go/compute/metadata"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// metadataIP is the documented metadata server IP address.
|
||||||
|
metadataIP = "169.254.169.254"
|
||||||
|
|
||||||
|
// metadataHostEnv is the environment variable specifying the
|
||||||
|
// GCE metadata hostname. If empty, the default value of
|
||||||
|
// metadataIP ("169.254.169.254") is used instead.
|
||||||
|
// This is variable name is not defined by any spec, as far as
|
||||||
|
// I know; it was made up for the Go package.
|
||||||
|
metadataHostEnv = "GCE_METADATA_HOST"
|
||||||
|
|
||||||
|
userAgent = "gcloud-golang/0.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cachedValue struct {
|
||||||
|
k string
|
||||||
|
trim bool
|
||||||
|
mu sync.Mutex
|
||||||
|
v string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
projID = &cachedValue{k: "project/project-id", trim: true}
|
||||||
|
projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
|
||||||
|
instID = &cachedValue{k: "instance/id", trim: true}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultClient = &Client{hc: &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Dial: (&net.Dialer{
|
||||||
|
Timeout: 2 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}).Dial,
|
||||||
|
ResponseHeaderTimeout: 2 * time.Second,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
subscribeClient = &Client{hc: &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Dial: (&net.Dialer{
|
||||||
|
Timeout: 2 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
}).Dial,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotDefinedError is returned when requested metadata is not defined.
|
||||||
|
//
|
||||||
|
// The underlying string is the suffix after "/computeMetadata/v1/".
|
||||||
|
//
|
||||||
|
// This error is not returned if the value is defined to be the empty
|
||||||
|
// string.
|
||||||
|
type NotDefinedError string
|
||||||
|
|
||||||
|
func (suffix NotDefinedError) Error() string {
|
||||||
|
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedValue) get(cl *Client) (v string, err error) {
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
c.mu.Lock()
|
||||||
|
if c.v != "" {
|
||||||
|
return c.v, nil
|
||||||
|
}
|
||||||
|
if c.trim {
|
||||||
|
v, err = cl.getTrimmed(c.k)
|
||||||
|
} else {
|
||||||
|
v, err = cl.Get(c.k)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
c.v = v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
onGCEOnce sync.Once
|
||||||
|
onGCE bool
|
||||||
|
)
|
||||||
|
|
||||||
|
// OnGCE reports whether this process is running on Google Compute Engine.
|
||||||
|
func OnGCE() bool {
|
||||||
|
onGCEOnce.Do(initOnGCE)
|
||||||
|
return onGCE
|
||||||
|
}
|
||||||
|
|
||||||
|
func initOnGCE() {
|
||||||
|
onGCE = testOnGCE()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testOnGCE() bool {
|
||||||
|
// The user explicitly said they're on GCE, so trust them.
|
||||||
|
if os.Getenv(metadataHostEnv) != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resc := make(chan bool, 2)
|
||||||
|
|
||||||
|
// Try two strategies in parallel.
|
||||||
|
// See https://github.com/googleapis/google-cloud-go/issues/194
|
||||||
|
go func() {
|
||||||
|
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
res, err := defaultClient.hc.Do(req.WithContext(ctx))
|
||||||
|
if err != nil {
|
||||||
|
resc <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
resc <- res.Header.Get("Metadata-Flavor") == "Google"
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
addrs, err := net.LookupHost("metadata.google.internal")
|
||||||
|
if err != nil || len(addrs) == 0 {
|
||||||
|
resc <- false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resc <- strsContains(addrs, metadataIP)
|
||||||
|
}()
|
||||||
|
|
||||||
|
tryHarder := systemInfoSuggestsGCE()
|
||||||
|
if tryHarder {
|
||||||
|
res := <-resc
|
||||||
|
if res {
|
||||||
|
// The first strategy succeeded, so let's use it.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Wait for either the DNS or metadata server probe to
|
||||||
|
// contradict the other one and say we are running on
|
||||||
|
// GCE. Give it a lot of time to do so, since the system
|
||||||
|
// info already suggests we're running on a GCE BIOS.
|
||||||
|
timer := time.NewTimer(5 * time.Second)
|
||||||
|
defer timer.Stop()
|
||||||
|
select {
|
||||||
|
case res = <-resc:
|
||||||
|
return res
|
||||||
|
case <-timer.C:
|
||||||
|
// Too slow. Who knows what this system is.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's no hint from the system info that we're running on
|
||||||
|
// GCE, so use the first probe's result as truth, whether it's
|
||||||
|
// true or false. The goal here is to optimize for speed for
|
||||||
|
// users who are NOT running on GCE. We can't assume that
|
||||||
|
// either a DNS lookup or an HTTP request to a blackholed IP
|
||||||
|
// address is fast. Worst case this should return when the
|
||||||
|
// metaClient's Transport.ResponseHeaderTimeout or
|
||||||
|
// Transport.Dial.Timeout fires (in two seconds).
|
||||||
|
return <-resc
|
||||||
|
}
|
||||||
|
|
||||||
|
// systemInfoSuggestsGCE reports whether the local system (without
|
||||||
|
// doing network requests) suggests that we're running on GCE. If this
|
||||||
|
// returns true, testOnGCE tries a bit harder to reach its metadata
|
||||||
|
// server.
|
||||||
|
func systemInfoSuggestsGCE() bool {
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
// We don't have any non-Linux clues available, at least yet.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
||||||
|
name := strings.TrimSpace(string(slurp))
|
||||||
|
return name == "Google" || name == "Google Compute Engine"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe calls Client.Subscribe on a client designed for subscribing (one with no
|
||||||
|
// ResponseHeaderTimeout).
|
||||||
|
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||||
|
return subscribeClient.Subscribe(suffix, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get calls Client.Get on the default client.
|
||||||
|
func Get(suffix string) (string, error) { return defaultClient.Get(suffix) }
|
||||||
|
|
||||||
|
// ProjectID returns the current instance's project ID string.
|
||||||
|
func ProjectID() (string, error) { return defaultClient.ProjectID() }
|
||||||
|
|
||||||
|
// NumericProjectID returns the current instance's numeric project ID.
|
||||||
|
func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
|
||||||
|
|
||||||
|
// InternalIP returns the instance's primary internal IP address.
|
||||||
|
func InternalIP() (string, error) { return defaultClient.InternalIP() }
|
||||||
|
|
||||||
|
// ExternalIP returns the instance's primary external (public) IP address.
|
||||||
|
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
|
||||||
|
|
||||||
|
// Email calls Client.Email on the default client.
|
||||||
|
func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) }
|
||||||
|
|
||||||
|
// Hostname returns the instance's hostname. This will be of the form
|
||||||
|
// "<instanceID>.c.<projID>.internal".
|
||||||
|
func Hostname() (string, error) { return defaultClient.Hostname() }
|
||||||
|
|
||||||
|
// InstanceTags returns the list of user-defined instance tags,
|
||||||
|
// assigned when initially creating a GCE instance.
|
||||||
|
func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
|
||||||
|
|
||||||
|
// InstanceID returns the current VM's numeric instance ID.
|
||||||
|
func InstanceID() (string, error) { return defaultClient.InstanceID() }
|
||||||
|
|
||||||
|
// InstanceName returns the current VM's instance ID string.
|
||||||
|
func InstanceName() (string, error) { return defaultClient.InstanceName() }
|
||||||
|
|
||||||
|
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||||
|
func Zone() (string, error) { return defaultClient.Zone() }
|
||||||
|
|
||||||
|
// InstanceAttributes calls Client.InstanceAttributes on the default client.
|
||||||
|
func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
|
||||||
|
|
||||||
|
// ProjectAttributes calls Client.ProjectAttributes on the default client.
|
||||||
|
func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
|
||||||
|
|
||||||
|
// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client.
|
||||||
|
func InstanceAttributeValue(attr string) (string, error) {
|
||||||
|
return defaultClient.InstanceAttributeValue(attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client.
|
||||||
|
func ProjectAttributeValue(attr string) (string, error) {
|
||||||
|
return defaultClient.ProjectAttributeValue(attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scopes calls Client.Scopes on the default client.
|
||||||
|
func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
|
||||||
|
|
||||||
|
func strsContains(ss []string, s string) bool {
|
||||||
|
for _, v := range ss {
|
||||||
|
if v == s {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Client provides metadata.
|
||||||
|
type Client struct {
|
||||||
|
hc *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns a Client that can be used to fetch metadata. All HTTP requests
|
||||||
|
// will use the given http.Client instead of the default client.
|
||||||
|
func NewClient(c *http.Client) *Client {
|
||||||
|
return &Client{hc: c}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getETag returns a value from the metadata service as well as the associated ETag.
|
||||||
|
// This func is otherwise equivalent to Get.
|
||||||
|
func (c *Client) getETag(suffix string) (value, etag string, err error) {
|
||||||
|
// Using a fixed IP makes it very difficult to spoof the metadata service in
|
||||||
|
// a container, which is an important use-case for local testing of cloud
|
||||||
|
// deployments. To enable spoofing of the metadata service, the environment
|
||||||
|
// variable GCE_METADATA_HOST is first inspected to decide where metadata
|
||||||
|
// requests shall go.
|
||||||
|
host := os.Getenv(metadataHostEnv)
|
||||||
|
if host == "" {
|
||||||
|
// Using 169.254.169.254 instead of "metadata" here because Go
|
||||||
|
// binaries built with the "netgo" tag and without cgo won't
|
||||||
|
// know the search suffix for "metadata" is
|
||||||
|
// ".google.internal", and this IP address is documented as
|
||||||
|
// being stable anyway.
|
||||||
|
host = metadataIP
|
||||||
|
}
|
||||||
|
u := "http://" + host + "/computeMetadata/v1/" + suffix
|
||||||
|
req, _ := http.NewRequest("GET", u, nil)
|
||||||
|
req.Header.Set("Metadata-Flavor", "Google")
|
||||||
|
req.Header.Set("User-Agent", userAgent)
|
||||||
|
res, err := c.hc.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode == http.StatusNotFound {
|
||||||
|
return "", "", NotDefinedError(suffix)
|
||||||
|
}
|
||||||
|
all, err := ioutil.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
if res.StatusCode != 200 {
|
||||||
|
return "", "", &Error{Code: res.StatusCode, Message: string(all)}
|
||||||
|
}
|
||||||
|
return string(all), res.Header.Get("Etag"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns a value from the metadata service.
|
||||||
|
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||||
|
//
|
||||||
|
// If the GCE_METADATA_HOST environment variable is not defined, a default of
|
||||||
|
// 169.254.169.254 will be used instead.
|
||||||
|
//
|
||||||
|
// If the requested metadata is not defined, the returned error will
|
||||||
|
// be of type NotDefinedError.
|
||||||
|
func (c *Client) Get(suffix string) (string, error) {
|
||||||
|
val, _, err := c.getETag(suffix)
|
||||||
|
return val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getTrimmed(suffix string) (s string, err error) {
|
||||||
|
s, err = c.Get(suffix)
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) lines(suffix string) ([]string, error) {
|
||||||
|
j, err := c.Get(suffix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s := strings.Split(strings.TrimSpace(j), "\n")
|
||||||
|
for i := range s {
|
||||||
|
s[i] = strings.TrimSpace(s[i])
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectID returns the current instance's project ID string.
|
||||||
|
func (c *Client) ProjectID() (string, error) { return projID.get(c) }
|
||||||
|
|
||||||
|
// NumericProjectID returns the current instance's numeric project ID.
|
||||||
|
func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
|
||||||
|
|
||||||
|
// InstanceID returns the current VM's numeric instance ID.
|
||||||
|
func (c *Client) InstanceID() (string, error) { return instID.get(c) }
|
||||||
|
|
||||||
|
// InternalIP returns the instance's primary internal IP address.
|
||||||
|
func (c *Client) InternalIP() (string, error) {
|
||||||
|
return c.getTrimmed("instance/network-interfaces/0/ip")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Email returns the email address associated with the service account.
|
||||||
|
// The account may be empty or the string "default" to use the instance's
|
||||||
|
// main account.
|
||||||
|
func (c *Client) Email(serviceAccount string) (string, error) {
|
||||||
|
if serviceAccount == "" {
|
||||||
|
serviceAccount = "default"
|
||||||
|
}
|
||||||
|
return c.getTrimmed("instance/service-accounts/" + serviceAccount + "/email")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalIP returns the instance's primary external (public) IP address.
|
||||||
|
func (c *Client) ExternalIP() (string, error) {
|
||||||
|
return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hostname returns the instance's hostname. This will be of the form
|
||||||
|
// "<instanceID>.c.<projID>.internal".
|
||||||
|
func (c *Client) Hostname() (string, error) {
|
||||||
|
return c.getTrimmed("instance/hostname")
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstanceTags returns the list of user-defined instance tags,
|
||||||
|
// assigned when initially creating a GCE instance.
|
||||||
|
func (c *Client) InstanceTags() ([]string, error) {
|
||||||
|
var s []string
|
||||||
|
j, err := c.Get("instance/tags")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstanceName returns the current VM's instance ID string.
|
||||||
|
func (c *Client) InstanceName() (string, error) {
|
||||||
|
host, err := c.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.Split(host, ".")[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||||
|
func (c *Client) Zone() (string, error) {
|
||||||
|
zone, err := c.getTrimmed("instance/zone")
|
||||||
|
// zone is of the form "projects/<projNum>/zones/<zoneName>".
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return zone[strings.LastIndex(zone, "/")+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstanceAttributes returns the list of user-defined attributes,
|
||||||
|
// assigned when initially creating a GCE VM instance. The value of an
|
||||||
|
// attribute can be obtained with InstanceAttributeValue.
|
||||||
|
func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
|
||||||
|
|
||||||
|
// ProjectAttributes returns the list of user-defined attributes
|
||||||
|
// applying to the project as a whole, not just this VM. The value of
|
||||||
|
// an attribute can be obtained with ProjectAttributeValue.
|
||||||
|
func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
|
||||||
|
|
||||||
|
// InstanceAttributeValue returns the value of the provided VM
|
||||||
|
// instance attribute.
|
||||||
|
//
|
||||||
|
// If the requested attribute is not defined, the returned error will
|
||||||
|
// be of type NotDefinedError.
|
||||||
|
//
|
||||||
|
// InstanceAttributeValue may return ("", nil) if the attribute was
|
||||||
|
// defined to be the empty string.
|
||||||
|
func (c *Client) InstanceAttributeValue(attr string) (string, error) {
|
||||||
|
return c.Get("instance/attributes/" + attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectAttributeValue returns the value of the provided
|
||||||
|
// project attribute.
|
||||||
|
//
|
||||||
|
// If the requested attribute is not defined, the returned error will
|
||||||
|
// be of type NotDefinedError.
|
||||||
|
//
|
||||||
|
// ProjectAttributeValue may return ("", nil) if the attribute was
|
||||||
|
// defined to be the empty string.
|
||||||
|
func (c *Client) ProjectAttributeValue(attr string) (string, error) {
|
||||||
|
return c.Get("project/attributes/" + attr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scopes returns the service account scopes for the given account.
|
||||||
|
// The account may be empty or the string "default" to use the instance's
|
||||||
|
// main account.
|
||||||
|
func (c *Client) Scopes(serviceAccount string) ([]string, error) {
|
||||||
|
if serviceAccount == "" {
|
||||||
|
serviceAccount = "default"
|
||||||
|
}
|
||||||
|
return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe subscribes to a value from the metadata service.
|
||||||
|
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||||
|
// The suffix may contain query parameters.
|
||||||
|
//
|
||||||
|
// Subscribe calls fn with the latest metadata value indicated by the provided
|
||||||
|
// suffix. If the metadata value is deleted, fn is called with the empty string
|
||||||
|
// and ok false. Subscribe blocks until fn returns a non-nil error or the value
|
||||||
|
// is deleted. Subscribe returns the error value returned from the last call to
|
||||||
|
// fn, which may be nil when ok == false.
|
||||||
|
func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||||
|
const failedSubscribeSleep = time.Second * 5
|
||||||
|
|
||||||
|
// First check to see if the metadata value exists at all.
|
||||||
|
val, lastETag, err := c.getETag(suffix)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := fn(val, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ok := true
|
||||||
|
if strings.ContainsRune(suffix, '?') {
|
||||||
|
suffix += "&wait_for_change=true&last_etag="
|
||||||
|
} else {
|
||||||
|
suffix += "?wait_for_change=true&last_etag="
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag))
|
||||||
|
if err != nil {
|
||||||
|
if _, deleted := err.(NotDefinedError); !deleted {
|
||||||
|
time.Sleep(failedSubscribeSleep)
|
||||||
|
continue // Retry on other errors.
|
||||||
|
}
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
lastETag = etag
|
||||||
|
|
||||||
|
if err := fn(val, ok); err != nil || !ok {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error contains an error response from the server.
|
||||||
|
type Error struct {
|
||||||
|
// Code is the HTTP response status code.
|
||||||
|
Code int
|
||||||
|
// Message is the server response message.
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Error() string {
|
||||||
|
return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message)
|
||||||
|
}
|
315
vendor/cloud.google.com/go/iam/iam.go
generated
vendored
Normal file
315
vendor/cloud.google.com/go/iam/iam.go
generated
vendored
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package iam supports the resource-specific operations of Google Cloud
|
||||||
|
// IAM (Identity and Access Management) for the Google Cloud Libraries.
|
||||||
|
// See https://cloud.google.com/iam for more about IAM.
|
||||||
|
//
|
||||||
|
// Users of the Google Cloud Libraries will typically not use this package
|
||||||
|
// directly. Instead they will begin with some resource that supports IAM, like
|
||||||
|
// a pubsub topic, and call its IAM method to get a Handle for that resource.
|
||||||
|
package iam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
gax "github.com/googleapis/gax-go/v2"
|
||||||
|
pb "google.golang.org/genproto/googleapis/iam/v1"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
)
|
||||||
|
|
||||||
|
// client abstracts the IAMPolicy API to allow multiple implementations.
|
||||||
|
type client interface {
|
||||||
|
Get(ctx context.Context, resource string) (*pb.Policy, error)
|
||||||
|
Set(ctx context.Context, resource string, p *pb.Policy) error
|
||||||
|
Test(ctx context.Context, resource string, perms []string) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// grpcClient implements client for the standard gRPC-based IAMPolicy service.
|
||||||
|
type grpcClient struct {
|
||||||
|
c pb.IAMPolicyClient
|
||||||
|
}
|
||||||
|
|
||||||
|
var withRetry = gax.WithRetry(func() gax.Retryer {
|
||||||
|
return gax.OnCodes([]codes.Code{
|
||||||
|
codes.DeadlineExceeded,
|
||||||
|
codes.Unavailable,
|
||||||
|
}, gax.Backoff{
|
||||||
|
Initial: 100 * time.Millisecond,
|
||||||
|
Max: 60 * time.Second,
|
||||||
|
Multiplier: 1.3,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, error) {
|
||||||
|
var proto *pb.Policy
|
||||||
|
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
|
||||||
|
ctx = insertMetadata(ctx, md)
|
||||||
|
|
||||||
|
err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
|
||||||
|
var err error
|
||||||
|
proto, err = g.c.GetIamPolicy(ctx, &pb.GetIamPolicyRequest{Resource: resource})
|
||||||
|
return err
|
||||||
|
}, withRetry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return proto, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) error {
|
||||||
|
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
|
||||||
|
ctx = insertMetadata(ctx, md)
|
||||||
|
|
||||||
|
return gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
|
||||||
|
_, err := g.c.SetIamPolicy(ctx, &pb.SetIamPolicyRequest{
|
||||||
|
Resource: resource,
|
||||||
|
Policy: p,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}, withRetry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *grpcClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
|
||||||
|
var res *pb.TestIamPermissionsResponse
|
||||||
|
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
|
||||||
|
ctx = insertMetadata(ctx, md)
|
||||||
|
|
||||||
|
err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
|
||||||
|
var err error
|
||||||
|
res, err = g.c.TestIamPermissions(ctx, &pb.TestIamPermissionsRequest{
|
||||||
|
Resource: resource,
|
||||||
|
Permissions: perms,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}, withRetry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Permissions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Handle provides IAM operations for a resource.
|
||||||
|
type Handle struct {
|
||||||
|
c client
|
||||||
|
resource string
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalNewHandle is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// InternalNewHandle returns a Handle for resource.
|
||||||
|
// The conn parameter refers to a server that must support the IAMPolicy service.
|
||||||
|
func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
|
||||||
|
return InternalNewHandleGRPCClient(pb.NewIAMPolicyClient(conn), resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalNewHandleGRPCClient is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// InternalNewHandleClient returns a Handle for resource using the given
|
||||||
|
// grpc service that implements IAM as a mixin
|
||||||
|
func InternalNewHandleGRPCClient(c pb.IAMPolicyClient, resource string) *Handle {
|
||||||
|
return InternalNewHandleClient(&grpcClient{c: c}, resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalNewHandleClient is for use by the Google Cloud Libraries only.
|
||||||
|
//
|
||||||
|
// InternalNewHandleClient returns a Handle for resource using the given
|
||||||
|
// client implementation.
|
||||||
|
func InternalNewHandleClient(c client, resource string) *Handle {
|
||||||
|
return &Handle{
|
||||||
|
c: c,
|
||||||
|
resource: resource,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Policy retrieves the IAM policy for the resource.
|
||||||
|
func (h *Handle) Policy(ctx context.Context) (*Policy, error) {
|
||||||
|
proto, err := h.c.Get(ctx, h.resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Policy{InternalProto: proto}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPolicy replaces the resource's current policy with the supplied Policy.
|
||||||
|
//
|
||||||
|
// If policy was created from a prior call to Get, then the modification will
|
||||||
|
// only succeed if the policy has not changed since the Get.
|
||||||
|
func (h *Handle) SetPolicy(ctx context.Context, policy *Policy) error {
|
||||||
|
return h.c.Set(ctx, h.resource, policy.InternalProto)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPermissions returns the subset of permissions that the caller has on the resource.
|
||||||
|
func (h *Handle) TestPermissions(ctx context.Context, permissions []string) ([]string, error) {
|
||||||
|
return h.c.Test(ctx, h.resource, permissions)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RoleName is a name representing a collection of permissions.
|
||||||
|
type RoleName string
|
||||||
|
|
||||||
|
// Common role names.
|
||||||
|
const (
|
||||||
|
Owner RoleName = "roles/owner"
|
||||||
|
Editor RoleName = "roles/editor"
|
||||||
|
Viewer RoleName = "roles/viewer"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AllUsers is a special member that denotes all users, even unauthenticated ones.
|
||||||
|
AllUsers = "allUsers"
|
||||||
|
|
||||||
|
// AllAuthenticatedUsers is a special member that denotes all authenticated users.
|
||||||
|
AllAuthenticatedUsers = "allAuthenticatedUsers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Policy is a list of Bindings representing roles
|
||||||
|
// granted to members.
|
||||||
|
//
|
||||||
|
// The zero Policy is a valid policy with no bindings.
|
||||||
|
type Policy struct {
|
||||||
|
// TODO(jba): when type aliases are available, put Policy into an internal package
|
||||||
|
// and provide an exported alias here.
|
||||||
|
|
||||||
|
// This field is exported for use by the Google Cloud Libraries only.
|
||||||
|
// It may become unexported in a future release.
|
||||||
|
InternalProto *pb.Policy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Members returns the list of members with the supplied role.
|
||||||
|
// The return value should not be modified. Use Add and Remove
|
||||||
|
// to modify the members of a role.
|
||||||
|
func (p *Policy) Members(r RoleName) []string {
|
||||||
|
b := p.binding(r)
|
||||||
|
if b == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return b.Members
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasRole reports whether member has role r.
|
||||||
|
func (p *Policy) HasRole(member string, r RoleName) bool {
|
||||||
|
return memberIndex(member, p.binding(r)) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds member member to role r if it is not already present.
|
||||||
|
// A new binding is created if there is no binding for the role.
|
||||||
|
func (p *Policy) Add(member string, r RoleName) {
|
||||||
|
b := p.binding(r)
|
||||||
|
if b == nil {
|
||||||
|
if p.InternalProto == nil {
|
||||||
|
p.InternalProto = &pb.Policy{}
|
||||||
|
}
|
||||||
|
p.InternalProto.Bindings = append(p.InternalProto.Bindings, &pb.Binding{
|
||||||
|
Role: string(r),
|
||||||
|
Members: []string{member},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if memberIndex(member, b) < 0 {
|
||||||
|
b.Members = append(b.Members, member)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes member from role r if it is present.
|
||||||
|
func (p *Policy) Remove(member string, r RoleName) {
|
||||||
|
bi := p.bindingIndex(r)
|
||||||
|
if bi < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bindings := p.InternalProto.Bindings
|
||||||
|
b := bindings[bi]
|
||||||
|
mi := memberIndex(member, b)
|
||||||
|
if mi < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Order doesn't matter for bindings or members, so to remove, move the last item
|
||||||
|
// into the removed spot and shrink the slice.
|
||||||
|
if len(b.Members) == 1 {
|
||||||
|
// Remove binding.
|
||||||
|
last := len(bindings) - 1
|
||||||
|
bindings[bi] = bindings[last]
|
||||||
|
bindings[last] = nil
|
||||||
|
p.InternalProto.Bindings = bindings[:last]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Remove member.
|
||||||
|
// TODO(jba): worry about multiple copies of m?
|
||||||
|
last := len(b.Members) - 1
|
||||||
|
b.Members[mi] = b.Members[last]
|
||||||
|
b.Members[last] = ""
|
||||||
|
b.Members = b.Members[:last]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roles returns the names of all the roles that appear in the Policy.
|
||||||
|
func (p *Policy) Roles() []RoleName {
|
||||||
|
if p.InternalProto == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var rns []RoleName
|
||||||
|
for _, b := range p.InternalProto.Bindings {
|
||||||
|
rns = append(rns, RoleName(b.Role))
|
||||||
|
}
|
||||||
|
return rns
|
||||||
|
}
|
||||||
|
|
||||||
|
// binding returns the Binding for the suppied role, or nil if there isn't one.
|
||||||
|
func (p *Policy) binding(r RoleName) *pb.Binding {
|
||||||
|
i := p.bindingIndex(r)
|
||||||
|
if i < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p.InternalProto.Bindings[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Policy) bindingIndex(r RoleName) int {
|
||||||
|
if p.InternalProto == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for i, b := range p.InternalProto.Bindings {
|
||||||
|
if b.Role == string(r) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// memberIndex returns the index of m in b's Members, or -1 if not found.
|
||||||
|
func memberIndex(m string, b *pb.Binding) int {
|
||||||
|
if b == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
for i, mm := range b.Members {
|
||||||
|
if mm == m {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// insertMetadata inserts metadata into the given context
|
||||||
|
func insertMetadata(ctx context.Context, mds ...metadata.MD) context.Context {
|
||||||
|
out, _ := metadata.FromOutgoingContext(ctx)
|
||||||
|
out = out.Copy()
|
||||||
|
for _, md := range mds {
|
||||||
|
for k, v := range md {
|
||||||
|
out[k] = append(out[k], v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return metadata.NewOutgoingContext(ctx, out)
|
||||||
|
}
|
54
vendor/cloud.google.com/go/internal/annotate.go
generated
vendored
Normal file
54
vendor/cloud.google.com/go/internal/annotate.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Annotate prepends msg to the error message in err, attempting
|
||||||
|
// to preserve other information in err, like an error code.
|
||||||
|
//
|
||||||
|
// Annotate panics if err is nil.
|
||||||
|
//
|
||||||
|
// Annotate knows about these error types:
|
||||||
|
// - "google.golang.org/grpc/status".Status
|
||||||
|
// - "google.golang.org/api/googleapi".Error
|
||||||
|
// If the error is not one of these types, Annotate behaves
|
||||||
|
// like
|
||||||
|
// fmt.Errorf("%s: %v", msg, err)
|
||||||
|
func Annotate(err error, msg string) error {
|
||||||
|
if err == nil {
|
||||||
|
panic("Annotate called with nil")
|
||||||
|
}
|
||||||
|
if s, ok := status.FromError(err); ok {
|
||||||
|
p := s.Proto()
|
||||||
|
p.Message = msg + ": " + p.Message
|
||||||
|
return status.ErrorProto(p)
|
||||||
|
}
|
||||||
|
if g, ok := err.(*googleapi.Error); ok {
|
||||||
|
g.Message = msg + ": " + g.Message
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s: %v", msg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef uses format and args to format a string, then calls Annotate.
|
||||||
|
func Annotatef(err error, format string, args ...interface{}) error {
|
||||||
|
return Annotate(err, fmt.Sprintf(format, args...))
|
||||||
|
}
|
108
vendor/cloud.google.com/go/internal/optional/optional.go
generated
vendored
Normal file
108
vendor/cloud.google.com/go/internal/optional/optional.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package optional provides versions of primitive types that can
|
||||||
|
// be nil. These are useful in methods that update some of an API object's
|
||||||
|
// fields.
|
||||||
|
package optional
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Bool is either a bool or nil.
|
||||||
|
Bool interface{}
|
||||||
|
|
||||||
|
// String is either a string or nil.
|
||||||
|
String interface{}
|
||||||
|
|
||||||
|
// Int is either an int or nil.
|
||||||
|
Int interface{}
|
||||||
|
|
||||||
|
// Uint is either a uint or nil.
|
||||||
|
Uint interface{}
|
||||||
|
|
||||||
|
// Float64 is either a float64 or nil.
|
||||||
|
Float64 interface{}
|
||||||
|
|
||||||
|
// Duration is either a time.Duration or nil.
|
||||||
|
Duration interface{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToBool returns its argument as a bool.
|
||||||
|
// It panics if its argument is nil or not a bool.
|
||||||
|
func ToBool(v Bool) bool {
|
||||||
|
x, ok := v.(bool)
|
||||||
|
if !ok {
|
||||||
|
doPanic("Bool", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString returns its argument as a string.
|
||||||
|
// It panics if its argument is nil or not a string.
|
||||||
|
func ToString(v String) string {
|
||||||
|
x, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
doPanic("String", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToInt returns its argument as an int.
|
||||||
|
// It panics if its argument is nil or not an int.
|
||||||
|
func ToInt(v Int) int {
|
||||||
|
x, ok := v.(int)
|
||||||
|
if !ok {
|
||||||
|
doPanic("Int", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToUint returns its argument as a uint.
|
||||||
|
// It panics if its argument is nil or not a uint.
|
||||||
|
func ToUint(v Uint) uint {
|
||||||
|
x, ok := v.(uint)
|
||||||
|
if !ok {
|
||||||
|
doPanic("Uint", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToFloat64 returns its argument as a float64.
|
||||||
|
// It panics if its argument is nil or not a float64.
|
||||||
|
func ToFloat64(v Float64) float64 {
|
||||||
|
x, ok := v.(float64)
|
||||||
|
if !ok {
|
||||||
|
doPanic("Float64", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToDuration returns its argument as a time.Duration.
|
||||||
|
// It panics if its argument is nil or not a time.Duration.
|
||||||
|
func ToDuration(v Duration) time.Duration {
|
||||||
|
x, ok := v.(time.Duration)
|
||||||
|
if !ok {
|
||||||
|
doPanic("Duration", v)
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func doPanic(capType string, v interface{}) {
|
||||||
|
panic(fmt.Sprintf("optional.%s value should be %s, got %T", capType, strings.ToLower(capType), v))
|
||||||
|
}
|
54
vendor/cloud.google.com/go/internal/retry.go
generated
vendored
Normal file
54
vendor/cloud.google.com/go/internal/retry.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
gax "github.com/googleapis/gax-go/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Retry calls the supplied function f repeatedly according to the provided
|
||||||
|
// backoff parameters. It returns when one of the following occurs:
|
||||||
|
// When f's first return value is true, Retry immediately returns with f's second
|
||||||
|
// return value.
|
||||||
|
// When the provided context is done, Retry returns with an error that
|
||||||
|
// includes both ctx.Error() and the last error returned by f.
|
||||||
|
func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
|
||||||
|
return retry(ctx, bo, f, gax.Sleep)
|
||||||
|
}
|
||||||
|
|
||||||
|
func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
|
||||||
|
sleep func(context.Context, time.Duration) error) error {
|
||||||
|
var lastErr error
|
||||||
|
for {
|
||||||
|
stop, err := f()
|
||||||
|
if stop {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Remember the last "real" error from f.
|
||||||
|
if err != nil && err != context.Canceled && err != context.DeadlineExceeded {
|
||||||
|
lastErr = err
|
||||||
|
}
|
||||||
|
p := bo.Pause()
|
||||||
|
if cerr := sleep(ctx, p); cerr != nil {
|
||||||
|
if lastErr != nil {
|
||||||
|
return Annotatef(lastErr, "retry failed with %v; last error", cerr)
|
||||||
|
}
|
||||||
|
return cerr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
vendor/cloud.google.com/go/internal/trace/trace.go
generated
vendored
Normal file
109
vendor/cloud.google.com/go/internal/trace/trace.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package trace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"go.opencensus.io/trace"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
"google.golang.org/genproto/googleapis/rpc/code"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StartSpan adds a span to the trace with the given name.
|
||||||
|
func StartSpan(ctx context.Context, name string) context.Context {
|
||||||
|
ctx, _ = trace.StartSpan(ctx, name)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndSpan ends a span with the given error.
|
||||||
|
func EndSpan(ctx context.Context, err error) {
|
||||||
|
span := trace.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
span.SetStatus(toStatus(err))
|
||||||
|
}
|
||||||
|
span.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// toStatus interrogates an error and converts it to an appropriate
|
||||||
|
// OpenCensus status.
|
||||||
|
func toStatus(err error) trace.Status {
|
||||||
|
if err2, ok := err.(*googleapi.Error); ok {
|
||||||
|
return trace.Status{Code: httpStatusCodeToOCCode(err2.Code), Message: err2.Message}
|
||||||
|
} else if s, ok := status.FromError(err); ok {
|
||||||
|
return trace.Status{Code: int32(s.Code()), Message: s.Message()}
|
||||||
|
} else {
|
||||||
|
return trace.Status{Code: int32(code.Code_UNKNOWN), Message: err.Error()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(deklerk): switch to using OpenCensus function when it becomes available.
|
||||||
|
// Reference: https://github.com/googleapis/googleapis/blob/26b634d2724ac5dd30ae0b0cbfb01f07f2e4050e/google/rpc/code.proto
|
||||||
|
func httpStatusCodeToOCCode(httpStatusCode int) int32 {
|
||||||
|
switch httpStatusCode {
|
||||||
|
case 200:
|
||||||
|
return int32(code.Code_OK)
|
||||||
|
case 499:
|
||||||
|
return int32(code.Code_CANCELLED)
|
||||||
|
case 500:
|
||||||
|
return int32(code.Code_UNKNOWN) // Could also be Code_INTERNAL, Code_DATA_LOSS
|
||||||
|
case 400:
|
||||||
|
return int32(code.Code_INVALID_ARGUMENT) // Could also be Code_OUT_OF_RANGE
|
||||||
|
case 504:
|
||||||
|
return int32(code.Code_DEADLINE_EXCEEDED)
|
||||||
|
case 404:
|
||||||
|
return int32(code.Code_NOT_FOUND)
|
||||||
|
case 409:
|
||||||
|
return int32(code.Code_ALREADY_EXISTS) // Could also be Code_ABORTED
|
||||||
|
case 403:
|
||||||
|
return int32(code.Code_PERMISSION_DENIED)
|
||||||
|
case 401:
|
||||||
|
return int32(code.Code_UNAUTHENTICATED)
|
||||||
|
case 429:
|
||||||
|
return int32(code.Code_RESOURCE_EXHAUSTED)
|
||||||
|
case 501:
|
||||||
|
return int32(code.Code_UNIMPLEMENTED)
|
||||||
|
case 503:
|
||||||
|
return int32(code.Code_UNAVAILABLE)
|
||||||
|
default:
|
||||||
|
return int32(code.Code_UNKNOWN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: (odeke-em): perhaps just pass around spans due to the cost
|
||||||
|
// incurred from using trace.FromContext(ctx) yet we could avoid
|
||||||
|
// throwing away the work done by ctx, span := trace.StartSpan.
|
||||||
|
func TracePrintf(ctx context.Context, attrMap map[string]interface{}, format string, args ...interface{}) {
|
||||||
|
var attrs []trace.Attribute
|
||||||
|
for k, v := range attrMap {
|
||||||
|
var a trace.Attribute
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
a = trace.StringAttribute(k, v)
|
||||||
|
case bool:
|
||||||
|
a = trace.BoolAttribute(k, v)
|
||||||
|
case int:
|
||||||
|
a = trace.Int64Attribute(k, int64(v))
|
||||||
|
case int64:
|
||||||
|
a = trace.Int64Attribute(k, v)
|
||||||
|
default:
|
||||||
|
a = trace.StringAttribute(k, fmt.Sprintf("%#v", v))
|
||||||
|
}
|
||||||
|
attrs = append(attrs, a)
|
||||||
|
}
|
||||||
|
trace.FromContext(ctx).Annotatef(attrs, format, args...)
|
||||||
|
}
|
19
vendor/cloud.google.com/go/internal/version/update_version.sh
generated
vendored
Normal file
19
vendor/cloud.google.com/go/internal/version/update_version.sh
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Copyright 2019 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
today=$(date +%Y%m%d)
|
||||||
|
|
||||||
|
sed -i -r -e 's/const Repo = "([0-9]{8})"/const Repo = "'$today'"/' $GOFILE
|
||||||
|
|
71
vendor/cloud.google.com/go/internal/version/version.go
generated
vendored
Normal file
71
vendor/cloud.google.com/go/internal/version/version.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:generate ./update_version.sh
|
||||||
|
|
||||||
|
// Package version contains version information for Google Cloud Client
|
||||||
|
// Libraries for Go, as reported in request headers.
|
||||||
|
package version
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Repo is the current version of the client libraries in this
|
||||||
|
// repo. It should be a date in YYYYMMDD format.
|
||||||
|
const Repo = "20190802"
|
||||||
|
|
||||||
|
// Go returns the Go runtime version. The returned string
|
||||||
|
// has no whitespace.
|
||||||
|
func Go() string {
|
||||||
|
return goVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
var goVersion = goVer(runtime.Version())
|
||||||
|
|
||||||
|
const develPrefix = "devel +"
|
||||||
|
|
||||||
|
func goVer(s string) string {
|
||||||
|
if strings.HasPrefix(s, develPrefix) {
|
||||||
|
s = s[len(develPrefix):]
|
||||||
|
if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
|
||||||
|
s = s[:p]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(s, "go1") {
|
||||||
|
s = s[2:]
|
||||||
|
var prerelease string
|
||||||
|
if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
|
||||||
|
s, prerelease = s[:p], s[p:]
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(s, ".") {
|
||||||
|
s += "0"
|
||||||
|
} else if strings.Count(s, ".") < 2 {
|
||||||
|
s += ".0"
|
||||||
|
}
|
||||||
|
if prerelease != "" {
|
||||||
|
s += "-" + prerelease
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func notSemverRune(r rune) bool {
|
||||||
|
return !strings.ContainsRune("0123456789.", r)
|
||||||
|
}
|
32
vendor/cloud.google.com/go/storage/README.md
generated
vendored
Normal file
32
vendor/cloud.google.com/go/storage/README.md
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
## Cloud Storage [![GoDoc](https://godoc.org/cloud.google.com/go/storage?status.svg)](https://godoc.org/cloud.google.com/go/storage)
|
||||||
|
|
||||||
|
- [About Cloud Storage](https://cloud.google.com/storage/)
|
||||||
|
- [API documentation](https://cloud.google.com/storage/docs)
|
||||||
|
- [Go client documentation](https://godoc.org/cloud.google.com/go/storage)
|
||||||
|
- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/storage)
|
||||||
|
|
||||||
|
### Example Usage
|
||||||
|
|
||||||
|
First create a `storage.Client` to use throughout your application:
|
||||||
|
|
||||||
|
[snip]:# (storage-1)
|
||||||
|
```go
|
||||||
|
client, err := storage.NewClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[snip]:# (storage-2)
|
||||||
|
```go
|
||||||
|
// Read the object1 from bucket.
|
||||||
|
rc, err := client.Bucket("bucket").Object("object1").NewReader(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer rc.Close()
|
||||||
|
body, err := ioutil.ReadAll(rc)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
```
|
335
vendor/cloud.google.com/go/storage/acl.go
generated
vendored
Normal file
335
vendor/cloud.google.com/go/storage/acl.go
generated
vendored
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
// Copyright 2014 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ACLRole is the level of access to grant.
|
||||||
|
type ACLRole string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RoleOwner ACLRole = "OWNER"
|
||||||
|
RoleReader ACLRole = "READER"
|
||||||
|
RoleWriter ACLRole = "WRITER"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ACLEntity refers to a user or group.
|
||||||
|
// They are sometimes referred to as grantees.
|
||||||
|
//
|
||||||
|
// It could be in the form of:
|
||||||
|
// "user-<userId>", "user-<email>", "group-<groupId>", "group-<email>",
|
||||||
|
// "domain-<domain>" and "project-team-<projectId>".
|
||||||
|
//
|
||||||
|
// Or one of the predefined constants: AllUsers, AllAuthenticatedUsers.
|
||||||
|
type ACLEntity string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AllUsers ACLEntity = "allUsers"
|
||||||
|
AllAuthenticatedUsers ACLEntity = "allAuthenticatedUsers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ACLRule represents a grant for a role to an entity (user, group or team) for a
|
||||||
|
// Google Cloud Storage object or bucket.
|
||||||
|
type ACLRule struct {
|
||||||
|
Entity ACLEntity
|
||||||
|
EntityID string
|
||||||
|
Role ACLRole
|
||||||
|
Domain string
|
||||||
|
Email string
|
||||||
|
ProjectTeam *ProjectTeam
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectTeam is the project team associated with the entity, if any.
|
||||||
|
type ProjectTeam struct {
|
||||||
|
ProjectNumber string
|
||||||
|
Team string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACLHandle provides operations on an access control list for a Google Cloud Storage bucket or object.
|
||||||
|
type ACLHandle struct {
|
||||||
|
c *Client
|
||||||
|
bucket string
|
||||||
|
object string
|
||||||
|
isDefault bool
|
||||||
|
userProject string // for requester-pays buckets
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete permanently deletes the ACL entry for the given entity.
|
||||||
|
func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Delete")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if a.object != "" {
|
||||||
|
return a.objectDelete(ctx, entity)
|
||||||
|
}
|
||||||
|
if a.isDefault {
|
||||||
|
return a.bucketDefaultDelete(ctx, entity)
|
||||||
|
}
|
||||||
|
return a.bucketDelete(ctx, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the role for the given entity.
|
||||||
|
func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Set")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if a.object != "" {
|
||||||
|
return a.objectSet(ctx, entity, role, false)
|
||||||
|
}
|
||||||
|
if a.isDefault {
|
||||||
|
return a.objectSet(ctx, entity, role, true)
|
||||||
|
}
|
||||||
|
return a.bucketSet(ctx, entity, role)
|
||||||
|
}
|
||||||
|
|
||||||
|
// List retrieves ACL entries.
|
||||||
|
func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.List")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if a.object != "" {
|
||||||
|
return a.objectList(ctx)
|
||||||
|
}
|
||||||
|
if a.isDefault {
|
||||||
|
return a.bucketDefaultList(ctx)
|
||||||
|
}
|
||||||
|
return a.bucketList(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) {
|
||||||
|
var acls *raw.ObjectAccessControls
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.DefaultObjectAccessControls.List(a.bucket)
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
acls, err = req.Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return toObjectACLRules(acls.Items), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.DefaultObjectAccessControls.Delete(a.bucket, string(entity))
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
return req.Do()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
|
||||||
|
var acls *raw.BucketAccessControls
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.BucketAccessControls.List(a.bucket)
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
acls, err = req.Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return toBucketACLRules(acls.Items), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
|
||||||
|
acl := &raw.BucketAccessControl{
|
||||||
|
Bucket: a.bucket,
|
||||||
|
Entity: string(entity),
|
||||||
|
Role: string(role),
|
||||||
|
}
|
||||||
|
err := runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.BucketAccessControls.Update(a.bucket, string(entity), acl)
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
_, err := req.Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity))
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
return req.Do()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) {
|
||||||
|
var acls *raw.ObjectAccessControls
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.ObjectAccessControls.List(a.bucket, a.object)
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
acls, err = req.Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return toObjectACLRules(acls.Items), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error {
|
||||||
|
type setRequest interface {
|
||||||
|
Do(opts ...googleapi.CallOption) (*raw.ObjectAccessControl, error)
|
||||||
|
Header() http.Header
|
||||||
|
}
|
||||||
|
|
||||||
|
acl := &raw.ObjectAccessControl{
|
||||||
|
Bucket: a.bucket,
|
||||||
|
Entity: string(entity),
|
||||||
|
Role: string(role),
|
||||||
|
}
|
||||||
|
var req setRequest
|
||||||
|
if isBucketDefault {
|
||||||
|
req = a.c.raw.DefaultObjectAccessControls.Update(a.bucket, string(entity), acl)
|
||||||
|
} else {
|
||||||
|
req = a.c.raw.ObjectAccessControls.Update(a.bucket, a.object, string(entity), acl)
|
||||||
|
}
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
_, err := req.Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
req := a.c.raw.ObjectAccessControls.Delete(a.bucket, a.object, string(entity))
|
||||||
|
a.configureCall(ctx, req)
|
||||||
|
return req.Do()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACLHandle) configureCall(ctx context.Context, call interface{ Header() http.Header }) {
|
||||||
|
vc := reflect.ValueOf(call)
|
||||||
|
vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
|
||||||
|
if a.userProject != "" {
|
||||||
|
vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
|
||||||
|
}
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
}
|
||||||
|
|
||||||
|
func toObjectACLRules(items []*raw.ObjectAccessControl) []ACLRule {
|
||||||
|
var rs []ACLRule
|
||||||
|
for _, item := range items {
|
||||||
|
rs = append(rs, toObjectACLRule(item))
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBucketACLRules(items []*raw.BucketAccessControl) []ACLRule {
|
||||||
|
var rs []ACLRule
|
||||||
|
for _, item := range items {
|
||||||
|
rs = append(rs, toBucketACLRule(item))
|
||||||
|
}
|
||||||
|
return rs
|
||||||
|
}
|
||||||
|
|
||||||
|
func toObjectACLRule(a *raw.ObjectAccessControl) ACLRule {
|
||||||
|
return ACLRule{
|
||||||
|
Entity: ACLEntity(a.Entity),
|
||||||
|
EntityID: a.EntityId,
|
||||||
|
Role: ACLRole(a.Role),
|
||||||
|
Domain: a.Domain,
|
||||||
|
Email: a.Email,
|
||||||
|
ProjectTeam: toObjectProjectTeam(a.ProjectTeam),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBucketACLRule(a *raw.BucketAccessControl) ACLRule {
|
||||||
|
return ACLRule{
|
||||||
|
Entity: ACLEntity(a.Entity),
|
||||||
|
EntityID: a.EntityId,
|
||||||
|
Role: ACLRole(a.Role),
|
||||||
|
Domain: a.Domain,
|
||||||
|
Email: a.Email,
|
||||||
|
ProjectTeam: toBucketProjectTeam(a.ProjectTeam),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRawObjectACL(rules []ACLRule) []*raw.ObjectAccessControl {
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
r := make([]*raw.ObjectAccessControl, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
r = append(r, rule.toRawObjectAccessControl("")) // bucket name unnecessary
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRawBucketACL(rules []ACLRule) []*raw.BucketAccessControl {
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
r := make([]*raw.BucketAccessControl, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
r = append(r, rule.toRawBucketAccessControl("")) // bucket name unnecessary
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ACLRule) toRawBucketAccessControl(bucket string) *raw.BucketAccessControl {
|
||||||
|
return &raw.BucketAccessControl{
|
||||||
|
Bucket: bucket,
|
||||||
|
Entity: string(r.Entity),
|
||||||
|
Role: string(r.Role),
|
||||||
|
// The other fields are not settable.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ACLRule) toRawObjectAccessControl(bucket string) *raw.ObjectAccessControl {
|
||||||
|
return &raw.ObjectAccessControl{
|
||||||
|
Bucket: bucket,
|
||||||
|
Entity: string(r.Entity),
|
||||||
|
Role: string(r.Role),
|
||||||
|
// The other fields are not settable.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toBucketProjectTeam(p *raw.BucketAccessControlProjectTeam) *ProjectTeam {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ProjectTeam{
|
||||||
|
ProjectNumber: p.ProjectNumber,
|
||||||
|
Team: p.Team,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toObjectProjectTeam(p *raw.ObjectAccessControlProjectTeam) *ProjectTeam {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ProjectTeam{
|
||||||
|
ProjectNumber: p.ProjectNumber,
|
||||||
|
Team: p.Team,
|
||||||
|
}
|
||||||
|
}
|
1195
vendor/cloud.google.com/go/storage/bucket.go
generated
vendored
Normal file
1195
vendor/cloud.google.com/go/storage/bucket.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
228
vendor/cloud.google.com/go/storage/copy.go
generated
vendored
Normal file
228
vendor/cloud.google.com/go/storage/copy.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CopierFrom creates a Copier that can copy src to dst.
|
||||||
|
// You can immediately call Run on the returned Copier, or
|
||||||
|
// you can configure it first.
|
||||||
|
//
|
||||||
|
// For Requester Pays buckets, the user project of dst is billed, unless it is empty,
|
||||||
|
// in which case the user project of src is billed.
|
||||||
|
func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier {
|
||||||
|
return &Copier{dst: dst, src: src}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Copier copies a source object to a destination.
|
||||||
|
type Copier struct {
|
||||||
|
// ObjectAttrs are optional attributes to set on the destination object.
|
||||||
|
// Any attributes must be initialized before any calls on the Copier. Nil
|
||||||
|
// or zero-valued attributes are ignored.
|
||||||
|
ObjectAttrs
|
||||||
|
|
||||||
|
// RewriteToken can be set before calling Run to resume a copy
|
||||||
|
// operation. After Run returns a non-nil error, RewriteToken will
|
||||||
|
// have been updated to contain the value needed to resume the copy.
|
||||||
|
RewriteToken string
|
||||||
|
|
||||||
|
// ProgressFunc can be used to monitor the progress of a multi-RPC copy
|
||||||
|
// operation. If ProgressFunc is not nil and copying requires multiple
|
||||||
|
// calls to the underlying service (see
|
||||||
|
// https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite), then
|
||||||
|
// ProgressFunc will be invoked after each call with the number of bytes of
|
||||||
|
// content copied so far and the total size in bytes of the source object.
|
||||||
|
//
|
||||||
|
// ProgressFunc is intended to make upload progress available to the
|
||||||
|
// application. For example, the implementation of ProgressFunc may update
|
||||||
|
// a progress bar in the application's UI, or log the result of
|
||||||
|
// float64(copiedBytes)/float64(totalBytes).
|
||||||
|
//
|
||||||
|
// ProgressFunc should return quickly without blocking.
|
||||||
|
ProgressFunc func(copiedBytes, totalBytes uint64)
|
||||||
|
|
||||||
|
// The Cloud KMS key, in the form projects/P/locations/L/keyRings/R/cryptoKeys/K,
|
||||||
|
// that will be used to encrypt the object. Overrides the object's KMSKeyName, if
|
||||||
|
// any.
|
||||||
|
//
|
||||||
|
// Providing both a DestinationKMSKeyName and a customer-supplied encryption key
|
||||||
|
// (via ObjectHandle.Key) on the destination object will result in an error when
|
||||||
|
// Run is called.
|
||||||
|
DestinationKMSKeyName string
|
||||||
|
|
||||||
|
dst, src *ObjectHandle
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run performs the copy.
|
||||||
|
func (c *Copier) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Copier.Run")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if err := c.src.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.dst.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c.DestinationKMSKeyName != "" && c.dst.encryptionKey != nil {
|
||||||
|
return nil, errors.New("storage: cannot use DestinationKMSKeyName with a customer-supplied encryption key")
|
||||||
|
}
|
||||||
|
// Convert destination attributes to raw form, omitting the bucket.
|
||||||
|
// If the bucket is included but name or content-type aren't, the service
|
||||||
|
// returns a 400 with "Required" as the only message. Omitting the bucket
|
||||||
|
// does not cause any problems.
|
||||||
|
rawObject := c.ObjectAttrs.toRawObject("")
|
||||||
|
for {
|
||||||
|
res, err := c.callRewrite(ctx, rawObject)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c.ProgressFunc != nil {
|
||||||
|
c.ProgressFunc(uint64(res.TotalBytesRewritten), uint64(res.ObjectSize))
|
||||||
|
}
|
||||||
|
if res.Done { // Finished successfully.
|
||||||
|
return newObject(res.Resource), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.RewriteResponse, error) {
|
||||||
|
call := c.dst.c.raw.Objects.Rewrite(c.src.bucket, c.src.object, c.dst.bucket, c.dst.object, rawObj)
|
||||||
|
|
||||||
|
call.Context(ctx).Projection("full")
|
||||||
|
if c.RewriteToken != "" {
|
||||||
|
call.RewriteToken(c.RewriteToken)
|
||||||
|
}
|
||||||
|
if c.DestinationKMSKeyName != "" {
|
||||||
|
call.DestinationKmsKeyName(c.DestinationKMSKeyName)
|
||||||
|
}
|
||||||
|
if c.PredefinedACL != "" {
|
||||||
|
call.DestinationPredefinedAcl(c.PredefinedACL)
|
||||||
|
}
|
||||||
|
if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c.dst.userProject != "" {
|
||||||
|
call.UserProject(c.dst.userProject)
|
||||||
|
} else if c.src.userProject != "" {
|
||||||
|
call.UserProject(c.src.userProject)
|
||||||
|
}
|
||||||
|
if err := applySourceConds(c.src.gen, c.src.conds, call); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := setEncryptionHeaders(call.Header(), c.src.encryptionKey, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res *raw.RewriteResponse
|
||||||
|
var err error
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
err = runWithRetry(ctx, func() error { res, err = call.Do(); return err })
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.RewriteToken = res.RewriteToken
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComposerFrom creates a Composer that can compose srcs into dst.
|
||||||
|
// You can immediately call Run on the returned Composer, or you can
|
||||||
|
// configure it first.
|
||||||
|
//
|
||||||
|
// The encryption key for the destination object will be used to decrypt all
|
||||||
|
// source objects and encrypt the destination object. It is an error
|
||||||
|
// to specify an encryption key for any of the source objects.
|
||||||
|
func (dst *ObjectHandle) ComposerFrom(srcs ...*ObjectHandle) *Composer {
|
||||||
|
return &Composer{dst: dst, srcs: srcs}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Composer composes source objects into a destination object.
|
||||||
|
//
|
||||||
|
// For Requester Pays buckets, the user project of dst is billed.
|
||||||
|
type Composer struct {
|
||||||
|
// ObjectAttrs are optional attributes to set on the destination object.
|
||||||
|
// Any attributes must be initialized before any calls on the Composer. Nil
|
||||||
|
// or zero-valued attributes are ignored.
|
||||||
|
ObjectAttrs
|
||||||
|
|
||||||
|
dst *ObjectHandle
|
||||||
|
srcs []*ObjectHandle
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run performs the compose operation.
|
||||||
|
func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Composer.Run")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if err := c.dst.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(c.srcs) == 0 {
|
||||||
|
return nil, errors.New("storage: at least one source object must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &raw.ComposeRequest{}
|
||||||
|
// Compose requires a non-empty Destination, so we always set it,
|
||||||
|
// even if the caller-provided ObjectAttrs is the zero value.
|
||||||
|
req.Destination = c.ObjectAttrs.toRawObject(c.dst.bucket)
|
||||||
|
for _, src := range c.srcs {
|
||||||
|
if err := src.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if src.bucket != c.dst.bucket {
|
||||||
|
return nil, fmt.Errorf("storage: all source objects must be in bucket %q, found %q", c.dst.bucket, src.bucket)
|
||||||
|
}
|
||||||
|
if src.encryptionKey != nil {
|
||||||
|
return nil, fmt.Errorf("storage: compose source %s.%s must not have encryption key", src.bucket, src.object)
|
||||||
|
}
|
||||||
|
srcObj := &raw.ComposeRequestSourceObjects{
|
||||||
|
Name: src.object,
|
||||||
|
}
|
||||||
|
if err := applyConds("ComposeFrom source", src.gen, src.conds, composeSourceObj{srcObj}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.SourceObjects = append(req.SourceObjects, srcObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
call := c.dst.c.raw.Objects.Compose(c.dst.bucket, c.dst.object, req).Context(ctx)
|
||||||
|
if err := applyConds("ComposeFrom destination", c.dst.gen, c.dst.conds, call); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c.dst.userProject != "" {
|
||||||
|
call.UserProject(c.dst.userProject)
|
||||||
|
}
|
||||||
|
if c.PredefinedACL != "" {
|
||||||
|
call.DestinationPredefinedAcl(c.PredefinedACL)
|
||||||
|
}
|
||||||
|
if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var obj *raw.Object
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newObject(obj), nil
|
||||||
|
}
|
176
vendor/cloud.google.com/go/storage/doc.go
generated
vendored
Normal file
176
vendor/cloud.google.com/go/storage/doc.go
generated
vendored
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package storage provides an easy way to work with Google Cloud Storage.
|
||||||
|
Google Cloud Storage stores data in named objects, which are grouped into buckets.
|
||||||
|
|
||||||
|
More information about Google Cloud Storage is available at
|
||||||
|
https://cloud.google.com/storage/docs.
|
||||||
|
|
||||||
|
See https://godoc.org/cloud.google.com/go for authentication, timeouts,
|
||||||
|
connection pooling and similar aspects of this package.
|
||||||
|
|
||||||
|
All of the methods of this package use exponential backoff to retry calls that fail
|
||||||
|
with certain errors, as described in
|
||||||
|
https://cloud.google.com/storage/docs/exponential-backoff. Retrying continues
|
||||||
|
indefinitely unless the controlling context is canceled or the client is closed. See
|
||||||
|
context.WithTimeout and context.WithCancel.
|
||||||
|
|
||||||
|
|
||||||
|
Creating a Client
|
||||||
|
|
||||||
|
To start working with this package, create a client:
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
client, err := storage.NewClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
|
||||||
|
The client will use your default application credentials.
|
||||||
|
|
||||||
|
If you only wish to access public data, you can create
|
||||||
|
an unauthenticated client with
|
||||||
|
|
||||||
|
client, err := storage.NewClient(ctx, option.WithoutAuthentication())
|
||||||
|
|
||||||
|
Buckets
|
||||||
|
|
||||||
|
A Google Cloud Storage bucket is a collection of objects. To work with a
|
||||||
|
bucket, make a bucket handle:
|
||||||
|
|
||||||
|
bkt := client.Bucket(bucketName)
|
||||||
|
|
||||||
|
A handle is a reference to a bucket. You can have a handle even if the
|
||||||
|
bucket doesn't exist yet. To create a bucket in Google Cloud Storage,
|
||||||
|
call Create on the handle:
|
||||||
|
|
||||||
|
if err := bkt.Create(ctx, projectID, nil); err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that although buckets are associated with projects, bucket names are
|
||||||
|
global across all projects.
|
||||||
|
|
||||||
|
Each bucket has associated metadata, represented in this package by
|
||||||
|
BucketAttrs. The third argument to BucketHandle.Create allows you to set
|
||||||
|
the initial BucketAttrs of a bucket. To retrieve a bucket's attributes, use
|
||||||
|
Attrs:
|
||||||
|
|
||||||
|
attrs, err := bkt.Attrs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
fmt.Printf("bucket %s, created at %s, is located in %s with storage class %s\n",
|
||||||
|
attrs.Name, attrs.Created, attrs.Location, attrs.StorageClass)
|
||||||
|
|
||||||
|
Objects
|
||||||
|
|
||||||
|
An object holds arbitrary data as a sequence of bytes, like a file. You
|
||||||
|
refer to objects using a handle, just as with buckets, but unlike buckets
|
||||||
|
you don't explicitly create an object. Instead, the first time you write
|
||||||
|
to an object it will be created. You can use the standard Go io.Reader
|
||||||
|
and io.Writer interfaces to read and write object data:
|
||||||
|
|
||||||
|
obj := bkt.Object("data")
|
||||||
|
// Write something to obj.
|
||||||
|
// w implements io.Writer.
|
||||||
|
w := obj.NewWriter(ctx)
|
||||||
|
// Write some text to obj. This will either create the object or overwrite whatever is there already.
|
||||||
|
if _, err := fmt.Fprintf(w, "This object contains text.\n"); err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
// Close, just like writing a file.
|
||||||
|
if err := w.Close(); err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read it back.
|
||||||
|
r, err := obj.NewReader(ctx)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
if _, err := io.Copy(os.Stdout, r); err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
// Prints "This object contains text."
|
||||||
|
|
||||||
|
Objects also have attributes, which you can fetch with Attrs:
|
||||||
|
|
||||||
|
objAttrs, err := obj.Attrs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
fmt.Printf("object %s has size %d and can be read using %s\n",
|
||||||
|
objAttrs.Name, objAttrs.Size, objAttrs.MediaLink)
|
||||||
|
|
||||||
|
ACLs
|
||||||
|
|
||||||
|
Both objects and buckets have ACLs (Access Control Lists). An ACL is a list of
|
||||||
|
ACLRules, each of which specifies the role of a user, group or project. ACLs
|
||||||
|
are suitable for fine-grained control, but you may prefer using IAM to control
|
||||||
|
access at the project level (see
|
||||||
|
https://cloud.google.com/storage/docs/access-control/iam).
|
||||||
|
|
||||||
|
To list the ACLs of a bucket or object, obtain an ACLHandle and call its List method:
|
||||||
|
|
||||||
|
acls, err := obj.ACL().List(ctx)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
for _, rule := range acls {
|
||||||
|
fmt.Printf("%s has role %s\n", rule.Entity, rule.Role)
|
||||||
|
}
|
||||||
|
|
||||||
|
You can also set and delete ACLs.
|
||||||
|
|
||||||
|
Conditions
|
||||||
|
|
||||||
|
Every object has a generation and a metageneration. The generation changes
|
||||||
|
whenever the content changes, and the metageneration changes whenever the
|
||||||
|
metadata changes. Conditions let you check these values before an operation;
|
||||||
|
the operation only executes if the conditions match. You can use conditions to
|
||||||
|
prevent race conditions in read-modify-write operations.
|
||||||
|
|
||||||
|
For example, say you've read an object's metadata into objAttrs. Now
|
||||||
|
you want to write to that object, but only if its contents haven't changed
|
||||||
|
since you read it. Here is how to express that:
|
||||||
|
|
||||||
|
w = obj.If(storage.Conditions{GenerationMatch: objAttrs.Generation}).NewWriter(ctx)
|
||||||
|
// Proceed with writing as above.
|
||||||
|
|
||||||
|
Signed URLs
|
||||||
|
|
||||||
|
You can obtain a URL that lets anyone read or write an object for a limited time.
|
||||||
|
You don't need to create a client to do this. See the documentation of
|
||||||
|
SignedURL for details.
|
||||||
|
|
||||||
|
url, err := storage.SignedURL(bucketName, "shared-object", opts)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Handle error.
|
||||||
|
}
|
||||||
|
fmt.Println(url)
|
||||||
|
|
||||||
|
Errors
|
||||||
|
|
||||||
|
Errors returned by this client are often of the type [`googleapi.Error`](https://godoc.org/google.golang.org/api/googleapi#Error).
|
||||||
|
These errors can be introspected for more information by type asserting to the richer `googleapi.Error` type. For example:
|
||||||
|
|
||||||
|
if e, ok := err.(*googleapi.Error); ok {
|
||||||
|
if e.Code == 409 { ... }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package storage // import "cloud.google.com/go/storage"
|
32
vendor/cloud.google.com/go/storage/go110.go
generated
vendored
Normal file
32
vendor/cloud.google.com/go/storage/go110.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build go1.10
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import "google.golang.org/api/googleapi"
|
||||||
|
|
||||||
|
func shouldRetry(err error) bool {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *googleapi.Error:
|
||||||
|
// Retry on 429 and 5xx, according to
|
||||||
|
// https://cloud.google.com/storage/docs/exponential-backoff.
|
||||||
|
return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
|
||||||
|
case interface{ Temporary() bool }:
|
||||||
|
return e.Temporary()
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
330
vendor/cloud.google.com/go/storage/hmac.go
generated
vendored
Normal file
330
vendor/cloud.google.com/go/storage/hmac.go
generated
vendored
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
// Copyright 2019 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"google.golang.org/api/iterator"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HMACState is the state of the HMAC key.
|
||||||
|
type HMACState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Active is the status for an active key that can be used to sign
|
||||||
|
// requests.
|
||||||
|
Active HMACState = "ACTIVE"
|
||||||
|
|
||||||
|
// Inactive is the status for an inactive key thus requests signed by
|
||||||
|
// this key will be denied.
|
||||||
|
Inactive HMACState = "INACTIVE"
|
||||||
|
|
||||||
|
// Deleted is the status for a key that is deleted.
|
||||||
|
// Once in this state the key cannot key cannot be recovered
|
||||||
|
// and does not count towards key limits. Deleted keys will be cleaned
|
||||||
|
// up later.
|
||||||
|
Deleted HMACState = "DELETED"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HMACKey is the representation of a Google Cloud Storage HMAC key.
|
||||||
|
//
|
||||||
|
// HMAC keys are used to authenticate signed access to objects. To enable HMAC key
|
||||||
|
// authentication, please visit https://cloud.google.com/storage/docs/migrating.
|
||||||
|
//
|
||||||
|
// This type is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
type HMACKey struct {
|
||||||
|
// The HMAC's secret key.
|
||||||
|
Secret string
|
||||||
|
|
||||||
|
// AccessID is the ID of the HMAC key.
|
||||||
|
AccessID string
|
||||||
|
|
||||||
|
// Etag is the HTTP/1.1 Entity tag.
|
||||||
|
Etag string
|
||||||
|
|
||||||
|
// ID is the ID of the HMAC key, including the ProjectID and AccessID.
|
||||||
|
ID string
|
||||||
|
|
||||||
|
// ProjectID is the ID of the project that owns the
|
||||||
|
// service account to which the key authenticates.
|
||||||
|
ProjectID string
|
||||||
|
|
||||||
|
// ServiceAccountEmail is the email address
|
||||||
|
// of the key's associated service account.
|
||||||
|
ServiceAccountEmail string
|
||||||
|
|
||||||
|
// CreatedTime is the creation time of the HMAC key.
|
||||||
|
CreatedTime time.Time
|
||||||
|
|
||||||
|
// UpdatedTime is the last modification time of the HMAC key metadata.
|
||||||
|
UpdatedTime time.Time
|
||||||
|
|
||||||
|
// State is the state of the HMAC key.
|
||||||
|
// It can be one of StateActive, StateInactive or StateDeleted.
|
||||||
|
State HMACState
|
||||||
|
}
|
||||||
|
|
||||||
|
// HMACKeyHandle helps provide access and management for HMAC keys.
|
||||||
|
//
|
||||||
|
// This type is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
type HMACKeyHandle struct {
|
||||||
|
projectID string
|
||||||
|
accessID string
|
||||||
|
|
||||||
|
raw *raw.ProjectsHmacKeysService
|
||||||
|
}
|
||||||
|
|
||||||
|
// HMACKeyHandle creates a handle that will be used for HMACKey operations.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (c *Client) HMACKeyHandle(projectID, accessID string) *HMACKeyHandle {
|
||||||
|
return &HMACKeyHandle{
|
||||||
|
projectID: projectID,
|
||||||
|
accessID: accessID,
|
||||||
|
raw: raw.NewProjectsHmacKeysService(c.raw),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get invokes an RPC to retrieve the HMAC key referenced by the
|
||||||
|
// HMACKeyHandle's accessID.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (hkh *HMACKeyHandle) Get(ctx context.Context) (*HMACKey, error) {
|
||||||
|
call := hkh.raw.Get(hkh.projectID, hkh.accessID)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
|
||||||
|
var metadata *raw.HmacKeyMetadata
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
metadata, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hkPb := &raw.HmacKey{
|
||||||
|
Metadata: metadata,
|
||||||
|
}
|
||||||
|
return pbHmacKeyToHMACKey(hkPb, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete invokes an RPC to delete the key referenced by accessID, on Google Cloud Storage.
|
||||||
|
// Only inactive HMAC keys can be deleted.
|
||||||
|
// After deletion, a key cannot be used to authenticate requests.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (hkh *HMACKeyHandle) Delete(ctx context.Context) error {
|
||||||
|
delCall := hkh.raw.Delete(hkh.projectID, hkh.accessID)
|
||||||
|
setClientHeader(delCall.Header())
|
||||||
|
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
return delCall.Context(ctx).Do()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func pbHmacKeyToHMACKey(pb *raw.HmacKey, updatedTimeCanBeNil bool) (*HMACKey, error) {
|
||||||
|
pbmd := pb.Metadata
|
||||||
|
if pbmd == nil {
|
||||||
|
return nil, errors.New("field Metadata cannot be nil")
|
||||||
|
}
|
||||||
|
createdTime, err := time.Parse(time.RFC3339, pbmd.TimeCreated)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("field CreatedTime: %v", err)
|
||||||
|
}
|
||||||
|
updatedTime, err := time.Parse(time.RFC3339, pbmd.Updated)
|
||||||
|
if err != nil && !updatedTimeCanBeNil {
|
||||||
|
return nil, fmt.Errorf("field UpdatedTime: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hmk := &HMACKey{
|
||||||
|
AccessID: pbmd.AccessId,
|
||||||
|
Secret: pb.Secret,
|
||||||
|
Etag: pbmd.Etag,
|
||||||
|
ID: pbmd.Id,
|
||||||
|
State: HMACState(pbmd.State),
|
||||||
|
ProjectID: pbmd.ProjectId,
|
||||||
|
CreatedTime: createdTime,
|
||||||
|
UpdatedTime: updatedTime,
|
||||||
|
|
||||||
|
ServiceAccountEmail: pbmd.ServiceAccountEmail,
|
||||||
|
}
|
||||||
|
|
||||||
|
return hmk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHMACKey invokes an RPC for Google Cloud Storage to create a new HMACKey.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (c *Client) CreateHMACKey(ctx context.Context, projectID, serviceAccountEmail string) (*HMACKey, error) {
|
||||||
|
if projectID == "" {
|
||||||
|
return nil, errors.New("storage: expecting a non-blank projectID")
|
||||||
|
}
|
||||||
|
if serviceAccountEmail == "" {
|
||||||
|
return nil, errors.New("storage: expecting a non-blank service account email")
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := raw.NewProjectsHmacKeysService(c.raw)
|
||||||
|
call := svc.Create(projectID, serviceAccountEmail)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
|
||||||
|
var hkPb *raw.HmacKey
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
hkPb, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pbHmacKeyToHMACKey(hkPb, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HMACKeyAttrsToUpdate defines the attributes of an HMACKey that will be updated.
|
||||||
|
//
|
||||||
|
// This type is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
type HMACKeyAttrsToUpdate struct {
|
||||||
|
// State is required and must be either StateActive or StateInactive.
|
||||||
|
State HMACState
|
||||||
|
|
||||||
|
// Etag is an optional field and it is the HTTP/1.1 Entity tag.
|
||||||
|
Etag string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update mutates the HMACKey referred to by accessID.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (h *HMACKeyHandle) Update(ctx context.Context, au HMACKeyAttrsToUpdate) (*HMACKey, error) {
|
||||||
|
if au.State != Active && au.State != Inactive {
|
||||||
|
return nil, fmt.Errorf("storage: invalid state %q for update, must be either %q or %q", au.State, Active, Inactive)
|
||||||
|
}
|
||||||
|
|
||||||
|
call := h.raw.Update(h.projectID, h.accessID, &raw.HmacKeyMetadata{
|
||||||
|
Etag: au.Etag,
|
||||||
|
State: string(au.State),
|
||||||
|
})
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
|
||||||
|
var metadata *raw.HmacKeyMetadata
|
||||||
|
var err error
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
metadata, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hkPb := &raw.HmacKey{
|
||||||
|
Metadata: metadata,
|
||||||
|
}
|
||||||
|
return pbHmacKeyToHMACKey(hkPb, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An HMACKeysIterator is an iterator over HMACKeys.
|
||||||
|
//
|
||||||
|
// This type is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
type HMACKeysIterator struct {
|
||||||
|
ctx context.Context
|
||||||
|
raw *raw.ProjectsHmacKeysService
|
||||||
|
projectID string
|
||||||
|
hmacKeys []*HMACKey
|
||||||
|
pageInfo *iterator.PageInfo
|
||||||
|
nextFunc func() error
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListHMACKeys returns an iterator for listing HMACKeys.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (c *Client) ListHMACKeys(ctx context.Context, projectID string) *HMACKeysIterator {
|
||||||
|
it := &HMACKeysIterator{
|
||||||
|
ctx: ctx,
|
||||||
|
raw: raw.NewProjectsHmacKeysService(c.raw),
|
||||||
|
projectID: projectID,
|
||||||
|
}
|
||||||
|
|
||||||
|
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
|
||||||
|
it.fetch,
|
||||||
|
func() int { return len(it.hmacKeys) - it.index },
|
||||||
|
func() interface{} {
|
||||||
|
prev := it.hmacKeys
|
||||||
|
it.hmacKeys = it.hmacKeys[:0]
|
||||||
|
it.index = 0
|
||||||
|
return prev
|
||||||
|
})
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next result. Its second return value is iterator.Done if
|
||||||
|
// there are no more results. Once Next returns iterator.Done, all subsequent
|
||||||
|
// calls will return iterator.Done.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (it *HMACKeysIterator) Next() (*HMACKey, error) {
|
||||||
|
if err := it.nextFunc(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
key := it.hmacKeys[it.index]
|
||||||
|
it.index++
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
|
||||||
|
//
|
||||||
|
// This method is EXPERIMENTAL and subject to change or removal without notice.
|
||||||
|
func (it *HMACKeysIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
|
||||||
|
|
||||||
|
func (it *HMACKeysIterator) fetch(pageSize int, pageToken string) (token string, err error) {
|
||||||
|
call := it.raw.List(it.projectID)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
call = call.PageToken(pageToken)
|
||||||
|
// By default we'll also show deleted keys and then
|
||||||
|
// let users filter on their own.
|
||||||
|
call = call.ShowDeletedKeys(true)
|
||||||
|
if pageSize > 0 {
|
||||||
|
call = call.MaxResults(int64(pageSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := it.ctx
|
||||||
|
var resp *raw.HmacKeysMetadata
|
||||||
|
err = runWithRetry(it.ctx, func() error {
|
||||||
|
resp, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, metadata := range resp.Items {
|
||||||
|
hkPb := &raw.HmacKey{
|
||||||
|
Metadata: metadata,
|
||||||
|
}
|
||||||
|
hkey, err := pbHmacKeyToHMACKey(hkPb, true)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
it.hmacKeys = append(it.hmacKeys, hkey)
|
||||||
|
}
|
||||||
|
return resp.NextPageToken, nil
|
||||||
|
}
|
130
vendor/cloud.google.com/go/storage/iam.go
generated
vendored
Normal file
130
vendor/cloud.google.com/go/storage/iam.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"cloud.google.com/go/iam"
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
iampb "google.golang.org/genproto/googleapis/iam/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IAM provides access to IAM access control for the bucket.
|
||||||
|
func (b *BucketHandle) IAM() *iam.Handle {
|
||||||
|
return iam.InternalNewHandleClient(&iamClient{
|
||||||
|
raw: b.c.raw,
|
||||||
|
userProject: b.userProject,
|
||||||
|
}, b.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// iamClient implements the iam.client interface.
|
||||||
|
type iamClient struct {
|
||||||
|
raw *raw.Service
|
||||||
|
userProject string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *iamClient) Get(ctx context.Context, resource string) (p *iampb.Policy, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Get")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
call := c.raw.Buckets.GetIamPolicy(resource)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if c.userProject != "" {
|
||||||
|
call.UserProject(c.userProject)
|
||||||
|
}
|
||||||
|
var rp *raw.Policy
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
rp, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return iamFromStoragePolicy(rp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Set")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
rp := iamToStoragePolicy(p)
|
||||||
|
call := c.raw.Buckets.SetIamPolicy(resource, rp)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if c.userProject != "" {
|
||||||
|
call.UserProject(c.userProject)
|
||||||
|
}
|
||||||
|
return runWithRetry(ctx, func() error {
|
||||||
|
_, err := call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *iamClient) Test(ctx context.Context, resource string, perms []string) (permissions []string, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Test")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
call := c.raw.Buckets.TestIamPermissions(resource, perms)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if c.userProject != "" {
|
||||||
|
call.UserProject(c.userProject)
|
||||||
|
}
|
||||||
|
var res *raw.TestIamPermissionsResponse
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Permissions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamToStoragePolicy(ip *iampb.Policy) *raw.Policy {
|
||||||
|
return &raw.Policy{
|
||||||
|
Bindings: iamToStorageBindings(ip.Bindings),
|
||||||
|
Etag: string(ip.Etag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamToStorageBindings(ibs []*iampb.Binding) []*raw.PolicyBindings {
|
||||||
|
var rbs []*raw.PolicyBindings
|
||||||
|
for _, ib := range ibs {
|
||||||
|
rbs = append(rbs, &raw.PolicyBindings{
|
||||||
|
Role: ib.Role,
|
||||||
|
Members: ib.Members,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return rbs
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamFromStoragePolicy(rp *raw.Policy) *iampb.Policy {
|
||||||
|
return &iampb.Policy{
|
||||||
|
Bindings: iamFromStorageBindings(rp.Bindings),
|
||||||
|
Etag: []byte(rp.Etag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func iamFromStorageBindings(rbs []*raw.PolicyBindings) []*iampb.Binding {
|
||||||
|
var ibs []*iampb.Binding
|
||||||
|
for _, rb := range rbs {
|
||||||
|
ibs = append(ibs, &iampb.Binding{
|
||||||
|
Role: rb.Role,
|
||||||
|
Members: rb.Members,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ibs
|
||||||
|
}
|
37
vendor/cloud.google.com/go/storage/invoke.go
generated
vendored
Normal file
37
vendor/cloud.google.com/go/storage/invoke.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2014 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal"
|
||||||
|
gax "github.com/googleapis/gax-go/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// runWithRetry calls the function until it returns nil or a non-retryable error, or
|
||||||
|
// the context is done.
|
||||||
|
func runWithRetry(ctx context.Context, call func() error) error {
|
||||||
|
return internal.Retry(ctx, gax.Backoff{}, func() (stop bool, err error) {
|
||||||
|
err = call()
|
||||||
|
if err == nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if shouldRetry(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
|
})
|
||||||
|
}
|
42
vendor/cloud.google.com/go/storage/not_go110.go
generated
vendored
Normal file
42
vendor/cloud.google.com/go/storage/not_go110.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build !go1.10
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func shouldRetry(err error) bool {
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *googleapi.Error:
|
||||||
|
// Retry on 429 and 5xx, according to
|
||||||
|
// https://cloud.google.com/storage/docs/exponential-backoff.
|
||||||
|
return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
|
||||||
|
case *url.Error:
|
||||||
|
// Retry on REFUSED_STREAM.
|
||||||
|
// Unfortunately the error type is unexported, so we resort to string
|
||||||
|
// matching.
|
||||||
|
return strings.Contains(e.Error(), "REFUSED_STREAM")
|
||||||
|
case interface{ Temporary() bool }:
|
||||||
|
return e.Temporary()
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
188
vendor/cloud.google.com/go/storage/notifications.go
generated
vendored
Normal file
188
vendor/cloud.google.com/go/storage/notifications.go
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Notification describes how to send Cloud PubSub messages when certain
|
||||||
|
// events occur in a bucket.
|
||||||
|
type Notification struct {
|
||||||
|
//The ID of the notification.
|
||||||
|
ID string
|
||||||
|
|
||||||
|
// The ID of the topic to which this subscription publishes.
|
||||||
|
TopicID string
|
||||||
|
|
||||||
|
// The ID of the project to which the topic belongs.
|
||||||
|
TopicProjectID string
|
||||||
|
|
||||||
|
// Only send notifications about listed event types. If empty, send notifications
|
||||||
|
// for all event types.
|
||||||
|
// See https://cloud.google.com/storage/docs/pubsub-notifications#events.
|
||||||
|
EventTypes []string
|
||||||
|
|
||||||
|
// If present, only apply this notification configuration to object names that
|
||||||
|
// begin with this prefix.
|
||||||
|
ObjectNamePrefix string
|
||||||
|
|
||||||
|
// An optional list of additional attributes to attach to each Cloud PubSub
|
||||||
|
// message published for this notification subscription.
|
||||||
|
CustomAttributes map[string]string
|
||||||
|
|
||||||
|
// The contents of the message payload.
|
||||||
|
// See https://cloud.google.com/storage/docs/pubsub-notifications#payload.
|
||||||
|
PayloadFormat string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values for Notification.PayloadFormat.
|
||||||
|
const (
|
||||||
|
// Send no payload with notification messages.
|
||||||
|
NoPayload = "NONE"
|
||||||
|
|
||||||
|
// Send object metadata as JSON with notification messages.
|
||||||
|
JSONPayload = "JSON_API_V1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Values for Notification.EventTypes.
|
||||||
|
const (
|
||||||
|
// Event that occurs when an object is successfully created.
|
||||||
|
ObjectFinalizeEvent = "OBJECT_FINALIZE"
|
||||||
|
|
||||||
|
// Event that occurs when the metadata of an existing object changes.
|
||||||
|
ObjectMetadataUpdateEvent = "OBJECT_METADATA_UPDATE"
|
||||||
|
|
||||||
|
// Event that occurs when an object is permanently deleted.
|
||||||
|
ObjectDeleteEvent = "OBJECT_DELETE"
|
||||||
|
|
||||||
|
// Event that occurs when the live version of an object becomes an
|
||||||
|
// archived version.
|
||||||
|
ObjectArchiveEvent = "OBJECT_ARCHIVE"
|
||||||
|
)
|
||||||
|
|
||||||
|
func toNotification(rn *raw.Notification) *Notification {
|
||||||
|
n := &Notification{
|
||||||
|
ID: rn.Id,
|
||||||
|
EventTypes: rn.EventTypes,
|
||||||
|
ObjectNamePrefix: rn.ObjectNamePrefix,
|
||||||
|
CustomAttributes: rn.CustomAttributes,
|
||||||
|
PayloadFormat: rn.PayloadFormat,
|
||||||
|
}
|
||||||
|
n.TopicProjectID, n.TopicID = parseNotificationTopic(rn.Topic)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
var topicRE = regexp.MustCompile("^//pubsub.googleapis.com/projects/([^/]+)/topics/([^/]+)")
|
||||||
|
|
||||||
|
// parseNotificationTopic extracts the project and topic IDs from from the full
|
||||||
|
// resource name returned by the service. If the name is malformed, it returns
|
||||||
|
// "?" for both IDs.
|
||||||
|
func parseNotificationTopic(nt string) (projectID, topicID string) {
|
||||||
|
matches := topicRE.FindStringSubmatch(nt)
|
||||||
|
if matches == nil {
|
||||||
|
return "?", "?"
|
||||||
|
}
|
||||||
|
return matches[1], matches[2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func toRawNotification(n *Notification) *raw.Notification {
|
||||||
|
return &raw.Notification{
|
||||||
|
Id: n.ID,
|
||||||
|
Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
|
||||||
|
n.TopicProjectID, n.TopicID),
|
||||||
|
EventTypes: n.EventTypes,
|
||||||
|
ObjectNamePrefix: n.ObjectNamePrefix,
|
||||||
|
CustomAttributes: n.CustomAttributes,
|
||||||
|
PayloadFormat: string(n.PayloadFormat),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
|
||||||
|
// and PayloadFormat, and must not set its ID. The other fields are all optional. The
|
||||||
|
// returned Notification's ID can be used to refer to it.
|
||||||
|
func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (ret *Notification, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.AddNotification")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if n.ID != "" {
|
||||||
|
return nil, errors.New("storage: AddNotification: ID must not be set")
|
||||||
|
}
|
||||||
|
if n.TopicProjectID == "" {
|
||||||
|
return nil, errors.New("storage: AddNotification: missing TopicProjectID")
|
||||||
|
}
|
||||||
|
if n.TopicID == "" {
|
||||||
|
return nil, errors.New("storage: AddNotification: missing TopicID")
|
||||||
|
}
|
||||||
|
call := b.c.raw.Notifications.Insert(b.name, toRawNotification(n))
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if b.userProject != "" {
|
||||||
|
call.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
rn, err := call.Context(ctx).Do()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return toNotification(rn), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifications returns all the Notifications configured for this bucket, as a map
|
||||||
|
// indexed by notification ID.
|
||||||
|
func (b *BucketHandle) Notifications(ctx context.Context) (n map[string]*Notification, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Notifications")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
call := b.c.raw.Notifications.List(b.name)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if b.userProject != "" {
|
||||||
|
call.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
var res *raw.Notifications
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = call.Context(ctx).Do()
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return notificationsToMap(res.Items), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
|
||||||
|
m := map[string]*Notification{}
|
||||||
|
for _, rn := range rns {
|
||||||
|
m[rn.Id] = toNotification(rn)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteNotification deletes the notification with the given ID.
|
||||||
|
func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) (err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.DeleteNotification")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
call := b.c.raw.Notifications.Delete(b.name, id)
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
if b.userProject != "" {
|
||||||
|
call.UserProject(b.userProject)
|
||||||
|
}
|
||||||
|
return call.Context(ctx).Do()
|
||||||
|
}
|
403
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
Normal file
403
vendor/cloud.google.com/go/storage/reader.go
generated
vendored
Normal file
@ -0,0 +1,403 @@
|
|||||||
|
// Copyright 2016 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"hash/crc32"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"cloud.google.com/go/internal/trace"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
|
||||||
|
|
||||||
|
// ReaderObjectAttrs are attributes about the object being read. These are populated
|
||||||
|
// during the New call. This struct only holds a subset of object attributes: to
|
||||||
|
// get the full set of attributes, use ObjectHandle.Attrs.
|
||||||
|
//
|
||||||
|
// Each field is read-only.
|
||||||
|
type ReaderObjectAttrs struct {
|
||||||
|
// Size is the length of the object's content.
|
||||||
|
Size int64
|
||||||
|
|
||||||
|
// StartOffset is the byte offset within the object
|
||||||
|
// from which reading begins.
|
||||||
|
// This value is only non-zero for range requests.
|
||||||
|
StartOffset int64
|
||||||
|
|
||||||
|
// ContentType is the MIME type of the object's content.
|
||||||
|
ContentType string
|
||||||
|
|
||||||
|
// ContentEncoding is the encoding of the object's content.
|
||||||
|
ContentEncoding string
|
||||||
|
|
||||||
|
// CacheControl specifies whether and for how long browser and Internet
|
||||||
|
// caches are allowed to cache your objects.
|
||||||
|
CacheControl string
|
||||||
|
|
||||||
|
// LastModified is the time that the object was last modified.
|
||||||
|
LastModified time.Time
|
||||||
|
|
||||||
|
// Generation is the generation number of the object's content.
|
||||||
|
Generation int64
|
||||||
|
|
||||||
|
// Metageneration is the version of the metadata for this object at
|
||||||
|
// this generation. This field is used for preconditions and for
|
||||||
|
// detecting changes in metadata. A metageneration number is only
|
||||||
|
// meaningful in the context of a particular generation of a
|
||||||
|
// particular object.
|
||||||
|
Metageneration int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader creates a new Reader to read the contents of the
|
||||||
|
// object.
|
||||||
|
// ErrObjectNotExist will be returned if the object is not found.
|
||||||
|
//
|
||||||
|
// The caller must call Close on the returned Reader when done reading.
|
||||||
|
func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
|
||||||
|
return o.NewRangeReader(ctx, 0, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRangeReader reads part of an object, reading at most length bytes
|
||||||
|
// starting at the given offset. If length is negative, the object is read
|
||||||
|
// until the end. If offset is negative, the object is read abs(offset) bytes
|
||||||
|
// from the end, and length must also be negative to indicate all remaining
|
||||||
|
// bytes will be read.
|
||||||
|
func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (r *Reader, err error) {
|
||||||
|
ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.NewRangeReader")
|
||||||
|
defer func() { trace.EndSpan(ctx, err) }()
|
||||||
|
|
||||||
|
if err := o.validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if offset < 0 && length >= 0 {
|
||||||
|
return nil, fmt.Errorf("storage: invalid offset %d < 0 requires negative length", offset)
|
||||||
|
}
|
||||||
|
if o.conds != nil {
|
||||||
|
if err := o.conds.validate("NewRangeReader"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u := &url.URL{
|
||||||
|
Scheme: o.c.scheme,
|
||||||
|
Host: o.c.readHost,
|
||||||
|
Path: fmt.Sprintf("/%s/%s", o.bucket, o.object),
|
||||||
|
}
|
||||||
|
verb := "GET"
|
||||||
|
if length == 0 {
|
||||||
|
verb = "HEAD"
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(verb, u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
if o.userProject != "" {
|
||||||
|
req.Header.Set("X-Goog-User-Project", o.userProject)
|
||||||
|
}
|
||||||
|
if o.readCompressed {
|
||||||
|
req.Header.Set("Accept-Encoding", "gzip")
|
||||||
|
}
|
||||||
|
if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gen := o.gen
|
||||||
|
|
||||||
|
// Define a function that initiates a Read with offset and length, assuming we
|
||||||
|
// have already read seen bytes.
|
||||||
|
reopen := func(seen int64) (*http.Response, error) {
|
||||||
|
start := offset + seen
|
||||||
|
if length < 0 && start < 0 {
|
||||||
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d", start))
|
||||||
|
} else if length < 0 && start > 0 {
|
||||||
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", start))
|
||||||
|
} else if length > 0 {
|
||||||
|
// The end character isn't affected by how many bytes we've seen.
|
||||||
|
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, offset+length-1))
|
||||||
|
}
|
||||||
|
// We wait to assign conditions here because the generation number can change in between reopen() runs.
|
||||||
|
req.URL.RawQuery = conditionsQuery(gen, o.conds)
|
||||||
|
var res *http.Response
|
||||||
|
err = runWithRetry(ctx, func() error {
|
||||||
|
res, err = o.c.hc.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if res.StatusCode == http.StatusNotFound {
|
||||||
|
res.Body.Close()
|
||||||
|
return ErrObjectNotExist
|
||||||
|
}
|
||||||
|
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||||
|
body, _ := ioutil.ReadAll(res.Body)
|
||||||
|
res.Body.Close()
|
||||||
|
return &googleapi.Error{
|
||||||
|
Code: res.StatusCode,
|
||||||
|
Header: res.Header,
|
||||||
|
Body: string(body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if start > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
|
||||||
|
res.Body.Close()
|
||||||
|
return errors.New("storage: partial request not satisfied")
|
||||||
|
}
|
||||||
|
// If a generation hasn't been specified, and this is the first response we get, let's record the
|
||||||
|
// generation. In future requests we'll use this generation as a precondition to avoid data races.
|
||||||
|
if gen < 0 && res.Header.Get("X-Goog-Generation") != "" {
|
||||||
|
gen64, err := strconv.ParseInt(res.Header.Get("X-Goog-Generation"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gen = gen64
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := reopen(0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
size int64 // total size of object, even if a range was requested.
|
||||||
|
checkCRC bool
|
||||||
|
crc uint32
|
||||||
|
startOffset int64 // non-zero if range request.
|
||||||
|
)
|
||||||
|
if res.StatusCode == http.StatusPartialContent {
|
||||||
|
cr := strings.TrimSpace(res.Header.Get("Content-Range"))
|
||||||
|
if !strings.HasPrefix(cr, "bytes ") || !strings.Contains(cr, "/") {
|
||||||
|
return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
|
||||||
|
}
|
||||||
|
size, err = strconv.ParseInt(cr[strings.LastIndex(cr, "/")+1:], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
|
||||||
|
}
|
||||||
|
|
||||||
|
dashIndex := strings.Index(cr, "-")
|
||||||
|
if dashIndex >= 0 {
|
||||||
|
startOffset, err = strconv.ParseInt(cr[len("bytes="):dashIndex], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("storage: invalid Content-Range %q: %v", cr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size = res.ContentLength
|
||||||
|
// Check the CRC iff all of the following hold:
|
||||||
|
// - We asked for content (length != 0).
|
||||||
|
// - We got all the content (status != PartialContent).
|
||||||
|
// - The server sent a CRC header.
|
||||||
|
// - The Go http stack did not uncompress the file.
|
||||||
|
// - We were not served compressed data that was uncompressed on download.
|
||||||
|
// The problem with the last two cases is that the CRC will not match -- GCS
|
||||||
|
// computes it on the compressed contents, but we compute it on the
|
||||||
|
// uncompressed contents.
|
||||||
|
if length != 0 && !res.Uncompressed && !uncompressedByServer(res) {
|
||||||
|
crc, checkCRC = parseCRC32c(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remain := res.ContentLength
|
||||||
|
body := res.Body
|
||||||
|
if length == 0 {
|
||||||
|
remain = 0
|
||||||
|
body.Close()
|
||||||
|
body = emptyBody
|
||||||
|
}
|
||||||
|
var metaGen int64
|
||||||
|
if res.Header.Get("X-Goog-Generation") != "" {
|
||||||
|
metaGen, err = strconv.ParseInt(res.Header.Get("X-Goog-Metageneration"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lm time.Time
|
||||||
|
if res.Header.Get("Last-Modified") != "" {
|
||||||
|
lm, err = http.ParseTime(res.Header.Get("Last-Modified"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs := ReaderObjectAttrs{
|
||||||
|
Size: size,
|
||||||
|
ContentType: res.Header.Get("Content-Type"),
|
||||||
|
ContentEncoding: res.Header.Get("Content-Encoding"),
|
||||||
|
CacheControl: res.Header.Get("Cache-Control"),
|
||||||
|
LastModified: lm,
|
||||||
|
StartOffset: startOffset,
|
||||||
|
Generation: gen,
|
||||||
|
Metageneration: metaGen,
|
||||||
|
}
|
||||||
|
return &Reader{
|
||||||
|
Attrs: attrs,
|
||||||
|
body: body,
|
||||||
|
size: size,
|
||||||
|
remain: remain,
|
||||||
|
wantCRC: crc,
|
||||||
|
checkCRC: checkCRC,
|
||||||
|
reopen: reopen,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uncompressedByServer(res *http.Response) bool {
|
||||||
|
// If the data is stored as gzip but is not encoded as gzip, then it
|
||||||
|
// was uncompressed by the server.
|
||||||
|
return res.Header.Get("X-Goog-Stored-Content-Encoding") == "gzip" &&
|
||||||
|
res.Header.Get("Content-Encoding") != "gzip"
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCRC32c(res *http.Response) (uint32, bool) {
|
||||||
|
const prefix = "crc32c="
|
||||||
|
for _, spec := range res.Header["X-Goog-Hash"] {
|
||||||
|
if strings.HasPrefix(spec, prefix) {
|
||||||
|
c, err := decodeUint32(spec[len(prefix):])
|
||||||
|
if err == nil {
|
||||||
|
return c, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var emptyBody = ioutil.NopCloser(strings.NewReader(""))
|
||||||
|
|
||||||
|
// Reader reads a Cloud Storage object.
|
||||||
|
// It implements io.Reader.
|
||||||
|
//
|
||||||
|
// Typically, a Reader computes the CRC of the downloaded content and compares it to
|
||||||
|
// the stored CRC, returning an error from Read if there is a mismatch. This integrity check
|
||||||
|
// is skipped if transcoding occurs. See https://cloud.google.com/storage/docs/transcoding.
|
||||||
|
type Reader struct {
|
||||||
|
Attrs ReaderObjectAttrs
|
||||||
|
body io.ReadCloser
|
||||||
|
seen, remain, size int64
|
||||||
|
checkCRC bool // should we check the CRC?
|
||||||
|
wantCRC uint32 // the CRC32c value the server sent in the header
|
||||||
|
gotCRC uint32 // running crc
|
||||||
|
reopen func(seen int64) (*http.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the Reader. It must be called when done reading.
|
||||||
|
func (r *Reader) Close() error {
|
||||||
|
return r.body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) Read(p []byte) (int, error) {
|
||||||
|
n, err := r.readWithRetry(p)
|
||||||
|
if r.remain != -1 {
|
||||||
|
r.remain -= int64(n)
|
||||||
|
}
|
||||||
|
if r.checkCRC {
|
||||||
|
r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, p[:n])
|
||||||
|
// Check CRC here. It would be natural to check it in Close, but
|
||||||
|
// everybody defers Close on the assumption that it doesn't return
|
||||||
|
// anything worth looking at.
|
||||||
|
if err == io.EOF {
|
||||||
|
if r.gotCRC != r.wantCRC {
|
||||||
|
return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
|
||||||
|
r.gotCRC, r.wantCRC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) readWithRetry(p []byte) (int, error) {
|
||||||
|
n := 0
|
||||||
|
for len(p[n:]) > 0 {
|
||||||
|
m, err := r.body.Read(p[n:])
|
||||||
|
n += m
|
||||||
|
r.seen += int64(m)
|
||||||
|
if !shouldRetryRead(err) {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
// Read failed, but we will try again. Send a ranged read request that takes
|
||||||
|
// into account the number of bytes we've already seen.
|
||||||
|
res, err := r.reopen(r.seen)
|
||||||
|
if err != nil {
|
||||||
|
// reopen already retries
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
r.body.Close()
|
||||||
|
r.body = res.Body
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldRetryRead(err error) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.HasSuffix(err.Error(), "INTERNAL_ERROR") && strings.Contains(reflect.TypeOf(err).String(), "http2")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the size of the object in bytes.
|
||||||
|
// The returned value is always the same and is not affected by
|
||||||
|
// calls to Read or Close.
|
||||||
|
//
|
||||||
|
// Deprecated: use Reader.Attrs.Size.
|
||||||
|
func (r *Reader) Size() int64 {
|
||||||
|
return r.Attrs.Size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remain returns the number of bytes left to read, or -1 if unknown.
|
||||||
|
func (r *Reader) Remain() int64 {
|
||||||
|
return r.remain
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentType returns the content type of the object.
|
||||||
|
//
|
||||||
|
// Deprecated: use Reader.Attrs.ContentType.
|
||||||
|
func (r *Reader) ContentType() string {
|
||||||
|
return r.Attrs.ContentType
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentEncoding returns the content encoding of the object.
|
||||||
|
//
|
||||||
|
// Deprecated: use Reader.Attrs.ContentEncoding.
|
||||||
|
func (r *Reader) ContentEncoding() string {
|
||||||
|
return r.Attrs.ContentEncoding
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheControl returns the cache control of the object.
|
||||||
|
//
|
||||||
|
// Deprecated: use Reader.Attrs.CacheControl.
|
||||||
|
func (r *Reader) CacheControl() string {
|
||||||
|
return r.Attrs.CacheControl
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastModified returns the value of the Last-Modified header.
|
||||||
|
//
|
||||||
|
// Deprecated: use Reader.Attrs.LastModified.
|
||||||
|
func (r *Reader) LastModified() (time.Time, error) {
|
||||||
|
return r.Attrs.LastModified, nil
|
||||||
|
}
|
1369
vendor/cloud.google.com/go/storage/storage.go
generated
vendored
Normal file
1369
vendor/cloud.google.com/go/storage/storage.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
30067
vendor/cloud.google.com/go/storage/storage.replay
generated
vendored
Normal file
30067
vendor/cloud.google.com/go/storage/storage.replay
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
260
vendor/cloud.google.com/go/storage/writer.go
generated
vendored
Normal file
260
vendor/cloud.google.com/go/storage/writer.go
generated
vendored
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
// Copyright 2014 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
raw "google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Writer writes a Cloud Storage object.
|
||||||
|
type Writer struct {
|
||||||
|
// ObjectAttrs are optional attributes to set on the object. Any attributes
|
||||||
|
// must be initialized before the first Write call. Nil or zero-valued
|
||||||
|
// attributes are ignored.
|
||||||
|
ObjectAttrs
|
||||||
|
|
||||||
|
// SendCRC specifies whether to transmit a CRC32C field. It should be set
|
||||||
|
// to true in addition to setting the Writer's CRC32C field, because zero
|
||||||
|
// is a valid CRC and normally a zero would not be transmitted.
|
||||||
|
// If a CRC32C is sent, and the data written does not match the checksum,
|
||||||
|
// the write will be rejected.
|
||||||
|
SendCRC32C bool
|
||||||
|
|
||||||
|
// ChunkSize controls the maximum number of bytes of the object that the
|
||||||
|
// Writer will attempt to send to the server in a single request. Objects
|
||||||
|
// smaller than the size will be sent in a single request, while larger
|
||||||
|
// objects will be split over multiple requests. The size will be rounded up
|
||||||
|
// to the nearest multiple of 256K. If zero, chunking will be disabled and
|
||||||
|
// the object will be uploaded in a single request.
|
||||||
|
//
|
||||||
|
// ChunkSize will default to a reasonable value. If you perform many concurrent
|
||||||
|
// writes of small objects, you may wish set ChunkSize to a value that matches
|
||||||
|
// your objects' sizes to avoid consuming large amounts of memory.
|
||||||
|
//
|
||||||
|
// ChunkSize must be set before the first Write call.
|
||||||
|
ChunkSize int
|
||||||
|
|
||||||
|
// ProgressFunc can be used to monitor the progress of a large write.
|
||||||
|
// operation. If ProgressFunc is not nil and writing requires multiple
|
||||||
|
// calls to the underlying service (see
|
||||||
|
// https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload),
|
||||||
|
// then ProgressFunc will be invoked after each call with the number of bytes of
|
||||||
|
// content copied so far.
|
||||||
|
//
|
||||||
|
// ProgressFunc should return quickly without blocking.
|
||||||
|
ProgressFunc func(int64)
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
o *ObjectHandle
|
||||||
|
|
||||||
|
opened bool
|
||||||
|
pw *io.PipeWriter
|
||||||
|
|
||||||
|
donec chan struct{} // closed after err and obj are set.
|
||||||
|
obj *ObjectAttrs
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) open() error {
|
||||||
|
attrs := w.ObjectAttrs
|
||||||
|
// Check the developer didn't change the object Name (this is unfortunate, but
|
||||||
|
// we don't want to store an object under the wrong name).
|
||||||
|
if attrs.Name != w.o.object {
|
||||||
|
return fmt.Errorf("storage: Writer.Name %q does not match object name %q", attrs.Name, w.o.object)
|
||||||
|
}
|
||||||
|
if !utf8.ValidString(attrs.Name) {
|
||||||
|
return fmt.Errorf("storage: object name %q is not valid UTF-8", attrs.Name)
|
||||||
|
}
|
||||||
|
if attrs.KMSKeyName != "" && w.o.encryptionKey != nil {
|
||||||
|
return errors.New("storage: cannot use KMSKeyName with a customer-supplied encryption key")
|
||||||
|
}
|
||||||
|
pr, pw := io.Pipe()
|
||||||
|
w.pw = pw
|
||||||
|
w.opened = true
|
||||||
|
|
||||||
|
go w.monitorCancel()
|
||||||
|
|
||||||
|
if w.ChunkSize < 0 {
|
||||||
|
return errors.New("storage: Writer.ChunkSize must be non-negative")
|
||||||
|
}
|
||||||
|
mediaOpts := []googleapi.MediaOption{
|
||||||
|
googleapi.ChunkSize(w.ChunkSize),
|
||||||
|
}
|
||||||
|
if c := attrs.ContentType; c != "" {
|
||||||
|
mediaOpts = append(mediaOpts, googleapi.ContentType(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(w.donec)
|
||||||
|
|
||||||
|
rawObj := attrs.toRawObject(w.o.bucket)
|
||||||
|
if w.SendCRC32C {
|
||||||
|
rawObj.Crc32c = encodeUint32(attrs.CRC32C)
|
||||||
|
}
|
||||||
|
if w.MD5 != nil {
|
||||||
|
rawObj.Md5Hash = base64.StdEncoding.EncodeToString(w.MD5)
|
||||||
|
}
|
||||||
|
if w.o.c.envHost != "" {
|
||||||
|
w.o.c.raw.BasePath = fmt.Sprintf("%s://%s", w.o.c.scheme, w.o.c.envHost)
|
||||||
|
}
|
||||||
|
call := w.o.c.raw.Objects.Insert(w.o.bucket, rawObj).
|
||||||
|
Media(pr, mediaOpts...).
|
||||||
|
Projection("full").
|
||||||
|
Context(w.ctx)
|
||||||
|
|
||||||
|
if w.ProgressFunc != nil {
|
||||||
|
call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
|
||||||
|
}
|
||||||
|
if attrs.KMSKeyName != "" {
|
||||||
|
call.KmsKeyName(attrs.KMSKeyName)
|
||||||
|
}
|
||||||
|
if attrs.PredefinedACL != "" {
|
||||||
|
call.PredefinedAcl(attrs.PredefinedACL)
|
||||||
|
}
|
||||||
|
if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
|
||||||
|
w.mu.Lock()
|
||||||
|
w.err = err
|
||||||
|
w.mu.Unlock()
|
||||||
|
pr.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var resp *raw.Object
|
||||||
|
err := applyConds("NewWriter", w.o.gen, w.o.conds, call)
|
||||||
|
if err == nil {
|
||||||
|
if w.o.userProject != "" {
|
||||||
|
call.UserProject(w.o.userProject)
|
||||||
|
}
|
||||||
|
setClientHeader(call.Header())
|
||||||
|
|
||||||
|
// The internals that perform call.Do automatically retry
|
||||||
|
// uploading chunks, hence no need to add retries here.
|
||||||
|
// See issue https://github.com/googleapis/google-cloud-go/issues/1507.
|
||||||
|
//
|
||||||
|
// However, since this whole call's internals involve making the initial
|
||||||
|
// resumable upload session, the first HTTP request is not retried.
|
||||||
|
// TODO: Follow-up with google.golang.org/gensupport to solve
|
||||||
|
// https://github.com/googleapis/google-api-go-client/issues/392.
|
||||||
|
resp, err = call.Do()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
w.mu.Lock()
|
||||||
|
w.err = err
|
||||||
|
w.mu.Unlock()
|
||||||
|
pr.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.obj = newObject(resp)
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write appends to w. It implements the io.Writer interface.
|
||||||
|
//
|
||||||
|
// Since writes happen asynchronously, Write may return a nil
|
||||||
|
// error even though the write failed (or will fail). Always
|
||||||
|
// use the error returned from Writer.Close to determine if
|
||||||
|
// the upload was successful.
|
||||||
|
func (w *Writer) Write(p []byte) (n int, err error) {
|
||||||
|
w.mu.Lock()
|
||||||
|
werr := w.err
|
||||||
|
w.mu.Unlock()
|
||||||
|
if werr != nil {
|
||||||
|
return 0, werr
|
||||||
|
}
|
||||||
|
if !w.opened {
|
||||||
|
if err := w.open(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n, err = w.pw.Write(p)
|
||||||
|
if err != nil {
|
||||||
|
w.mu.Lock()
|
||||||
|
werr := w.err
|
||||||
|
w.mu.Unlock()
|
||||||
|
// Preserve existing functionality that when context is canceled, Write will return
|
||||||
|
// context.Canceled instead of "io: read/write on closed pipe". This hides the
|
||||||
|
// pipe implementation detail from users and makes Write seem as though it's an RPC.
|
||||||
|
if werr == context.Canceled || werr == context.DeadlineExceeded {
|
||||||
|
return n, werr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close completes the write operation and flushes any buffered data.
|
||||||
|
// If Close doesn't return an error, metadata about the written object
|
||||||
|
// can be retrieved by calling Attrs.
|
||||||
|
func (w *Writer) Close() error {
|
||||||
|
if !w.opened {
|
||||||
|
if err := w.open(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closing either the read or write causes the entire pipe to close.
|
||||||
|
if err := w.pw.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
<-w.donec
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
return w.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// monitorCancel is intended to be used as a background goroutine. It monitors the
|
||||||
|
// context, and when it observes that the context has been canceled, it manually
|
||||||
|
// closes things that do not take a context.
|
||||||
|
func (w *Writer) monitorCancel() {
|
||||||
|
select {
|
||||||
|
case <-w.ctx.Done():
|
||||||
|
w.mu.Lock()
|
||||||
|
werr := w.ctx.Err()
|
||||||
|
w.err = werr
|
||||||
|
w.mu.Unlock()
|
||||||
|
|
||||||
|
// Closing either the read or write causes the entire pipe to close.
|
||||||
|
w.CloseWithError(werr)
|
||||||
|
case <-w.donec:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseWithError aborts the write operation with the provided error.
|
||||||
|
// CloseWithError always returns nil.
|
||||||
|
//
|
||||||
|
// Deprecated: cancel the context passed to NewWriter instead.
|
||||||
|
func (w *Writer) CloseWithError(err error) error {
|
||||||
|
if !w.opened {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return w.pw.CloseWithError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attrs returns metadata about a successfully-written object.
|
||||||
|
// It's only valid to call it after Close returns nil.
|
||||||
|
func (w *Writer) Attrs() *ObjectAttrs {
|
||||||
|
return w.obj
|
||||||
|
}
|
20
vendor/code.gitea.io/sdk/gitea/LICENSE
generated
vendored
Normal file
20
vendor/code.gitea.io/sdk/gitea/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2016 The Gitea Authors
|
||||||
|
Copyright (c) 2014 The Gogs Authors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
47
vendor/code.gitea.io/sdk/gitea/admin_cron.go
generated
vendored
Normal file
47
vendor/code.gitea.io/sdk/gitea/admin_cron.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CronTask represents a Cron task
|
||||||
|
type CronTask struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Schedule string `json:"schedule"`
|
||||||
|
Next time.Time `json:"next"`
|
||||||
|
Prev time.Time `json:"prev"`
|
||||||
|
ExecTimes int64 `json:"exec_times"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCronTaskOptions list options for ListCronTasks
|
||||||
|
type ListCronTaskOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCronTasks list available cron tasks
|
||||||
|
func (c *Client) ListCronTasks(opt ListCronTaskOptions) ([]*CronTask, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
ct := make([]*CronTask, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/cron?%s", opt.getURLQuery().Encode()), jsonHeader, nil, &ct)
|
||||||
|
return ct, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunCronTasks run a cron task
|
||||||
|
func (c *Client) RunCronTasks(task string) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&task); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
39
vendor/code.gitea.io/sdk/gitea/admin_org.go
generated
vendored
Normal file
39
vendor/code.gitea.io/sdk/gitea/admin_org.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminListOrgsOptions options for listing admin's organizations
|
||||||
|
type AdminListOrgsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminListOrgs lists all orgs
|
||||||
|
func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
orgs := make([]*Organization, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||||
|
return orgs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminCreateOrg create an organization
|
||||||
|
func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
org := new(Organization)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user), jsonHeader, bytes.NewReader(body), org)
|
||||||
|
return org, resp, err
|
||||||
|
}
|
25
vendor/code.gitea.io/sdk/gitea/admin_repo.go
generated
vendored
Normal file
25
vendor/code.gitea.io/sdk/gitea/admin_repo.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminCreateRepo create a repo
|
||||||
|
func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
130
vendor/code.gitea.io/sdk/gitea/admin_user.go
generated
vendored
Normal file
130
vendor/code.gitea.io/sdk/gitea/admin_user.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AdminListUsersOptions options for listing admin users
|
||||||
|
type AdminListUsersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminListUsers lists all users
|
||||||
|
func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateUserOption create user options
|
||||||
|
type CreateUserOption struct {
|
||||||
|
SourceID int64 `json:"source_id"`
|
||||||
|
LoginName string `json:"login_name"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
MustChangePassword *bool `json:"must_change_password"`
|
||||||
|
SendNotify bool `json:"send_notify"`
|
||||||
|
Visibility *VisibleType `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateUserOption struct
|
||||||
|
func (opt CreateUserOption) Validate() error {
|
||||||
|
if len(opt.Email) == 0 {
|
||||||
|
return fmt.Errorf("email is empty")
|
||||||
|
}
|
||||||
|
if len(opt.Username) == 0 {
|
||||||
|
return fmt.Errorf("username is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminCreateUser create a user
|
||||||
|
func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, *Response, error) {
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
user := new(User)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user)
|
||||||
|
return user, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditUserOption edit user options
|
||||||
|
type EditUserOption struct {
|
||||||
|
SourceID int64 `json:"source_id"`
|
||||||
|
LoginName string `json:"login_name"`
|
||||||
|
Email *string `json:"email"`
|
||||||
|
FullName *string `json:"full_name"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
MustChangePassword *bool `json:"must_change_password"`
|
||||||
|
Website *string `json:"website"`
|
||||||
|
Location *string `json:"location"`
|
||||||
|
Active *bool `json:"active"`
|
||||||
|
Admin *bool `json:"admin"`
|
||||||
|
AllowGitHook *bool `json:"allow_git_hook"`
|
||||||
|
AllowImportLocal *bool `json:"allow_import_local"`
|
||||||
|
MaxRepoCreation *int `json:"max_repo_creation"`
|
||||||
|
ProhibitLogin *bool `json:"prohibit_login"`
|
||||||
|
AllowCreateOrganization *bool `json:"allow_create_organization"`
|
||||||
|
Restricted *bool `json:"restricted"`
|
||||||
|
Visibility *VisibleType `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminEditUser modify user informations
|
||||||
|
func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminDeleteUser delete one user according name
|
||||||
|
func (c *Client) AdminDeleteUser(user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminCreateUserPublicKey adds a public key for the user
|
||||||
|
func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(PublicKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdminDeleteUserPublicKey deletes a user's public key
|
||||||
|
func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
111
vendor/code.gitea.io/sdk/gitea/attachment.go
generated
vendored
Normal file
111
vendor/code.gitea.io/sdk/gitea/attachment.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea // import "code.gitea.io/sdk/gitea"
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Attachment a generic attachment
|
||||||
|
type Attachment struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
DownloadCount int64 `json:"download_count"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
DownloadURL string `json:"browser_download_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleaseAttachmentsOptions options for listing release's attachments
|
||||||
|
type ListReleaseAttachmentsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleaseAttachments list release's attachments
|
||||||
|
func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
attachments := make([]*Attachment, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d/assets?%s", user, repo, release, opt.getURLQuery().Encode()),
|
||||||
|
nil, nil, &attachments)
|
||||||
|
return attachments, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReleaseAttachment returns the requested attachment
|
||||||
|
func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
a := new(Attachment)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id),
|
||||||
|
nil, nil, &a)
|
||||||
|
return a, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReleaseAttachment creates an attachment for the given release
|
||||||
|
func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
// Write file to body
|
||||||
|
body := new(bytes.Buffer)
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
part, err := writer.CreateFormFile("attachment", filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = io.Copy(part, file); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err = writer.Close(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
attachment := new(Attachment)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release),
|
||||||
|
http.Header{"Content-Type": {writer.FormDataContentType()}}, body, &attachment)
|
||||||
|
return attachment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditAttachmentOptions options for editing attachments
|
||||||
|
type EditAttachmentOptions struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditReleaseAttachment updates the given attachment with the given options
|
||||||
|
func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
attach := new(Attachment)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, attachment), jsonHeader, bytes.NewReader(body), attach)
|
||||||
|
return attach, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteReleaseAttachment deletes the given attachment including the uploaded file
|
||||||
|
func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
347
vendor/code.gitea.io/sdk/gitea/client.go
generated
vendored
Normal file
347
vendor/code.gitea.io/sdk/gitea/client.go
generated
vendored
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
var jsonHeader = http.Header{"content-type": []string{"application/json"}}
|
||||||
|
|
||||||
|
// Version return the library version
|
||||||
|
func Version() string {
|
||||||
|
return "0.15.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client represents a thread-safe Gitea API client.
|
||||||
|
type Client struct {
|
||||||
|
url string
|
||||||
|
accessToken string
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
otp string
|
||||||
|
sudo string
|
||||||
|
debug bool
|
||||||
|
client *http.Client
|
||||||
|
ctx context.Context
|
||||||
|
mutex sync.RWMutex
|
||||||
|
|
||||||
|
serverVersion *version.Version
|
||||||
|
getVersionOnce sync.Once
|
||||||
|
ignoreVersion bool // only set by SetGiteaVersion so don't need a mutex lock
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response represents the gitea response
|
||||||
|
type Response struct {
|
||||||
|
*http.Response
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientOption are functions used to init a new client
|
||||||
|
type ClientOption func(*Client) error
|
||||||
|
|
||||||
|
// NewClient initializes and returns a API client.
|
||||||
|
// Usage of all gitea.Client methods is concurrency-safe.
|
||||||
|
func NewClient(url string, options ...ClientOption) (*Client, error) {
|
||||||
|
client := &Client{
|
||||||
|
url: strings.TrimSuffix(url, "/"),
|
||||||
|
client: &http.Client{},
|
||||||
|
ctx: context.Background(),
|
||||||
|
}
|
||||||
|
for _, opt := range options {
|
||||||
|
if err := opt(client); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := client.checkServerVersionGreaterThanOrEqual(version1_11_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClientWithHTTP creates an API client with a custom http client
|
||||||
|
// Deprecated use SetHTTPClient option
|
||||||
|
func NewClientWithHTTP(url string, httpClient *http.Client) *Client {
|
||||||
|
client, _ := NewClient(url, SetHTTPClient(httpClient))
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHTTPClient is an option for NewClient to set custom http client
|
||||||
|
func SetHTTPClient(httpClient *http.Client) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetHTTPClient(httpClient)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHTTPClient replaces default http.Client with user given one.
|
||||||
|
func (c *Client) SetHTTPClient(client *http.Client) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.client = client
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetToken is an option for NewClient to set token
|
||||||
|
func SetToken(token string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.mutex.Lock()
|
||||||
|
client.accessToken = token
|
||||||
|
client.mutex.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBasicAuth is an option for NewClient to set username and password
|
||||||
|
func SetBasicAuth(username, password string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetBasicAuth(username, password)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBasicAuth sets username and password
|
||||||
|
func (c *Client) SetBasicAuth(username, password string) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.username, c.password = username, password
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOTP is an option for NewClient to set OTP for 2FA
|
||||||
|
func SetOTP(otp string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetOTP(otp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOTP sets OTP for 2FA
|
||||||
|
func (c *Client) SetOTP(otp string) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.otp = otp
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContext is an option for NewClient to set the default context
|
||||||
|
func SetContext(ctx context.Context) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetContext(ctx)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContext set default context witch is used for http requests
|
||||||
|
func (c *Client) SetContext(ctx context.Context) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.ctx = ctx
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSudo is an option for NewClient to set sudo header
|
||||||
|
func SetSudo(sudo string) ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.SetSudo(sudo)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSudo sets username to impersonate.
|
||||||
|
func (c *Client) SetSudo(sudo string) {
|
||||||
|
c.mutex.Lock()
|
||||||
|
c.sudo = sudo
|
||||||
|
c.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDebugMode is an option for NewClient to enable debug mode
|
||||||
|
func SetDebugMode() ClientOption {
|
||||||
|
return func(client *Client) error {
|
||||||
|
client.mutex.Lock()
|
||||||
|
client.debug = true
|
||||||
|
client.mutex.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
debug := c.debug
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("%s: %s\nBody: %v\n", method, c.url+path, body)
|
||||||
|
}
|
||||||
|
req, err := http.NewRequestWithContext(c.ctx, method, c.url+path, body)
|
||||||
|
|
||||||
|
client := c.client // client ref can change from this point on so safe it
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("Response: %v\n\n", resp)
|
||||||
|
}
|
||||||
|
return data, &Response{resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
debug := c.debug
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("%s: %s\nHeader: %v\nBody: %s\n", method, c.url+"/api/v1"+path, header, body)
|
||||||
|
}
|
||||||
|
req, err := http.NewRequestWithContext(c.ctx, method, c.url+"/api/v1"+path, body)
|
||||||
|
if err != nil {
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(c.accessToken) != 0 {
|
||||||
|
req.Header.Set("Authorization", "token "+c.accessToken)
|
||||||
|
}
|
||||||
|
if len(c.otp) != 0 {
|
||||||
|
req.Header.Set("X-GITEA-OTP", c.otp)
|
||||||
|
}
|
||||||
|
if len(c.username) != 0 {
|
||||||
|
req.SetBasicAuth(c.username, c.password)
|
||||||
|
}
|
||||||
|
if len(c.sudo) != 0 {
|
||||||
|
req.Header.Set("Sudo", c.sudo)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := c.client // client ref can change from this point on so safe it
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
|
||||||
|
for k, v := range header {
|
||||||
|
req.Header[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if debug {
|
||||||
|
fmt.Printf("Response: %v\n\n", resp)
|
||||||
|
}
|
||||||
|
return &Response{resp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a response for a HTTP status code indicating an error condition
|
||||||
|
// (non-2XX) to a well-known error value and response body. For non-problematic
|
||||||
|
// (2XX) status codes nil will be returned. Note that on a non-2XX response, the
|
||||||
|
// response body stream will have been read and, hence, is closed on return.
|
||||||
|
func statusCodeToErr(resp *Response) (body []byte, err error) {
|
||||||
|
// no error
|
||||||
|
if resp.StatusCode/100 == 2 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// error: body will be read for details
|
||||||
|
//
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case 403:
|
||||||
|
return data, errors.New("403 Forbidden")
|
||||||
|
case 404:
|
||||||
|
return data, errors.New("404 Not Found")
|
||||||
|
case 409:
|
||||||
|
return data, errors.New("409 Conflict")
|
||||||
|
case 422:
|
||||||
|
return data, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
path := resp.Request.URL.Path
|
||||||
|
method := resp.Request.Method
|
||||||
|
header := resp.Request.Header
|
||||||
|
errMap := make(map[string]interface{})
|
||||||
|
if err = json.Unmarshal(data, &errMap); err != nil {
|
||||||
|
// when the JSON can't be parsed, data was probably empty or a
|
||||||
|
// plain string, so we try to return a helpful error anyway
|
||||||
|
return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
|
||||||
|
}
|
||||||
|
return data, errors.New(errMap["message"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) {
|
||||||
|
resp, err := c.doRequest(method, path, header, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
data, err := statusCodeToErr(resp)
|
||||||
|
if err != nil {
|
||||||
|
return data, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// success (2XX), read body
|
||||||
|
data, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) (*Response, error) {
|
||||||
|
data, resp, err := c.getResponse(method, path, header, body)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
return resp, json.Unmarshal(data, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getStatusCode(method, path string, header http.Header, body io.Reader) (int, *Response, error) {
|
||||||
|
resp, err := c.doRequest(method, path, header, body)
|
||||||
|
if err != nil {
|
||||||
|
return -1, resp, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return resp.StatusCode, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pathEscapeSegments escapes segments of a path while not escaping forward slash
|
||||||
|
func pathEscapeSegments(path string) string {
|
||||||
|
slice := strings.Split(path, "/")
|
||||||
|
for index := range slice {
|
||||||
|
slice[index] = url.PathEscape(slice[index])
|
||||||
|
}
|
||||||
|
escapedPath := strings.Join(slice, "/")
|
||||||
|
return escapedPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// escapeValidatePathSegments is a help function to validate and encode url path segments
|
||||||
|
func escapeValidatePathSegments(seg ...*string) error {
|
||||||
|
for i := range seg {
|
||||||
|
if seg[i] == nil || len(*seg[i]) == 0 {
|
||||||
|
return fmt.Errorf("path segment [%d] is empty", i)
|
||||||
|
}
|
||||||
|
*seg[i] = url.PathEscape(*seg[i])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
5
vendor/code.gitea.io/sdk/gitea/doc.go
generated
vendored
Normal file
5
vendor/code.gitea.io/sdk/gitea/doc.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea // import "code.gitea.io/sdk/gitea"
|
49
vendor/code.gitea.io/sdk/gitea/fork.go
generated
vendored
Normal file
49
vendor/code.gitea.io/sdk/gitea/fork.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListForksOptions options for listing repository's forks
|
||||||
|
type ListForksOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListForks list a repository's forks
|
||||||
|
func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
forks := make([]*Repository, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/forks?%s", user, repo, opt.getURLQuery().Encode()),
|
||||||
|
nil, nil, &forks)
|
||||||
|
return forks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateForkOption options for creating a fork
|
||||||
|
type CreateForkOption struct {
|
||||||
|
// organization name, if forking into an organization
|
||||||
|
Organization *string `json:"organization"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFork create a fork of a repository
|
||||||
|
func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
fork := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/forks", user, repo), jsonHeader, bytes.NewReader(body), &fork)
|
||||||
|
return fork, resp, err
|
||||||
|
}
|
28
vendor/code.gitea.io/sdk/gitea/git_blob.go
generated
vendored
Normal file
28
vendor/code.gitea.io/sdk/gitea/git_blob.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitBlobResponse represents a git blob
|
||||||
|
type GitBlobResponse struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
Encoding string `json:"encoding"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlob get the blob of a repository file
|
||||||
|
func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
blob := new(GitBlobResponse)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob)
|
||||||
|
return blob, resp, err
|
||||||
|
}
|
71
vendor/code.gitea.io/sdk/gitea/git_hook.go
generated
vendored
Normal file
71
vendor/code.gitea.io/sdk/gitea/git_hook.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitHook represents a Git repository hook
|
||||||
|
type GitHook struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
IsActive bool `json:"is_active"`
|
||||||
|
Content string `json:"content,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoGitHooksOptions options for listing repository's githooks
|
||||||
|
type ListRepoGitHooksOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoGitHooks list all the Git hooks of one repository
|
||||||
|
func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
hooks := make([]*GitHook, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||||
|
return hooks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoGitHook get a Git hook of a repository
|
||||||
|
func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(GitHook)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditGitHookOption options when modifying one Git hook
|
||||||
|
type EditGitHookOption struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepoGitHook modify one Git hook of a repository
|
||||||
|
func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoGitHook delete one Git hook from a repository
|
||||||
|
func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
20
vendor/code.gitea.io/sdk/gitea/helper.go
generated
vendored
Normal file
20
vendor/code.gitea.io/sdk/gitea/helper.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
// OptionalBool convert a bool to a bool reference
|
||||||
|
func OptionalBool(v bool) *bool {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionalString convert a string to a string reference
|
||||||
|
func OptionalString(v string) *string {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// OptionalInt64 convert a int64 to a int64 reference
|
||||||
|
func OptionalInt64(v int64) *int64 {
|
||||||
|
return &v
|
||||||
|
}
|
194
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
Normal file
194
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hook a hook is a web hook when one repository changed
|
||||||
|
type Hook struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"-"`
|
||||||
|
Config map[string]string `json:"config"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HookType represent all webhook types gitea currently offer
|
||||||
|
type HookType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// HookTypeDingtalk webhook that dingtalk understand
|
||||||
|
HookTypeDingtalk HookType = "dingtalk"
|
||||||
|
// HookTypeDiscord webhook that discord understand
|
||||||
|
HookTypeDiscord HookType = "discord"
|
||||||
|
// HookTypeGitea webhook that gitea understand
|
||||||
|
HookTypeGitea HookType = "gitea"
|
||||||
|
// HookTypeGogs webhook that gogs understand
|
||||||
|
HookTypeGogs HookType = "gogs"
|
||||||
|
// HookTypeMsteams webhook that msteams understand
|
||||||
|
HookTypeMsteams HookType = "msteams"
|
||||||
|
// HookTypeSlack webhook that slack understand
|
||||||
|
HookTypeSlack HookType = "slack"
|
||||||
|
// HookTypeTelegram webhook that telegram understand
|
||||||
|
HookTypeTelegram HookType = "telegram"
|
||||||
|
// HookTypeFeishu webhook that feishu understand
|
||||||
|
HookTypeFeishu HookType = "feishu"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListHooksOptions options for listing hooks
|
||||||
|
type ListHooksOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgHooks list all the hooks of one organization
|
||||||
|
func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
hooks := make([]*Hook, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||||
|
return hooks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoHooks list all the hooks of one repository
|
||||||
|
func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
hooks := make([]*Hook, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||||
|
return hooks, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrgHook get a hook of an organization
|
||||||
|
func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoHook get a hook of a repository
|
||||||
|
func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHookOption options when create a hook
|
||||||
|
type CreateHookOption struct {
|
||||||
|
Type HookType `json:"type"`
|
||||||
|
Config map[string]string `json:"config"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
BranchFilter string `json:"branch_filter"`
|
||||||
|
Active bool `json:"active"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateHookOption struct
|
||||||
|
func (opt CreateHookOption) Validate() error {
|
||||||
|
if len(opt.Type) == 0 {
|
||||||
|
return fmt.Errorf("hook type needed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrgHook create one hook for an organization, with options
|
||||||
|
func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/hooks", org), jsonHeader, bytes.NewReader(body), h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepoHook create one hook for a repository, with options
|
||||||
|
func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
h := new(Hook)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h)
|
||||||
|
return h, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditHookOption options when modify one hook
|
||||||
|
type EditHookOption struct {
|
||||||
|
Config map[string]string `json:"config"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
BranchFilter string `json:"branch_filter"`
|
||||||
|
Active *bool `json:"active"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditOrgHook modify one hook of an organization, with hook id and options
|
||||||
|
func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepoHook modify one hook of a repository, with hook id and options
|
||||||
|
func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrgHook delete one hook from an organization, with hook id
|
||||||
|
func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoHook delete one hook from a repository, with hook id
|
||||||
|
func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
288
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
Normal file
288
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PullRequestMeta PR info if an issue is a PR
|
||||||
|
type PullRequestMeta struct {
|
||||||
|
HasMerged bool `json:"merged"`
|
||||||
|
Merged *time.Time `json:"merged_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepositoryMeta basic repository information
|
||||||
|
type RepositoryMeta struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue represents an issue in a repository
|
||||||
|
type Issue struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
Index int64 `json:"number"`
|
||||||
|
Poster *User `json:"user"`
|
||||||
|
OriginalAuthor string `json:"original_author"`
|
||||||
|
OriginalAuthorID int64 `json:"original_author_id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Labels []*Label `json:"labels"`
|
||||||
|
Milestone *Milestone `json:"milestone"`
|
||||||
|
Assignees []*User `json:"assignees"`
|
||||||
|
// Whether the issue is open or closed
|
||||||
|
State StateType `json:"state"`
|
||||||
|
IsLocked bool `json:"is_locked"`
|
||||||
|
Comments int `json:"comments"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
PullRequest *PullRequestMeta `json:"pull_request"`
|
||||||
|
Repository *RepositoryMeta `json:"repository"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueOption list issue options
|
||||||
|
type ListIssueOption struct {
|
||||||
|
ListOptions
|
||||||
|
State StateType
|
||||||
|
Type IssueType
|
||||||
|
Labels []string
|
||||||
|
Milestones []string
|
||||||
|
KeyWord string
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
// filter by created by username
|
||||||
|
CreatedBy string
|
||||||
|
// filter by assigned to username
|
||||||
|
AssignedBy string
|
||||||
|
// filter by username mentioned
|
||||||
|
MentionedBy string
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateType issue state type
|
||||||
|
type StateType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StateOpen pr/issue is opend
|
||||||
|
StateOpen StateType = "open"
|
||||||
|
// StateClosed pr/issue is closed
|
||||||
|
StateClosed StateType = "closed"
|
||||||
|
// StateAll is all
|
||||||
|
StateAll StateType = "all"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IssueType is issue a pull or only an issue
|
||||||
|
type IssueType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// IssueTypeAll pr and issue
|
||||||
|
IssueTypeAll IssueType = ""
|
||||||
|
// IssueTypeIssue only issues
|
||||||
|
IssueTypeIssue IssueType = "issues"
|
||||||
|
// IssueTypePull only pulls
|
||||||
|
IssueTypePull IssueType = "pulls"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListIssueOption) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
|
||||||
|
if len(opt.State) > 0 {
|
||||||
|
query.Add("state", string(opt.State))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.Labels) > 0 {
|
||||||
|
query.Add("labels", strings.Join(opt.Labels, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.KeyWord) > 0 {
|
||||||
|
query.Add("q", opt.KeyWord)
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Add("type", string(opt.Type))
|
||||||
|
|
||||||
|
if len(opt.Milestones) > 0 {
|
||||||
|
query.Add("milestones", strings.Join(opt.Milestones, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.CreatedBy) > 0 {
|
||||||
|
query.Add("created_by", opt.CreatedBy)
|
||||||
|
}
|
||||||
|
if len(opt.AssignedBy) > 0 {
|
||||||
|
query.Add("assigned_by", opt.AssignedBy)
|
||||||
|
}
|
||||||
|
if len(opt.MentionedBy) > 0 {
|
||||||
|
query.Add("mentioned_by", opt.MentionedBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssues returns all issues assigned the authenticated user
|
||||||
|
func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
issues := make([]*Issue, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse("/repos/issues/search")
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
|
||||||
|
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil {
|
||||||
|
for i := 0; i < len(issues); i++ {
|
||||||
|
if issues[i].Repository != nil {
|
||||||
|
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range issues {
|
||||||
|
c.issueBackwardsCompatibility(issues[i])
|
||||||
|
}
|
||||||
|
return issues, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoIssues returns all issues for a given repository
|
||||||
|
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
issues := make([]*Issue, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
|
||||||
|
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil {
|
||||||
|
for i := 0; i < len(issues); i++ {
|
||||||
|
if issues[i].Repository != nil {
|
||||||
|
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range issues {
|
||||||
|
c.issueBackwardsCompatibility(issues[i])
|
||||||
|
}
|
||||||
|
return issues, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssue returns a single issue for a given repository
|
||||||
|
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
issue := new(Issue)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
|
||||||
|
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil && issue.Repository != nil {
|
||||||
|
issue.Repository.Owner = strings.Split(issue.Repository.FullName, "/")[0]
|
||||||
|
}
|
||||||
|
c.issueBackwardsCompatibility(issue)
|
||||||
|
return issue, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueOption options to create one issue
|
||||||
|
type CreateIssueOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
// milestone id
|
||||||
|
Milestone int64 `json:"milestone"`
|
||||||
|
// list of label ids
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
Closed bool `json:"closed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateIssueOption struct
|
||||||
|
func (opt CreateIssueOption) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssue create a new issue for a given repository
|
||||||
|
func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
issue := new(Issue)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), issue)
|
||||||
|
c.issueBackwardsCompatibility(issue)
|
||||||
|
return issue, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssueOption options for editing an issue
|
||||||
|
type EditIssueOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body *string `json:"body"`
|
||||||
|
Ref *string `json:"ref"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Milestone *int64 `json:"milestone"`
|
||||||
|
State *StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
RemoveDeadline *bool `json:"unset_due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditIssueOption struct
|
||||||
|
func (opt EditIssueOption) Validate() error {
|
||||||
|
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssue modify an existing issue for a given repository
|
||||||
|
func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
issue := new(Issue)
|
||||||
|
resp, err := c.getParsedResponse("PATCH",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), issue)
|
||||||
|
c.issueBackwardsCompatibility(issue)
|
||||||
|
return issue, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) issueBackwardsCompatibility(issue *Issue) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
|
||||||
|
c.mutex.RLock()
|
||||||
|
issue.HTMLURL = fmt.Sprintf("%s/%s/issues/%d", c.url, issue.Repository.FullName, issue.Index)
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
154
vendor/code.gitea.io/sdk/gitea/issue_comment.go
generated
vendored
Normal file
154
vendor/code.gitea.io/sdk/gitea/issue_comment.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Comment represents a comment on a commit or issue
|
||||||
|
type Comment struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
PRURL string `json:"pull_request_url"`
|
||||||
|
IssueURL string `json:"issue_url"`
|
||||||
|
Poster *User `json:"user"`
|
||||||
|
OriginalAuthor string `json:"original_author"`
|
||||||
|
OriginalAuthorID int64 `json:"original_author_id"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueCommentOptions list comment options
|
||||||
|
type ListIssueCommentOptions struct {
|
||||||
|
ListOptions
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListIssueCommentOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueComments list comments on an issue.
|
||||||
|
func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
comments := make([]*Comment, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments)
|
||||||
|
return comments, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoIssueComments list comments for a given repo.
|
||||||
|
func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
comments := make([]*Comment, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &comments)
|
||||||
|
return comments, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueComment get a comment for a given repo by id.
|
||||||
|
func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
comment := new(Comment)
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return comment, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, id), nil, nil, &comment)
|
||||||
|
return comment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueCommentOption options for creating a comment on an issue
|
||||||
|
type CreateIssueCommentOption struct {
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateIssueCommentOption struct
|
||||||
|
func (opt CreateIssueCommentOption) Validate() error {
|
||||||
|
if len(opt.Body) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssueComment create comment on an issue.
|
||||||
|
func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
comment := new(Comment)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment)
|
||||||
|
return comment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssueCommentOption options for editing a comment
|
||||||
|
type EditIssueCommentOption struct {
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditIssueCommentOption struct
|
||||||
|
func (opt EditIssueCommentOption) Validate() error {
|
||||||
|
if len(opt.Body) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditIssueComment edits an issue comment.
|
||||||
|
func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
comment := new(Comment)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), jsonHeader, bytes.NewReader(body), comment)
|
||||||
|
return comment, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueComment deletes an issue comment.
|
||||||
|
func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
211
vendor/code.gitea.io/sdk/gitea/issue_label.go
generated
vendored
Normal file
211
vendor/code.gitea.io/sdk/gitea/issue_label.go
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Label a label to an issue or a pr
|
||||||
|
type Label struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
// example: 00aabb
|
||||||
|
Color string `json:"color"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListLabelsOptions options for listing repository's labels
|
||||||
|
type ListLabelsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoLabels list labels of one repository
|
||||||
|
func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
labels := make([]*Label, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoLabel get one label of repository by repo it
|
||||||
|
func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
label := new(Label)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
|
||||||
|
return label, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateLabelOption options for creating a label
|
||||||
|
type CreateLabelOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
// example: #00aabb
|
||||||
|
Color string `json:"color"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateLabelOption struct
|
||||||
|
func (opt CreateLabelOption) Validate() error {
|
||||||
|
aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !aw {
|
||||||
|
return fmt.Errorf("invalid color format")
|
||||||
|
}
|
||||||
|
if len(strings.TrimSpace(opt.Name)) == 0 {
|
||||||
|
return fmt.Errorf("empty name not allowed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateLabel create one label of repository
|
||||||
|
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(opt.Color) == 6 {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
opt.Color = "#" + opt.Color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
label := new(Label)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/labels", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), label)
|
||||||
|
return label, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditLabelOption options for editing a label
|
||||||
|
type EditLabelOption struct {
|
||||||
|
Name *string `json:"name"`
|
||||||
|
Color *string `json:"color"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditLabelOption struct
|
||||||
|
func (opt EditLabelOption) Validate() error {
|
||||||
|
if opt.Color != nil {
|
||||||
|
aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", *opt.Color)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !aw {
|
||||||
|
return fmt.Errorf("invalid color format")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opt.Name != nil {
|
||||||
|
if len(strings.TrimSpace(*opt.Name)) == 0 {
|
||||||
|
return fmt.Errorf("empty name not allowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditLabel modify one label with options
|
||||||
|
func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
label := new(Label)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label)
|
||||||
|
return label, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteLabel delete one label of repository by id
|
||||||
|
func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueLabels get labels of one issue via issue id
|
||||||
|
func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
labels := make([]*Label, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueLabelsOption a collection of labels
|
||||||
|
type IssueLabelsOption struct {
|
||||||
|
// list of label IDs
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIssueLabels add one or more labels to one issue
|
||||||
|
func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var labels []*Label
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceIssueLabels replace old labels of issue with new labels
|
||||||
|
func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var labels []*Label
|
||||||
|
resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
|
||||||
|
return labels, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueLabel delete one label of one issue by issue id and label id
|
||||||
|
// TODO: maybe we need delete by label name and issue id
|
||||||
|
func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearIssueLabels delete all the labels of one issue.
|
||||||
|
func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
237
vendor/code.gitea.io/sdk/gitea/issue_milestone.go
generated
vendored
Normal file
237
vendor/code.gitea.io/sdk/gitea/issue_milestone.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Milestone milestone is a collection of issues on one repository
|
||||||
|
type Milestone struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
State StateType `json:"state"`
|
||||||
|
OpenIssues int `json:"open_issues"`
|
||||||
|
ClosedIssues int `json:"closed_issues"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated *time.Time `json:"updated_at"`
|
||||||
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
Deadline *time.Time `json:"due_on"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMilestoneOption list milestone options
|
||||||
|
type ListMilestoneOption struct {
|
||||||
|
ListOptions
|
||||||
|
// open, closed, all
|
||||||
|
State StateType
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListMilestoneOption) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if opt.State != "" {
|
||||||
|
query.Add("state", string(opt.State))
|
||||||
|
}
|
||||||
|
if len(opt.Name) != 0 {
|
||||||
|
query.Add("name", opt.Name)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoMilestones list all the milestones of one repository
|
||||||
|
func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
milestones := make([]*Milestone, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/milestones", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &milestones)
|
||||||
|
return milestones, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMilestone get one milestone by repo name and milestone id
|
||||||
|
func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMilestoneByName get one milestone by repo and milestone name
|
||||||
|
func (c *Client) GetMilestoneByName(owner, repo string, name string) (*Milestone, *Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
// backwards compatibility mode
|
||||||
|
m, resp, err := c.resolveMilestoneByName(owner, repo, name)
|
||||||
|
return m, resp, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil, milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMilestoneOption options for creating a milestone
|
||||||
|
type CreateMilestoneOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
State StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_on"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateMilestoneOption struct
|
||||||
|
func (opt CreateMilestoneOption) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMilestone create one milestone with options
|
||||||
|
func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
|
||||||
|
|
||||||
|
// make creating closed milestones need gitea >= v1.13.0
|
||||||
|
// this make it backwards compatible
|
||||||
|
if err == nil && opt.State == StateClosed && milestone.State != StateClosed {
|
||||||
|
closed := StateClosed
|
||||||
|
return c.EditMilestone(owner, repo, milestone.ID, EditMilestoneOption{
|
||||||
|
State: &closed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditMilestoneOption options for editing a milestone
|
||||||
|
type EditMilestoneOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
State *StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_on"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditMilestoneOption struct
|
||||||
|
func (opt EditMilestoneOption) Validate() error {
|
||||||
|
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditMilestone modify milestone with options
|
||||||
|
func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditMilestoneByName modify milestone with options
|
||||||
|
func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMilestoneOption) (*Milestone, *Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
// backwards compatibility mode
|
||||||
|
m, _, err := c.resolveMilestoneByName(owner, repo, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return c.EditMilestone(owner, repo, m.ID, opt)
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
milestone := new(Milestone)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), milestone)
|
||||||
|
return milestone, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMilestone delete one milestone by id
|
||||||
|
func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMilestoneByName delete one milestone by name
|
||||||
|
func (c *Client) DeleteMilestoneByName(owner, repo string, name string) (*Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
// backwards compatibility mode
|
||||||
|
m, _, err := c.resolveMilestoneByName(owner, repo, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.DeleteMilestone(owner, repo, m.ID)
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveMilestoneByName is a fallback method to find milestone id by name
|
||||||
|
func (c *Client) resolveMilestoneByName(owner, repo, name string) (*Milestone, *Response, error) {
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
miles, resp, err := c.ListRepoMilestones(owner, repo, ListMilestoneOption{
|
||||||
|
ListOptions: ListOptions{
|
||||||
|
Page: i,
|
||||||
|
},
|
||||||
|
State: "all",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(miles) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("milestone '%s' do not exist", name)
|
||||||
|
}
|
||||||
|
for _, m := range miles {
|
||||||
|
if strings.ToLower(strings.TrimSpace(m.Title)) == strings.ToLower(strings.TrimSpace(name)) {
|
||||||
|
return m, resp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
vendor/code.gitea.io/sdk/gitea/issue_reaction.go
generated
vendored
Normal file
104
vendor/code.gitea.io/sdk/gitea/issue_reaction.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reaction contain one reaction
|
||||||
|
type Reaction struct {
|
||||||
|
User *User `json:"user"`
|
||||||
|
Reaction string `json:"content"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueReactions get a list reactions of an issue
|
||||||
|
func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactions := make([]*Reaction, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions)
|
||||||
|
return reactions, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIssueCommentReactions get a list of reactions from a comment of an issue
|
||||||
|
func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactions := make([]*Reaction, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions)
|
||||||
|
return reactions, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// editReactionOption contain the reaction type
|
||||||
|
type editReactionOption struct {
|
||||||
|
Reaction string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostIssueReaction add a reaction to an issue
|
||||||
|
func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactionResponse := new(Reaction)
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), reactionResponse)
|
||||||
|
return reactionResponse, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueReaction remove a reaction from an issue
|
||||||
|
func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostIssueCommentReaction add a reaction to a comment of an issue
|
||||||
|
func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reactionResponse := new(Reaction)
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID),
|
||||||
|
jsonHeader, bytes.NewReader(body), reactionResponse)
|
||||||
|
return reactionResponse, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueCommentReaction remove a reaction from a comment of an issue
|
||||||
|
func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
57
vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
generated
vendored
Normal file
57
vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StopWatch represents a running stopwatch of an issue / pr
|
||||||
|
type StopWatch struct {
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
Seconds int64 `json:"seconds"`
|
||||||
|
Duration string `json:"duration"`
|
||||||
|
IssueIndex int64 `json:"issue_index"`
|
||||||
|
IssueTitle string `json:"issue_title"`
|
||||||
|
RepoOwnerName string `json:"repo_owner_name"`
|
||||||
|
RepoName string `json:"repo_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyStopwatches list all stopwatches
|
||||||
|
func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) {
|
||||||
|
stopwatches := make([]*StopWatch, 0, 1)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/stopwatches", nil, nil, &stopwatches)
|
||||||
|
return stopwatches, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueStopwatch delete / cancel a specific stopwatch
|
||||||
|
func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartIssueStopWatch starts a stopwatch for an existing issue for a given
|
||||||
|
// repository
|
||||||
|
func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopIssueStopWatch stops an existing stopwatch for an issue in a given
|
||||||
|
// repository
|
||||||
|
func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
87
vendor/code.gitea.io/sdk/gitea/issue_subscription.go
generated
vendored
Normal file
87
vendor/code.gitea.io/sdk/gitea/issue_subscription.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetIssueSubscribers get list of users who subscribed on an issue
|
||||||
|
func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
subscribers := make([]*User, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers)
|
||||||
|
return subscribers, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIssueSubscription Subscribe user to issue
|
||||||
|
func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusCreated {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
if status == http.StatusOK {
|
||||||
|
return resp, fmt.Errorf("already subscribed")
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIssueSubscription unsubscribe user from issue
|
||||||
|
func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusCreated {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
if status == http.StatusOK {
|
||||||
|
return resp, fmt.Errorf("already unsubscribed")
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckIssueSubscription check if current user is subscribed to an issue
|
||||||
|
func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
wi := new(WatchInfo)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/check", owner, repo, index), nil, nil, wi)
|
||||||
|
return wi, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueSubscribe subscribe current user to an issue
|
||||||
|
func (c *Client) IssueSubscribe(owner, repo string, index int64) (*Response, error) {
|
||||||
|
u, _, err := c.GetMyUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.AddIssueSubscription(owner, repo, index, u.UserName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssueUnSubscribe unsubscribe current user from an issue
|
||||||
|
func (c *Client) IssueUnSubscribe(owner, repo string, index int64) (*Response, error) {
|
||||||
|
u, _, err := c.GetMyUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.DeleteIssueSubscription(owner, repo, index, u.UserName)
|
||||||
|
}
|
142
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
generated
vendored
Normal file
142
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TrackedTime worked time for an issue / pr
|
||||||
|
type TrackedTime struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
// Time in seconds
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
// deprecated (only for backwards compatibility)
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
UserName string `json:"user_name"`
|
||||||
|
// deprecated (only for backwards compatibility)
|
||||||
|
IssueID int64 `json:"issue_id"`
|
||||||
|
Issue *Issue `json:"issue"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTrackedTimesOptions options for listing repository's tracked times
|
||||||
|
type ListTrackedTimesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
// User filter is only used by ListRepoTrackedTimes !!!
|
||||||
|
User string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListTrackedTimesOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opt.User) != 0 {
|
||||||
|
query.Add("user", opt.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTrackedTimes list tracked times of a repository
|
||||||
|
func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/times", owner, repo))
|
||||||
|
opt.setDefaults()
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
times := make([]*TrackedTime, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
|
||||||
|
return times, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyTrackedTimes list tracked times of the current user
|
||||||
|
func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) {
|
||||||
|
times := make([]*TrackedTime, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, ×)
|
||||||
|
return times, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTimeOption options for adding time to an issue
|
||||||
|
type AddTimeOption struct {
|
||||||
|
// time in seconds
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
// optional
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
// optional
|
||||||
|
User string `json:"user_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the AddTimeOption struct
|
||||||
|
func (opt AddTimeOption) Validate() error {
|
||||||
|
if opt.Time == 0 {
|
||||||
|
return fmt.Errorf("no time to add")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTime adds time to issue with the given index
|
||||||
|
func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(TrackedTime)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListIssueTrackedTimes list tracked times of a single issue for a given repository
|
||||||
|
func (c *Client) ListIssueTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index))
|
||||||
|
opt.setDefaults()
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
times := make([]*TrackedTime, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
|
||||||
|
return times, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetIssueTime reset tracked time of a single issue for a given repository
|
||||||
|
func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteTime delete a specific tracked time by id of a single issue for a given repository
|
||||||
|
func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
42
vendor/code.gitea.io/sdk/gitea/list_options.go
generated
vendored
Normal file
42
vendor/code.gitea.io/sdk/gitea/list_options.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultPageSize = 10
|
||||||
|
const maxPageSize = 50
|
||||||
|
|
||||||
|
// ListOptions options for using Gitea's API pagination
|
||||||
|
type ListOptions struct {
|
||||||
|
Page int
|
||||||
|
PageSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o ListOptions) getURLQuery() url.Values {
|
||||||
|
query := make(url.Values)
|
||||||
|
query.Add("page", fmt.Sprintf("%d", o.Page))
|
||||||
|
query.Add("limit", fmt.Sprintf("%d", o.PageSize))
|
||||||
|
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// setDefaults set default pagination options if none or wrong are set
|
||||||
|
// if you set -1 as page it will set all to 0
|
||||||
|
func (o *ListOptions) setDefaults() {
|
||||||
|
if o.Page < 0 {
|
||||||
|
o.Page, o.PageSize = 0, 0
|
||||||
|
return
|
||||||
|
} else if o.Page == 0 {
|
||||||
|
o.Page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.PageSize < 0 || o.PageSize > maxPageSize {
|
||||||
|
o.PageSize = defaultPageSize
|
||||||
|
}
|
||||||
|
}
|
241
vendor/code.gitea.io/sdk/gitea/notifications.go
generated
vendored
Normal file
241
vendor/code.gitea.io/sdk/gitea/notifications.go
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
version1_12_3, _ = version.NewVersion("1.12.3")
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotificationThread expose Notification on API
|
||||||
|
type NotificationThread struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Repository *Repository `json:"repository"`
|
||||||
|
Subject *NotificationSubject `json:"subject"`
|
||||||
|
Unread bool `json:"unread"`
|
||||||
|
Pinned bool `json:"pinned"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotificationSubject contains the notification subject (Issue/Pull/Commit)
|
||||||
|
type NotificationSubject struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
LatestCommentURL string `json:"latest_comment_url"`
|
||||||
|
Type NotifySubjectType `json:"type"`
|
||||||
|
State NotifySubjectState `json:"state"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyStatus notification status type
|
||||||
|
type NotifyStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NotifyStatusUnread was not read
|
||||||
|
NotifyStatusUnread NotifyStatus = "unread"
|
||||||
|
// NotifyStatusRead was already read by user
|
||||||
|
NotifyStatusRead NotifyStatus = "read"
|
||||||
|
// NotifyStatusPinned notification is pinned by user
|
||||||
|
NotifyStatusPinned NotifyStatus = "pinned"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotifySubjectType represent type of notification subject
|
||||||
|
type NotifySubjectType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NotifySubjectIssue an issue is subject of an notification
|
||||||
|
NotifySubjectIssue NotifySubjectType = "Issue"
|
||||||
|
// NotifySubjectPull an pull is subject of an notification
|
||||||
|
NotifySubjectPull NotifySubjectType = "Pull"
|
||||||
|
// NotifySubjectCommit an commit is subject of an notification
|
||||||
|
NotifySubjectCommit NotifySubjectType = "Commit"
|
||||||
|
// NotifySubjectRepository an repository is subject of an notification
|
||||||
|
NotifySubjectRepository NotifySubjectType = "Repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NotifySubjectState reflect state of notification subject
|
||||||
|
type NotifySubjectState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NotifySubjectOpen if subject is a pull/issue and is open at the moment
|
||||||
|
NotifySubjectOpen NotifySubjectState = "open"
|
||||||
|
// NotifySubjectClosed if subject is a pull/issue and is closed at the moment
|
||||||
|
NotifySubjectClosed NotifySubjectState = "closed"
|
||||||
|
// NotifySubjectMerged if subject is a pull and got merged
|
||||||
|
NotifySubjectMerged NotifySubjectState = "merged"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListNotificationOptions represents the filter options
|
||||||
|
type ListNotificationOptions struct {
|
||||||
|
ListOptions
|
||||||
|
Since time.Time
|
||||||
|
Before time.Time
|
||||||
|
Status []NotifyStatus
|
||||||
|
SubjectTypes []NotifySubjectType
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkNotificationOptions represents the filter & modify options
|
||||||
|
type MarkNotificationOptions struct {
|
||||||
|
LastReadAt time.Time
|
||||||
|
Status []NotifyStatus
|
||||||
|
ToStatus NotifyStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode encode options to url query
|
||||||
|
func (opt *ListNotificationOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if !opt.Since.IsZero() {
|
||||||
|
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
if !opt.Before.IsZero() {
|
||||||
|
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
for _, s := range opt.Status {
|
||||||
|
query.Add("status-types", string(s))
|
||||||
|
}
|
||||||
|
for _, s := range opt.SubjectTypes {
|
||||||
|
query.Add("subject-type", string(s))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateUserOption struct
|
||||||
|
func (opt ListNotificationOptions) Validate(c *Client) error {
|
||||||
|
if len(opt.Status) != 0 {
|
||||||
|
return c.checkServerVersionGreaterThanOrEqual(version1_12_3)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode encode options to url query
|
||||||
|
func (opt *MarkNotificationOptions) QueryEncode() string {
|
||||||
|
query := make(url.Values)
|
||||||
|
if !opt.LastReadAt.IsZero() {
|
||||||
|
query.Add("last_read_at", opt.LastReadAt.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
for _, s := range opt.Status {
|
||||||
|
query.Add("status-types", string(s))
|
||||||
|
}
|
||||||
|
if len(opt.ToStatus) != 0 {
|
||||||
|
query.Add("to-status", string(opt.ToStatus))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateUserOption struct
|
||||||
|
func (opt MarkNotificationOptions) Validate(c *Client) error {
|
||||||
|
if len(opt.Status) != 0 || len(opt.ToStatus) != 0 {
|
||||||
|
return c.checkServerVersionGreaterThanOrEqual(version1_12_3)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckNotifications list users's notification threads
|
||||||
|
func (c *Client) CheckNotifications() (int64, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
new := struct {
|
||||||
|
New int64 `json:"new"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", "/notifications/new", jsonHeader, nil, &new)
|
||||||
|
return new.New, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNotification get notification thread by ID
|
||||||
|
func (c *Client) GetNotification(id int64) (*NotificationThread, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
thread := new(NotificationThread)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/notifications/threads/%d", id), nil, nil, thread)
|
||||||
|
return thread, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadNotification mark notification thread as read by ID
|
||||||
|
// It optionally takes a second argument if status has to be set other than 'read'
|
||||||
|
func (c *Client) ReadNotification(id int64, status ...NotifyStatus) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link := fmt.Sprintf("/notifications/threads/%d", id)
|
||||||
|
if len(status) != 0 {
|
||||||
|
link += fmt.Sprintf("?to-status=%s", status[0])
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", link, nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNotifications list users's notification threads
|
||||||
|
func (c *Client) ListNotifications(opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse("/notifications")
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
threads := make([]*NotificationThread, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
|
||||||
|
return threads, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadNotifications mark notification threads as read
|
||||||
|
func (c *Client) ReadNotifications(opt MarkNotificationOptions) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse("/notifications")
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoNotifications list users's notification threads on a specific repo
|
||||||
|
func (c *Client) ListRepoNotifications(owner, repo string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
threads := make([]*NotificationThread, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
|
||||||
|
return threads, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadRepoNotifications mark notification threads as read on a specific repo
|
||||||
|
func (c *Client) ReadRepoNotifications(owner, repo string, opt MarkNotificationOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
91
vendor/code.gitea.io/sdk/gitea/oauth2.go
generated
vendored
Normal file
91
vendor/code.gitea.io/sdk/gitea/oauth2.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Oauth2 represents an Oauth2 Application
|
||||||
|
type Oauth2 struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ClientID string `json:"client_id"`
|
||||||
|
ClientSecret string `json:"client_secret"`
|
||||||
|
RedirectURIs []string `json:"redirect_uris"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOauth2Option for listing Oauth2 Applications
|
||||||
|
type ListOauth2Option struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOauth2Option required options for creating an Application
|
||||||
|
type CreateOauth2Option struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
RedirectURIs []string `json:"redirect_uris"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOauth2 create an Oauth2 Application and returns a completed Oauth2 object.
|
||||||
|
func (c *Client) CreateOauth2(opt CreateOauth2Option) (*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
oauth := new(Oauth2)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/applications/oauth2", jsonHeader, bytes.NewReader(body), oauth)
|
||||||
|
return oauth, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOauth2 a specific Oauth2 Application by ID and return a completed Oauth2 object.
|
||||||
|
func (c *Client) UpdateOauth2(oauth2id int64, opt CreateOauth2Option) (*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
oauth := new(Oauth2)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), jsonHeader, bytes.NewReader(body), oauth)
|
||||||
|
return oauth, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOauth2 a specific Oauth2 Application by ID.
|
||||||
|
func (c *Client) GetOauth2(oauth2id int64) (*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
oauth2s := &Oauth2{}
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil, &oauth2s)
|
||||||
|
return oauth2s, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOauth2 all of your Oauth2 Applications.
|
||||||
|
func (c *Client) ListOauth2(opt ListOauth2Option) ([]*Oauth2, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
oauth2s := make([]*Oauth2, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2?%s", opt.getURLQuery().Encode()), nil, nil, &oauth2s)
|
||||||
|
return oauth2s, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOauth2 delete an Oauth2 application by ID
|
||||||
|
func (c *Client) DeleteOauth2(oauth2id int64) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
155
vendor/code.gitea.io/sdk/gitea/org.go
generated
vendored
Normal file
155
vendor/code.gitea.io/sdk/gitea/org.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Organization represents an organization
|
||||||
|
type Organization struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
UserName string `json:"username"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Visibility string `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisibleType defines the visibility
|
||||||
|
type VisibleType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// VisibleTypePublic Visible for everyone
|
||||||
|
VisibleTypePublic VisibleType = "public"
|
||||||
|
|
||||||
|
// VisibleTypeLimited Visible for every connected user
|
||||||
|
VisibleTypeLimited VisibleType = "limited"
|
||||||
|
|
||||||
|
// VisibleTypePrivate Visible only for organization's members
|
||||||
|
VisibleTypePrivate VisibleType = "private"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListOrgsOptions options for listing organizations
|
||||||
|
type ListOrgsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyOrgs list all of current user's organizations
|
||||||
|
func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
orgs := make([]*Organization, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||||
|
return orgs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUserOrgs list all of some user's organizations
|
||||||
|
func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
orgs := make([]*Organization, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||||
|
return orgs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrg get one organization by name
|
||||||
|
func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
org := new(Organization)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
|
||||||
|
return org, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrgOption options for creating an organization
|
||||||
|
type CreateOrgOption struct {
|
||||||
|
Name string `json:"username"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Visibility VisibleType `json:"visibility"`
|
||||||
|
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkVisibilityOpt check if mode exist
|
||||||
|
func checkVisibilityOpt(v VisibleType) bool {
|
||||||
|
return v == VisibleTypePublic || v == VisibleTypeLimited || v == VisibleTypePrivate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateOrgOption struct
|
||||||
|
func (opt CreateOrgOption) Validate() error {
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("empty org name")
|
||||||
|
}
|
||||||
|
if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) {
|
||||||
|
return fmt.Errorf("infalid bisibility option")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrg creates an organization
|
||||||
|
func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, *Response, error) {
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
org := new(Organization)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/orgs", jsonHeader, bytes.NewReader(body), org)
|
||||||
|
return org, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditOrgOption options for editing an organization
|
||||||
|
type EditOrgOption struct {
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Visibility VisibleType `json:"visibility"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditOrgOption struct
|
||||||
|
func (opt EditOrgOption) Validate() error {
|
||||||
|
if len(opt.Visibility) != 0 && !checkVisibilityOpt(opt.Visibility) {
|
||||||
|
return fmt.Errorf("infalid bisibility option")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditOrg modify one organization via options
|
||||||
|
func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrg deletes an organization
|
||||||
|
func (c *Client) DeleteOrg(orgname string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
119
vendor/code.gitea.io/sdk/gitea/org_member.go
generated
vendored
Normal file
119
vendor/code.gitea.io/sdk/gitea/org_member.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteOrgMembership remove a member from an organization
|
||||||
|
func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgMembershipOption list OrgMembership options
|
||||||
|
type ListOrgMembershipOption struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgMembership list an organization's members
|
||||||
|
func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", org))
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPublicOrgMembership list an organization's members
|
||||||
|
func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", org))
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckOrgMembership Check if a user is a member of an organization
|
||||||
|
func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return true, resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPublicOrgMembership Check if a user is a member of an organization
|
||||||
|
func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return true, resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPublicOrgMembership publicize/conceal a user's membership
|
||||||
|
func (c *Client) SetPublicOrgMembership(org, user string, visible bool) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
status int
|
||||||
|
err error
|
||||||
|
resp *Response
|
||||||
|
)
|
||||||
|
if visible {
|
||||||
|
status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||||
|
} else {
|
||||||
|
status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return resp, fmt.Errorf("forbidden")
|
||||||
|
default:
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
242
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
Normal file
242
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Team represents a team in an organization
|
||||||
|
type Team struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Organization *Organization `json:"organization"`
|
||||||
|
Permission AccessMode `json:"permission"`
|
||||||
|
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||||
|
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||||
|
Units []RepoUnitType `json:"units"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoUnitType represent all unit types of a repo gitea currently offer
|
||||||
|
type RepoUnitType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RepoUnitCode represent file view of a repository
|
||||||
|
RepoUnitCode RepoUnitType = "repo.code"
|
||||||
|
// RepoUnitIssues represent issues of a repository
|
||||||
|
RepoUnitIssues RepoUnitType = "repo.issues"
|
||||||
|
// RepoUnitPulls represent pulls of a repository
|
||||||
|
RepoUnitPulls RepoUnitType = "repo.pulls"
|
||||||
|
// RepoUnitExtIssues represent external issues of a repository
|
||||||
|
RepoUnitExtIssues RepoUnitType = "repo.ext_issues"
|
||||||
|
// RepoUnitWiki represent wiki of a repository
|
||||||
|
RepoUnitWiki RepoUnitType = "repo.wiki"
|
||||||
|
// RepoUnitExtWiki represent external wiki of a repository
|
||||||
|
RepoUnitExtWiki RepoUnitType = "repo.ext_wiki"
|
||||||
|
// RepoUnitReleases represent releases of a repository
|
||||||
|
RepoUnitReleases RepoUnitType = "repo.releases"
|
||||||
|
// RepoUnitProjects represent projects of a repository
|
||||||
|
RepoUnitProjects RepoUnitType = "repo.projects"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListTeamsOptions options for listing teams
|
||||||
|
type ListTeamsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgTeams lists all teams of an organization
|
||||||
|
func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
teams := make([]*Team, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams)
|
||||||
|
return teams, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyTeams lists all the teams of the current user
|
||||||
|
func (c *Client) ListMyTeams(opt *ListTeamsOptions) ([]*Team, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
teams := make([]*Team, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/teams?%s", opt.getURLQuery().Encode()), nil, nil, &teams)
|
||||||
|
return teams, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeam gets a team by ID
|
||||||
|
func (c *Client) GetTeam(id int64) (*Team, *Response, error) {
|
||||||
|
t := new(Team)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d", id), nil, nil, t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTeamOption options for creating a team
|
||||||
|
type CreateTeamOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Permission AccessMode `json:"permission"`
|
||||||
|
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||||
|
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||||
|
Units []RepoUnitType `json:"units"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateTeamOption struct
|
||||||
|
func (opt CreateTeamOption) Validate() error {
|
||||||
|
if opt.Permission == AccessModeOwner {
|
||||||
|
opt.Permission = AccessModeAdmin
|
||||||
|
} else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin {
|
||||||
|
return fmt.Errorf("permission mode invalid")
|
||||||
|
}
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("name required")
|
||||||
|
}
|
||||||
|
if len(opt.Name) > 30 {
|
||||||
|
return fmt.Errorf("name to long")
|
||||||
|
}
|
||||||
|
if len(opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("description to long")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTeam creates a team for an organization
|
||||||
|
func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Team)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/teams", org), jsonHeader, bytes.NewReader(body), t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditTeamOption options for editing a team
|
||||||
|
type EditTeamOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
Permission AccessMode `json:"permission"`
|
||||||
|
CanCreateOrgRepo *bool `json:"can_create_org_repo"`
|
||||||
|
IncludesAllRepositories *bool `json:"includes_all_repositories"`
|
||||||
|
Units []RepoUnitType `json:"units"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditTeamOption struct
|
||||||
|
func (opt EditTeamOption) Validate() error {
|
||||||
|
if opt.Permission == AccessModeOwner {
|
||||||
|
opt.Permission = AccessModeAdmin
|
||||||
|
} else if opt.Permission != AccessModeRead && opt.Permission != AccessModeWrite && opt.Permission != AccessModeAdmin {
|
||||||
|
return fmt.Errorf("permission mode invalid")
|
||||||
|
}
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("name required")
|
||||||
|
}
|
||||||
|
if len(opt.Name) > 30 {
|
||||||
|
return fmt.Errorf("name to long")
|
||||||
|
}
|
||||||
|
if opt.Description != nil && len(*opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("description to long")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditTeam edits a team of an organization
|
||||||
|
func (c *Client) EditTeam(id int64, opt EditTeamOption) (*Response, error) {
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteTeam deletes a team of an organization
|
||||||
|
func (c *Client) DeleteTeam(id int64) (*Response, error) {
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamMembersOptions options for listing team's members
|
||||||
|
type ListTeamMembersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamMembers lists all members of a team
|
||||||
|
func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
members := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members?%s", id, opt.getURLQuery().Encode()), nil, nil, &members)
|
||||||
|
return members, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTeamMember gets a member of a team
|
||||||
|
func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
m := new(User)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m)
|
||||||
|
return m, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTeamMember adds a member to a team
|
||||||
|
func (c *Client) AddTeamMember(id int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTeamMember removes a member from a team
|
||||||
|
func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamRepositoriesOptions options for listing team's repositories
|
||||||
|
type ListTeamRepositoriesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTeamRepositories lists all repositories of a team
|
||||||
|
func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions) ([]*Repository, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos?%s", id, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTeamRepository adds a repository to a team
|
||||||
|
func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveTeamRepository removes a repository from a team
|
||||||
|
func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
328
vendor/code.gitea.io/sdk/gitea/pull.go
generated
vendored
Normal file
328
vendor/code.gitea.io/sdk/gitea/pull.go
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PRBranchInfo information about a branch
|
||||||
|
type PRBranchInfo struct {
|
||||||
|
Name string `json:"label"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Sha string `json:"sha"`
|
||||||
|
RepoID int64 `json:"repo_id"`
|
||||||
|
Repository *Repository `json:"repo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullRequest represents a pull request
|
||||||
|
type PullRequest struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Index int64 `json:"number"`
|
||||||
|
Poster *User `json:"user"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Labels []*Label `json:"labels"`
|
||||||
|
Milestone *Milestone `json:"milestone"`
|
||||||
|
Assignee *User `json:"assignee"`
|
||||||
|
Assignees []*User `json:"assignees"`
|
||||||
|
State StateType `json:"state"`
|
||||||
|
IsLocked bool `json:"is_locked"`
|
||||||
|
Comments int `json:"comments"`
|
||||||
|
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
DiffURL string `json:"diff_url"`
|
||||||
|
PatchURL string `json:"patch_url"`
|
||||||
|
|
||||||
|
Mergeable bool `json:"mergeable"`
|
||||||
|
HasMerged bool `json:"merged"`
|
||||||
|
Merged *time.Time `json:"merged_at"`
|
||||||
|
MergedCommitID *string `json:"merge_commit_sha"`
|
||||||
|
MergedBy *User `json:"merged_by"`
|
||||||
|
|
||||||
|
Base *PRBranchInfo `json:"base"`
|
||||||
|
Head *PRBranchInfo `json:"head"`
|
||||||
|
MergeBase string `json:"merge_base"`
|
||||||
|
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
Created *time.Time `json:"created_at"`
|
||||||
|
Updated *time.Time `json:"updated_at"`
|
||||||
|
Closed *time.Time `json:"closed_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullRequestsOptions options for listing pull requests
|
||||||
|
type ListPullRequestsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
State StateType `json:"state"`
|
||||||
|
// oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority
|
||||||
|
Sort string
|
||||||
|
Milestone int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeStyle is used specify how a pull is merged
|
||||||
|
type MergeStyle string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MergeStyleMerge merge pull as usual
|
||||||
|
MergeStyleMerge MergeStyle = "merge"
|
||||||
|
// MergeStyleRebase rebase pull
|
||||||
|
MergeStyleRebase MergeStyle = "rebase"
|
||||||
|
// MergeStyleRebaseMerge rebase and merge pull
|
||||||
|
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
|
||||||
|
// MergeStyleSquash squash and merge pull
|
||||||
|
MergeStyleSquash MergeStyle = "squash"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListPullRequestsOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if len(opt.State) > 0 {
|
||||||
|
query.Add("state", string(opt.State))
|
||||||
|
}
|
||||||
|
if len(opt.Sort) > 0 {
|
||||||
|
query.Add("sort", opt.Sort)
|
||||||
|
}
|
||||||
|
if opt.Milestone > 0 {
|
||||||
|
query.Add("milestone", fmt.Sprintf("%d", opt.Milestone))
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoPullRequests list PRs of one repository
|
||||||
|
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
prs := make([]*PullRequest, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo))
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs)
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
for i := range prs {
|
||||||
|
if err := fixPullHeadSha(c, prs[i]); err != nil {
|
||||||
|
return prs, resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequest get information of one PR
|
||||||
|
func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pr := new(PullRequest)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr)
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
if err := fixPullHeadSha(c, pr); err != nil {
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullRequestOption options when creating a pull request
|
||||||
|
type CreatePullRequestOption struct {
|
||||||
|
Head string `json:"head"`
|
||||||
|
Base string `json:"base"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Assignee string `json:"assignee"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Milestone int64 `json:"milestone"`
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullRequest create pull request with options
|
||||||
|
func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pr := new(PullRequest)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), pr)
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditPullRequestOption options when modify pull request
|
||||||
|
type EditPullRequestOption struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Base string `json:"base"`
|
||||||
|
Assignee string `json:"assignee"`
|
||||||
|
Assignees []string `json:"assignees"`
|
||||||
|
Milestone int64 `json:"milestone"`
|
||||||
|
Labels []int64 `json:"labels"`
|
||||||
|
State *StateType `json:"state"`
|
||||||
|
Deadline *time.Time `json:"due_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the EditPullRequestOption struct
|
||||||
|
func (opt EditPullRequestOption) Validate(c *Client) error {
|
||||||
|
if len(opt.Title) != 0 && len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
if len(opt.Base) != 0 {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return fmt.Errorf("can not change base gitea to old")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditPullRequest modify pull request with PR id and options
|
||||||
|
func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
pr := new(PullRequest)
|
||||||
|
resp, err := c.getParsedResponse("PATCH",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), pr)
|
||||||
|
return pr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergePullRequestOption options when merging a pull request
|
||||||
|
type MergePullRequestOption struct {
|
||||||
|
Style MergeStyle `json:"Do"`
|
||||||
|
Title string `json:"MergeTitleField"`
|
||||||
|
Message string `json:"MergeMessageField"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var version1_11_5, _ = version.NewVersion("1.11.5")
|
||||||
|
|
||||||
|
// Validate the MergePullRequestOption struct
|
||||||
|
func (opt MergePullRequestOption) Validate(c *Client) error {
|
||||||
|
if opt.Style == MergeStyleSquash {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_11_5); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergePullRequest merge a PR to repository by PR id
|
||||||
|
func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), jsonHeader, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
return status == 200, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPullRequestMerged test if one PR is merged to one repository
|
||||||
|
func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return status == 204, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getPullRequestDiffOrPatch gets the patch or diff file as bytes for a PR
|
||||||
|
func (c *Client) getPullRequestDiffOrPatch(owner, repo, kind string, index int64) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &kind); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
r, _, err2 := c.GetRepo(owner, repo)
|
||||||
|
if err2 != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if r.Private {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return c.getWebResponse("GET", fmt.Sprintf("/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil)
|
||||||
|
}
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d.%s", owner, repo, index, kind), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequestPatch gets the .patch file as bytes for a PR
|
||||||
|
func (c *Client) GetPullRequestPatch(owner, repo string, index int64) ([]byte, *Response, error) {
|
||||||
|
return c.getPullRequestDiffOrPatch(owner, repo, "patch", index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullRequestDiff gets the .diff file as bytes for a PR
|
||||||
|
func (c *Client) GetPullRequestDiff(owner, repo string, index int64) ([]byte, *Response, error) {
|
||||||
|
return c.getPullRequestDiffOrPatch(owner, repo, "diff", index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullRequestCommitsOptions options for listing pull requests
|
||||||
|
type ListPullRequestCommitsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullRequestCommits list commits for a pull request
|
||||||
|
func (c *Client) ListPullRequestCommits(owner, repo string, index int64, opt ListPullRequestCommitsOptions) ([]*Commit, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/commits", owner, repo, index))
|
||||||
|
opt.setDefaults()
|
||||||
|
commits := make([]*Commit, 0, opt.PageSize)
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
|
||||||
|
return commits, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
|
||||||
|
// When no head sha is available, this is because the branch got deleted in the base repo.
|
||||||
|
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
|
||||||
|
// which stays available to resolve the commit sha. This is fixed for gitea >= 1.14.0
|
||||||
|
func fixPullHeadSha(client *Client, pr *PullRequest) error {
|
||||||
|
if pr.Base != nil && pr.Base.Repository != nil && pr.Base.Repository.Owner != nil &&
|
||||||
|
pr.Head != nil && pr.Head.Ref != "" && pr.Head.Sha == "" {
|
||||||
|
owner := pr.Base.Repository.Owner.UserName
|
||||||
|
repo := pr.Base.Repository.Name
|
||||||
|
refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(refs) == 0 {
|
||||||
|
return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
|
||||||
|
}
|
||||||
|
pr.Head.Sha = refs[0].Object.SHA
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
325
vendor/code.gitea.io/sdk/gitea/pull_review.go
generated
vendored
Normal file
325
vendor/code.gitea.io/sdk/gitea/pull_review.go
generated
vendored
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReviewStateType review state type
|
||||||
|
type ReviewStateType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ReviewStateApproved pr is approved
|
||||||
|
ReviewStateApproved ReviewStateType = "APPROVED"
|
||||||
|
// ReviewStatePending pr state is pending
|
||||||
|
ReviewStatePending ReviewStateType = "PENDING"
|
||||||
|
// ReviewStateComment is a comment review
|
||||||
|
ReviewStateComment ReviewStateType = "COMMENT"
|
||||||
|
// ReviewStateRequestChanges changes for pr are requested
|
||||||
|
ReviewStateRequestChanges ReviewStateType = "REQUEST_CHANGES"
|
||||||
|
// ReviewStateRequestReview review is requested from user
|
||||||
|
ReviewStateRequestReview ReviewStateType = "REQUEST_REVIEW"
|
||||||
|
// ReviewStateUnknown state of pr is unknown
|
||||||
|
ReviewStateUnknown ReviewStateType = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
// PullReview represents a pull request review
|
||||||
|
type PullReview struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Reviewer *User `json:"user"`
|
||||||
|
ReviewerTeam *Team `json:"team"`
|
||||||
|
State ReviewStateType `json:"state"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
CommitID string `json:"commit_id"`
|
||||||
|
// Stale indicates if the pull has changed since the review
|
||||||
|
Stale bool `json:"stale"`
|
||||||
|
// Official indicates if the review counts towards the required approval limit, if PR base is a protected branch
|
||||||
|
Official bool `json:"official"`
|
||||||
|
Dismissed bool `json:"dismissed"`
|
||||||
|
CodeCommentsCount int `json:"comments_count"`
|
||||||
|
Submitted time.Time `json:"submitted_at"`
|
||||||
|
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
HTMLPullURL string `json:"pull_request_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullReviewComment represents a comment on a pull request review
|
||||||
|
type PullReviewComment struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
Reviewer *User `json:"user"`
|
||||||
|
ReviewID int64 `json:"pull_request_review_id"`
|
||||||
|
Resolver *User `json:"resolver"`
|
||||||
|
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
Path string `json:"path"`
|
||||||
|
CommitID string `json:"commit_id"`
|
||||||
|
OrigCommitID string `json:"original_commit_id"`
|
||||||
|
DiffHunk string `json:"diff_hunk"`
|
||||||
|
LineNum uint64 `json:"position"`
|
||||||
|
OldLineNum uint64 `json:"original_position"`
|
||||||
|
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
HTMLPullURL string `json:"pull_request_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullReviewOptions are options to create a pull review
|
||||||
|
type CreatePullReviewOptions struct {
|
||||||
|
State ReviewStateType `json:"event"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
CommitID string `json:"commit_id"`
|
||||||
|
Comments []CreatePullReviewComment `json:"comments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullReviewComment represent a review comment for creation api
|
||||||
|
type CreatePullReviewComment struct {
|
||||||
|
// the tree path
|
||||||
|
Path string `json:"path"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
// if comment to old file line or 0
|
||||||
|
OldLineNum int64 `json:"old_position"`
|
||||||
|
// if comment to new file line or 0
|
||||||
|
NewLineNum int64 `json:"new_position"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitPullReviewOptions are options to submit a pending pull review
|
||||||
|
type SubmitPullReviewOptions struct {
|
||||||
|
State ReviewStateType `json:"event"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DismissPullReviewOptions are options to dismiss a pull review
|
||||||
|
type DismissPullReviewOptions struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullReviewRequestOptions are options to add or remove pull review requests
|
||||||
|
type PullReviewRequestOptions struct {
|
||||||
|
Reviewers []string `json:"reviewers"`
|
||||||
|
TeamReviewers []string `json:"team_reviewers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullReviewsOptions options for listing PullReviews
|
||||||
|
type ListPullReviewsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreatePullReviewOptions struct
|
||||||
|
func (opt CreatePullReviewOptions) Validate() error {
|
||||||
|
if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
for i := range opt.Comments {
|
||||||
|
if err := opt.Comments[i].Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the SubmitPullReviewOptions struct
|
||||||
|
func (opt SubmitPullReviewOptions) Validate() error {
|
||||||
|
if opt.State != ReviewStateApproved && len(strings.TrimSpace(opt.Body)) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreatePullReviewComment struct
|
||||||
|
func (opt CreatePullReviewComment) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Body)) == 0 {
|
||||||
|
return fmt.Errorf("body is empty")
|
||||||
|
}
|
||||||
|
if opt.NewLineNum != 0 && opt.OldLineNum != 0 {
|
||||||
|
return fmt.Errorf("old and new line num are set, cant identify the code comment position")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullReviews lists all reviews of a pull request
|
||||||
|
func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
rs := make([]*PullReview, 0, opt.PageSize)
|
||||||
|
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index))
|
||||||
|
link.RawQuery = opt.ListOptions.getURLQuery().Encode()
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rs)
|
||||||
|
return rs, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPullReview gets a specific review of a pull request
|
||||||
|
func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(PullReview)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil, &r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPullReviewComments lists all comments of a pull request review
|
||||||
|
func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]*PullReviewComment, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
rcl := make([]*PullReviewComment, 0, 4)
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/comments", owner, repo, index, id))
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rcl)
|
||||||
|
return rcl, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePullReview delete a specific review from a pull request
|
||||||
|
func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullReview create a review to an pull request
|
||||||
|
func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(PullReview)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitPullReview submit a pending review to an pull request
|
||||||
|
func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(PullReview)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReviewRequests create review requests to an pull request
|
||||||
|
func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteReviewRequests delete review requests to an pull request
|
||||||
|
func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DismissPullReview dismiss a review for a pull request
|
||||||
|
func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt DismissPullReviewOptions) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id),
|
||||||
|
jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnDismissPullReview cancel to dismiss a review for a pull request
|
||||||
|
func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id),
|
||||||
|
jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
202
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
Normal file
202
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Release represents a repository release
|
||||||
|
type Release struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
TagName string `json:"tag_name"`
|
||||||
|
Target string `json:"target_commitish"`
|
||||||
|
Title string `json:"name"`
|
||||||
|
Note string `json:"body"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
TarURL string `json:"tarball_url"`
|
||||||
|
ZipURL string `json:"zipball_url"`
|
||||||
|
IsDraft bool `json:"draft"`
|
||||||
|
IsPrerelease bool `json:"prerelease"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
PublishedAt time.Time `json:"published_at"`
|
||||||
|
Publisher *User `json:"author"`
|
||||||
|
Attachments []*Attachment `json:"assets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleasesOptions options for listing repository's releases
|
||||||
|
type ListReleasesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
IsDraft *bool
|
||||||
|
IsPreRelease *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListReleasesOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
|
||||||
|
if opt.IsDraft != nil {
|
||||||
|
query.Add("draft", fmt.Sprintf("%t", *opt.IsDraft))
|
||||||
|
}
|
||||||
|
if opt.IsPreRelease != nil {
|
||||||
|
query.Add("draft", fmt.Sprintf("%t", *opt.IsPreRelease))
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReleases list releases of a repository
|
||||||
|
func (c *Client) ListReleases(owner, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
releases := make([]*Release, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases?%s", owner, repo, opt.QueryEncode()),
|
||||||
|
nil, nil, &releases)
|
||||||
|
return releases, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRelease get a release of a repository by id
|
||||||
|
func (c *Client) GetRelease(owner, repo string, id int64) (*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
|
||||||
|
jsonHeader, nil, &r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReleaseByTag get a release of a repository by tag
|
||||||
|
func (c *Client) GetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
return c.fallbackGetReleaseByTag(owner, repo, tag)
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &tag); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", owner, repo, tag),
|
||||||
|
nil, nil, &r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReleaseOption options when creating a release
|
||||||
|
type CreateReleaseOption struct {
|
||||||
|
TagName string `json:"tag_name"`
|
||||||
|
Target string `json:"target_commitish"`
|
||||||
|
Title string `json:"name"`
|
||||||
|
Note string `json:"body"`
|
||||||
|
IsDraft bool `json:"draft"`
|
||||||
|
IsPrerelease bool `json:"prerelease"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateReleaseOption struct
|
||||||
|
func (opt CreateReleaseOption) Validate() error {
|
||||||
|
if len(strings.TrimSpace(opt.Title)) == 0 {
|
||||||
|
return fmt.Errorf("title is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRelease create a release
|
||||||
|
func (c *Client) CreateRelease(owner, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("POST",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases", owner, repo),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditReleaseOption options when editing a release
|
||||||
|
type EditReleaseOption struct {
|
||||||
|
TagName string `json:"tag_name"`
|
||||||
|
Target string `json:"target_commitish"`
|
||||||
|
Title string `json:"name"`
|
||||||
|
Note string `json:"body"`
|
||||||
|
IsDraft *bool `json:"draft"`
|
||||||
|
IsPrerelease *bool `json:"prerelease"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRelease edit a release
|
||||||
|
func (c *Client) EditRelease(owner, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
r := new(Release)
|
||||||
|
resp, err := c.getParsedResponse("PATCH",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
|
||||||
|
jsonHeader, bytes.NewReader(body), r)
|
||||||
|
return r, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRelease delete a release from a repository, keeping its tag
|
||||||
|
func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
|
||||||
|
nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteReleaseByTag deletes a release frm a repository by tag
|
||||||
|
func (c *Client) DeleteReleaseByTag(user, repo string, tag string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
|
||||||
|
nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 )
|
||||||
|
func (c *Client) fallbackGetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
rl, resp, err := c.ListReleases(owner, repo, ListReleasesOptions{ListOptions: ListOptions{Page: i}})
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
if len(rl) == 0 {
|
||||||
|
return nil,
|
||||||
|
&Response{&http.Response{StatusCode: 404}},
|
||||||
|
fmt.Errorf("release with tag '%s' not found", tag)
|
||||||
|
}
|
||||||
|
for _, r := range rl {
|
||||||
|
if r.TagName == tag {
|
||||||
|
return r, resp, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
534
vendor/code.gitea.io/sdk/gitea/repo.go
generated
vendored
Normal file
534
vendor/code.gitea.io/sdk/gitea/repo.go
generated
vendored
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Permission represents a set of permissions
|
||||||
|
type Permission struct {
|
||||||
|
Admin bool `json:"admin"`
|
||||||
|
Push bool `json:"push"`
|
||||||
|
Pull bool `json:"pull"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// InternalTracker represents settings for internal tracker
|
||||||
|
type InternalTracker struct {
|
||||||
|
// Enable time tracking (Built-in issue tracker)
|
||||||
|
EnableTimeTracker bool `json:"enable_time_tracker"`
|
||||||
|
// Let only contributors track time (Built-in issue tracker)
|
||||||
|
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
|
||||||
|
// Enable dependencies for issues and pull requests (Built-in issue tracker)
|
||||||
|
EnableIssueDependencies bool `json:"enable_issue_dependencies"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalTracker represents settings for external tracker
|
||||||
|
type ExternalTracker struct {
|
||||||
|
// URL of external issue tracker.
|
||||||
|
ExternalTrackerURL string `json:"external_tracker_url"`
|
||||||
|
// External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.
|
||||||
|
ExternalTrackerFormat string `json:"external_tracker_format"`
|
||||||
|
// External Issue Tracker Number Format, either `numeric` or `alphanumeric`
|
||||||
|
ExternalTrackerStyle string `json:"external_tracker_style"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalWiki represents setting for external wiki
|
||||||
|
type ExternalWiki struct {
|
||||||
|
// URL of external wiki.
|
||||||
|
ExternalWikiURL string `json:"external_wiki_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repository represents a repository
|
||||||
|
type Repository struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Owner *User `json:"owner"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Empty bool `json:"empty"`
|
||||||
|
Private bool `json:"private"`
|
||||||
|
Fork bool `json:"fork"`
|
||||||
|
Template bool `json:"template"`
|
||||||
|
Parent *Repository `json:"parent"`
|
||||||
|
Mirror bool `json:"mirror"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
SSHURL string `json:"ssh_url"`
|
||||||
|
CloneURL string `json:"clone_url"`
|
||||||
|
OriginalURL string `json:"original_url"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Stars int `json:"stars_count"`
|
||||||
|
Forks int `json:"forks_count"`
|
||||||
|
Watchers int `json:"watchers_count"`
|
||||||
|
OpenIssues int `json:"open_issues_count"`
|
||||||
|
OpenPulls int `json:"open_pr_counter"`
|
||||||
|
Releases int `json:"release_counter"`
|
||||||
|
DefaultBranch string `json:"default_branch"`
|
||||||
|
Archived bool `json:"archived"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
Permissions *Permission `json:"permissions,omitempty"`
|
||||||
|
HasIssues bool `json:"has_issues"`
|
||||||
|
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
|
||||||
|
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
|
||||||
|
HasWiki bool `json:"has_wiki"`
|
||||||
|
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||||
|
HasPullRequests bool `json:"has_pull_requests"`
|
||||||
|
HasProjects bool `json:"has_projects"`
|
||||||
|
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
|
||||||
|
AllowMerge bool `json:"allow_merge_commits"`
|
||||||
|
AllowRebase bool `json:"allow_rebase"`
|
||||||
|
AllowRebaseMerge bool `json:"allow_rebase_explicit"`
|
||||||
|
AllowSquash bool `json:"allow_squash_merge"`
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
Internal bool `json:"internal"`
|
||||||
|
MirrorInterval string `json:"mirror_interval"`
|
||||||
|
DefaultMergeStyle MergeStyle `json:"default_merge_style"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoType represent repo type
|
||||||
|
type RepoType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RepoTypeNone dont specify a type
|
||||||
|
RepoTypeNone RepoType = ""
|
||||||
|
// RepoTypeSource is the default repo type
|
||||||
|
RepoTypeSource RepoType = "source"
|
||||||
|
// RepoTypeFork is a repo witch was forked from an other one
|
||||||
|
RepoTypeFork RepoType = "fork"
|
||||||
|
// RepoTypeMirror represents an mirror repo
|
||||||
|
RepoTypeMirror RepoType = "mirror"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TrustModel represent how git signatures are handled in a repository
|
||||||
|
type TrustModel string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TrustModelDefault use TM set by global config
|
||||||
|
TrustModelDefault TrustModel = "default"
|
||||||
|
// TrustModelCollaborator gpg signature has to be owned by a repo collaborator
|
||||||
|
TrustModelCollaborator TrustModel = "collaborator"
|
||||||
|
// TrustModelCommitter gpg signature has to match committer
|
||||||
|
TrustModelCommitter TrustModel = "committer"
|
||||||
|
// TrustModelCollaboratorCommitter gpg signature has to match committer and owned by a repo collaborator
|
||||||
|
TrustModelCollaboratorCommitter TrustModel = "collaboratorcommitter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListReposOptions options for listing repositories
|
||||||
|
type ListReposOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyRepos lists all repositories for the authenticated user that has access to.
|
||||||
|
func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/repos?%s", opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListUserRepos list all repositories of one user by user's name
|
||||||
|
func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgReposOptions options for a organization's repositories
|
||||||
|
type ListOrgReposOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrgRepos list all repositories of one organization by organization's name
|
||||||
|
func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := make([]*Repository, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchRepoOptions options for searching repositories
|
||||||
|
type SearchRepoOptions struct {
|
||||||
|
ListOptions
|
||||||
|
|
||||||
|
// The keyword to query
|
||||||
|
Keyword string
|
||||||
|
// Limit search to repositories with keyword as topic
|
||||||
|
KeywordIsTopic bool
|
||||||
|
// Include search of keyword within repository description
|
||||||
|
KeywordInDescription bool
|
||||||
|
|
||||||
|
/*
|
||||||
|
User Filter
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Repo Owner
|
||||||
|
OwnerID int64
|
||||||
|
// Stared By UserID
|
||||||
|
StarredByUserID int64
|
||||||
|
|
||||||
|
/*
|
||||||
|
Repo Attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
// pubic, private or all repositories (defaults to all)
|
||||||
|
IsPrivate *bool
|
||||||
|
// archived, non-archived or all repositories (defaults to all)
|
||||||
|
IsArchived *bool
|
||||||
|
// Exclude template repos from search
|
||||||
|
ExcludeTemplate bool
|
||||||
|
// Filter by "fork", "source", "mirror"
|
||||||
|
Type RepoType
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sort Filters
|
||||||
|
*/
|
||||||
|
|
||||||
|
// sort repos by attribute. Supported values are "alpha", "created", "updated", "size", and "id". Default is "alpha"
|
||||||
|
Sort string
|
||||||
|
// sort order, either "asc" (ascending) or "desc" (descending). Default is "asc", ignored if "sort" is not specified.
|
||||||
|
Order string
|
||||||
|
// Repo owner to prioritize in the results
|
||||||
|
PrioritizedByOwnerID int64
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cover EdgeCases
|
||||||
|
*/
|
||||||
|
// if set all other options are ignored and this string is used as query
|
||||||
|
RawQuery string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *SearchRepoOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if opt.Keyword != "" {
|
||||||
|
query.Add("q", opt.Keyword)
|
||||||
|
}
|
||||||
|
if opt.KeywordIsTopic {
|
||||||
|
query.Add("topic", "true")
|
||||||
|
}
|
||||||
|
if opt.KeywordInDescription {
|
||||||
|
query.Add("includeDesc", "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
// User Filter
|
||||||
|
if opt.OwnerID > 0 {
|
||||||
|
query.Add("uid", fmt.Sprintf("%d", opt.OwnerID))
|
||||||
|
query.Add("exclusive", "true")
|
||||||
|
}
|
||||||
|
if opt.StarredByUserID > 0 {
|
||||||
|
query.Add("starredBy", fmt.Sprintf("%d", opt.StarredByUserID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repo Attributes
|
||||||
|
if opt.IsPrivate != nil {
|
||||||
|
query.Add("is_private", fmt.Sprintf("%v", opt.IsPrivate))
|
||||||
|
}
|
||||||
|
if opt.IsArchived != nil {
|
||||||
|
query.Add("archived", fmt.Sprintf("%v", opt.IsArchived))
|
||||||
|
}
|
||||||
|
if opt.ExcludeTemplate {
|
||||||
|
query.Add("template", "false")
|
||||||
|
}
|
||||||
|
if len(opt.Type) != 0 {
|
||||||
|
query.Add("mode", string(opt.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort Filters
|
||||||
|
if opt.Sort != "" {
|
||||||
|
query.Add("sort", opt.Sort)
|
||||||
|
}
|
||||||
|
if opt.PrioritizedByOwnerID > 0 {
|
||||||
|
query.Add("priority_owner_id", fmt.Sprintf("%d", opt.PrioritizedByOwnerID))
|
||||||
|
}
|
||||||
|
if opt.Order != "" {
|
||||||
|
query.Add("order", opt.Order)
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
type searchRepoResponse struct {
|
||||||
|
Repos []*Repository `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchRepos searches for repositories matching the given filters
|
||||||
|
func (c *Client) SearchRepos(opt SearchRepoOptions) ([]*Repository, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
repos := new(searchRepoResponse)
|
||||||
|
|
||||||
|
link, _ := url.Parse("/repos/search")
|
||||||
|
|
||||||
|
if len(opt.RawQuery) != 0 {
|
||||||
|
link.RawQuery = opt.RawQuery
|
||||||
|
} else {
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
// IsPrivate only works on gitea >= 1.12.0
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil && opt.IsPrivate != nil {
|
||||||
|
if *opt.IsPrivate {
|
||||||
|
// private repos only not supported on gitea <= 1.11.x
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link.Query().Add("private", "false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &repos)
|
||||||
|
return repos.Repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepoOption options when creating repository
|
||||||
|
type CreateRepoOption struct {
|
||||||
|
// Name of the repository to create
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Description of the repository to create
|
||||||
|
Description string `json:"description"`
|
||||||
|
// Whether the repository is private
|
||||||
|
Private bool `json:"private"`
|
||||||
|
// Issue Label set to use
|
||||||
|
IssueLabels string `json:"issue_labels"`
|
||||||
|
// Whether the repository should be auto-intialized?
|
||||||
|
AutoInit bool `json:"auto_init"`
|
||||||
|
// Whether the repository is template
|
||||||
|
Template bool `json:"template"`
|
||||||
|
// Gitignores to use
|
||||||
|
Gitignores string `json:"gitignores"`
|
||||||
|
// License to use
|
||||||
|
License string `json:"license"`
|
||||||
|
// Readme of the repository to create
|
||||||
|
Readme string `json:"readme"`
|
||||||
|
// DefaultBranch of the repository (used when initializes and in template)
|
||||||
|
DefaultBranch string `json:"default_branch"`
|
||||||
|
// TrustModel of the repository
|
||||||
|
TrustModel TrustModel `json:"trust_model"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateRepoOption struct
|
||||||
|
func (opt CreateRepoOption) Validate(c *Client) error {
|
||||||
|
if len(strings.TrimSpace(opt.Name)) == 0 {
|
||||||
|
return fmt.Errorf("name is empty")
|
||||||
|
}
|
||||||
|
if len(opt.Name) > 100 {
|
||||||
|
return fmt.Errorf("name has more than 100 chars")
|
||||||
|
}
|
||||||
|
if len(opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("name has more than 255 chars")
|
||||||
|
}
|
||||||
|
if len(opt.DefaultBranch) > 100 {
|
||||||
|
return fmt.Errorf("name has more than 100 chars")
|
||||||
|
}
|
||||||
|
if len(opt.TrustModel) != 0 {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepo creates a repository for authenticated user.
|
||||||
|
func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrgRepo creates an organization repository for authenticated user.
|
||||||
|
func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&org); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepo returns information of a repository of given owner.
|
||||||
|
func (c *Client) GetRepo(owner, reponame string) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoByID returns information of a repository by a giver repository ID.
|
||||||
|
func (c *Client) GetRepoByID(id int64) (*Repository, *Response, error) {
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repositories/%d", id), nil, nil, repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepoOption options when editing a repository's properties
|
||||||
|
type EditRepoOption struct {
|
||||||
|
// name of the repository
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
// a short description of the repository.
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
// a URL with more information about the repository.
|
||||||
|
Website *string `json:"website,omitempty"`
|
||||||
|
// either `true` to make the repository private or `false` to make it public.
|
||||||
|
// Note: you will get a 422 error if the organization restricts changing repository visibility to organization
|
||||||
|
// owners and a non-owner tries to change the value of private.
|
||||||
|
Private *bool `json:"private,omitempty"`
|
||||||
|
// either `true` to make this repository a template or `false` to make it a normal repository
|
||||||
|
Template *bool `json:"template,omitempty"`
|
||||||
|
// either `true` to enable issues for this repository or `false` to disable them.
|
||||||
|
HasIssues *bool `json:"has_issues,omitempty"`
|
||||||
|
// set this structure to configure internal issue tracker (requires has_issues)
|
||||||
|
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
|
||||||
|
// set this structure to use external issue tracker (requires has_issues)
|
||||||
|
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
|
||||||
|
// either `true` to enable the wiki for this repository or `false` to disable it.
|
||||||
|
HasWiki *bool `json:"has_wiki,omitempty"`
|
||||||
|
// set this structure to use external wiki instead of internal (requires has_wiki)
|
||||||
|
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||||
|
// sets the default branch for this repository.
|
||||||
|
DefaultBranch *string `json:"default_branch,omitempty"`
|
||||||
|
// either `true` to allow pull requests, or `false` to prevent pull request.
|
||||||
|
HasPullRequests *bool `json:"has_pull_requests,omitempty"`
|
||||||
|
// either `true` to enable project unit, or `false` to disable them.
|
||||||
|
HasProjects *bool `json:"has_projects,omitempty"`
|
||||||
|
// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`.
|
||||||
|
IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"`
|
||||||
|
// either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`.
|
||||||
|
AllowMerge *bool `json:"allow_merge_commits,omitempty"`
|
||||||
|
// either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging. `has_pull_requests` must be `true`.
|
||||||
|
AllowRebase *bool `json:"allow_rebase,omitempty"`
|
||||||
|
// either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits. `has_pull_requests` must be `true`.
|
||||||
|
AllowRebaseMerge *bool `json:"allow_rebase_explicit,omitempty"`
|
||||||
|
// either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging. `has_pull_requests` must be `true`.
|
||||||
|
AllowSquash *bool `json:"allow_squash_merge,omitempty"`
|
||||||
|
// set to `true` to archive this repository.
|
||||||
|
Archived *bool `json:"archived,omitempty"`
|
||||||
|
// set to a string like `8h30m0s` to set the mirror interval time
|
||||||
|
MirrorInterval *string `json:"mirror_interval,omitempty"`
|
||||||
|
// either `true` to allow mark pr as merged manually, or `false` to prevent it. `has_pull_requests` must be `true`.
|
||||||
|
AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
|
||||||
|
// either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur.
|
||||||
|
AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"`
|
||||||
|
// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`.
|
||||||
|
DefaultMergeStyle *MergeStyle `json:"default_merge_style,omitempty"`
|
||||||
|
// set to `true` to archive this repository.
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditRepo edit the properties of a repository
|
||||||
|
func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepo deletes a repository of user or organization.
|
||||||
|
func (c *Client) DeleteRepo(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorSync adds a mirrored repository to the mirror sync queue.
|
||||||
|
func (c *Client) MirrorSync(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoLanguages return language stats of a repo
|
||||||
|
func (c *Client) GetRepoLanguages(owner, repo string) (map[string]int64, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
langMap := make(map[string]int64)
|
||||||
|
|
||||||
|
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/languages", owner, repo), jsonHeader, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(data, &langMap); err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return langMap, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArchiveType represent supported archive formats by gitea
|
||||||
|
type ArchiveType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ZipArchive represent zip format
|
||||||
|
ZipArchive ArchiveType = ".zip"
|
||||||
|
// TarGZArchive represent tar.gz format
|
||||||
|
TarGZArchive ArchiveType = ".tar.gz"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetArchive get an archive of a repository by git reference
|
||||||
|
// e.g.: ref -> master, 70b7c74b33, v1.2.1, ...
|
||||||
|
func (c *Client) GetArchive(owner, repo, ref string, ext ArchiveType) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetArchiveReader gets a `git archive` for a particular tree-ish git reference
|
||||||
|
// such as a branch name (`master`), a commit hash (`70b7c74b33`), a tag
|
||||||
|
// (`v1.2.1`). The archive is returned as a byte stream in a ReadCloser. It is
|
||||||
|
// the responsibility of the client to close the reader.
|
||||||
|
func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io.ReadCloser, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
resp, err := c.doRequest("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := statusCodeToErr(resp); err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Body, resp, nil
|
||||||
|
}
|
143
vendor/code.gitea.io/sdk/gitea/repo_branch.go
generated
vendored
Normal file
143
vendor/code.gitea.io/sdk/gitea/repo_branch.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PayloadUser represents the author or committer of a commit
|
||||||
|
type PayloadUser struct {
|
||||||
|
// Full name of the commit author
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
UserName string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayloadCommit represents a commit
|
||||||
|
type PayloadCommit struct {
|
||||||
|
// sha1 hash of the commit
|
||||||
|
ID string `json:"id"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Author *PayloadUser `json:"author"`
|
||||||
|
Committer *PayloadUser `json:"committer"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
Timestamp time.Time `json:"timestamp"`
|
||||||
|
Added []string `json:"added"`
|
||||||
|
Removed []string `json:"removed"`
|
||||||
|
Modified []string `json:"modified"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayloadCommitVerification represents the GPG verification of a commit
|
||||||
|
type PayloadCommitVerification struct {
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
Payload string `json:"payload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch represents a repository branch
|
||||||
|
type Branch struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Commit *PayloadCommit `json:"commit"`
|
||||||
|
Protected bool `json:"protected"`
|
||||||
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
UserCanPush bool `json:"user_can_push"`
|
||||||
|
UserCanMerge bool `json:"user_can_merge"`
|
||||||
|
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoBranchesOptions options for listing a repository's branches
|
||||||
|
type ListRepoBranchesOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoBranches list all the branches of one repository
|
||||||
|
func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
branches := make([]*Branch, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches)
|
||||||
|
return branches, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoBranch get one branch's information of one repository
|
||||||
|
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
b := new(Branch)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return b, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoBranch delete a branch in a repository
|
||||||
|
func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
return status == 204, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchOption options when creating a branch in a repository
|
||||||
|
type CreateBranchOption struct {
|
||||||
|
// Name of the branch to create
|
||||||
|
BranchName string `json:"new_branch_name"`
|
||||||
|
// Name of the old branch to create from (optional)
|
||||||
|
OldBranchName string `json:"old_branch_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the CreateBranchOption struct
|
||||||
|
func (opt CreateBranchOption) Validate() error {
|
||||||
|
if len(opt.BranchName) == 0 {
|
||||||
|
return fmt.Errorf("BranchName is empty")
|
||||||
|
}
|
||||||
|
if len(opt.BranchName) > 100 {
|
||||||
|
return fmt.Errorf("BranchName to long")
|
||||||
|
}
|
||||||
|
if len(opt.OldBranchName) > 100 {
|
||||||
|
return fmt.Errorf("OldBranchName to long")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranch creates a branch for a user's repository
|
||||||
|
func (c *Client) CreateBranch(owner, repo string, opt CreateBranchOption) (*Branch, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
branch := new(Branch)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branches", owner, repo), jsonHeader, bytes.NewReader(body), branch)
|
||||||
|
return branch, resp, err
|
||||||
|
}
|
168
vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
generated
vendored
Normal file
168
vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BranchProtection represents a branch protection for a repository
|
||||||
|
type BranchProtection struct {
|
||||||
|
BranchName string `json:"branch_name"`
|
||||||
|
EnablePush bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
|
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||||
|
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||||
|
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
|
||||||
|
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||||
|
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||||
|
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchProtectionOption options for creating a branch protection
|
||||||
|
type CreateBranchProtectionOption struct {
|
||||||
|
BranchName string `json:"branch_name"`
|
||||||
|
EnablePush bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
|
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||||
|
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||||
|
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
|
||||||
|
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||||
|
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||||
|
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditBranchProtectionOption options for editing a branch protection
|
||||||
|
type EditBranchProtectionOption struct {
|
||||||
|
EnablePush *bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist *bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
EnableStatusCheck *bool `json:"enable_status_check"`
|
||||||
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
|
RequiredApprovals *int64 `json:"required_approvals"`
|
||||||
|
EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"`
|
||||||
|
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"`
|
||||||
|
BlockOnOfficialReviewRequests *bool `json:"block_on_official_review_requests"`
|
||||||
|
BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"`
|
||||||
|
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits *bool `json:"require_signed_commits"`
|
||||||
|
ProtectedFilePatterns *string `json:"protected_file_patterns"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBranchProtectionsOptions list branch protection options
|
||||||
|
type ListBranchProtectionsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBranchProtections list branch protections for a repo
|
||||||
|
func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bps := make([]*BranchProtection, 0, opt.PageSize)
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo))
|
||||||
|
link.RawQuery = opt.getURLQuery().Encode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &bps)
|
||||||
|
return bps, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBranchProtection gets a branch protection
|
||||||
|
func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bp := new(BranchProtection)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil, bp)
|
||||||
|
return bp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchProtection creates a branch protection for a repo
|
||||||
|
func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bp := new(BranchProtection)
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo), jsonHeader, bytes.NewReader(body), bp)
|
||||||
|
return bp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditBranchProtection edits a branch protection for a repo
|
||||||
|
func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
bp := new(BranchProtection)
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), bp)
|
||||||
|
return bp, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBranchProtection deletes a branch protection for a repo
|
||||||
|
func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
136
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go
generated
vendored
Normal file
136
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListCollaboratorsOptions options for listing a repository's collaborators
|
||||||
|
type ListCollaboratorsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCollaborators list a repository's collaborators
|
||||||
|
func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
collaborators := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/collaborators?%s", user, repo, opt.getURLQuery().Encode()),
|
||||||
|
nil, nil, &collaborators)
|
||||||
|
return collaborators, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCollaborator check if a user is a collaborator of a repository
|
||||||
|
func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
if status == 204 {
|
||||||
|
return true, resp, nil
|
||||||
|
}
|
||||||
|
return false, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCollaboratorOption options when adding a user as a collaborator of a repository
|
||||||
|
type AddCollaboratorOption struct {
|
||||||
|
Permission *AccessMode `json:"permission"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessMode represent the grade of access you have to something
|
||||||
|
type AccessMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AccessModeNone no access
|
||||||
|
AccessModeNone AccessMode = "none"
|
||||||
|
// AccessModeRead read access
|
||||||
|
AccessModeRead AccessMode = "read"
|
||||||
|
// AccessModeWrite write access
|
||||||
|
AccessModeWrite AccessMode = "write"
|
||||||
|
// AccessModeAdmin admin access
|
||||||
|
AccessModeAdmin AccessMode = "admin"
|
||||||
|
// AccessModeOwner owner
|
||||||
|
AccessModeOwner AccessMode = "owner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Validate the AddCollaboratorOption struct
|
||||||
|
func (opt AddCollaboratorOption) Validate() error {
|
||||||
|
if opt.Permission != nil {
|
||||||
|
if *opt.Permission == AccessModeOwner {
|
||||||
|
*opt.Permission = AccessModeAdmin
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if *opt.Permission == AccessModeNone {
|
||||||
|
opt.Permission = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if *opt.Permission != AccessModeRead && *opt.Permission != AccessModeWrite && *opt.Permission != AccessModeAdmin {
|
||||||
|
return fmt.Errorf("permission mode invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCollaborator add some user as a collaborator of a repository
|
||||||
|
func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCollaborator remove a collaborator from a repository
|
||||||
|
func (c *Client) DeleteCollaborator(user, repo, collaborator string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetReviewers return all users that can be requested to review in this repo
|
||||||
|
func (c *Client) GetReviewers(user, repo string) ([]*User, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
reviewers := make([]*User, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/reviewers", user, repo), nil, nil, &reviewers)
|
||||||
|
return reviewers, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAssignees return all users that have write access and can be assigned to issues
|
||||||
|
func (c *Client) GetAssignees(user, repo string) ([]*User, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
assignees := make([]*User, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/assignees", user, repo), nil, nil, &assignees)
|
||||||
|
return assignees, resp, err
|
||||||
|
}
|
101
vendor/code.gitea.io/sdk/gitea/repo_commit.go
generated
vendored
Normal file
101
vendor/code.gitea.io/sdk/gitea/repo_commit.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2018 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Identity for a person's identity like an author or committer
|
||||||
|
type Identity struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitMeta contains meta information of a commit in terms of API.
|
||||||
|
type CommitMeta struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitUser contains information of a user in the context of a commit.
|
||||||
|
type CommitUser struct {
|
||||||
|
Identity
|
||||||
|
Date string `json:"date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoCommit contains information of a commit in the context of a repository.
|
||||||
|
type RepoCommit struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
Author *CommitUser `json:"author"`
|
||||||
|
Committer *CommitUser `json:"committer"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tree *CommitMeta `json:"tree"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit contains information generated from a Git commit.
|
||||||
|
type Commit struct {
|
||||||
|
*CommitMeta
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
RepoCommit *RepoCommit `json:"commit"`
|
||||||
|
Author *User `json:"author"`
|
||||||
|
Committer *User `json:"committer"`
|
||||||
|
Parents []*CommitMeta `json:"parents"`
|
||||||
|
Files []*CommitAffectedFiles `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
|
||||||
|
type CommitDateOptions struct {
|
||||||
|
Author time.Time `json:"author"`
|
||||||
|
Committer time.Time `json:"committer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitAffectedFiles store information about files affected by the commit
|
||||||
|
type CommitAffectedFiles struct {
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSingleCommit returns a single commit
|
||||||
|
func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &commitID); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
commit := new(Commit)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit)
|
||||||
|
return commit, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCommitOptions list commit options
|
||||||
|
type ListCommitOptions struct {
|
||||||
|
ListOptions
|
||||||
|
//SHA or branch to start listing commits from (usually 'master')
|
||||||
|
SHA string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListCommitOptions) QueryEncode() string {
|
||||||
|
query := opt.ListOptions.getURLQuery()
|
||||||
|
if opt.SHA != "" {
|
||||||
|
query.Add("sha", opt.SHA)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoCommits return list of commits from a repo
|
||||||
|
func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/commits", user, repo))
|
||||||
|
opt.setDefaults()
|
||||||
|
commits := make([]*Commit, 0, opt.PageSize)
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
|
||||||
|
return commits, resp, err
|
||||||
|
}
|
247
vendor/code.gitea.io/sdk/gitea/repo_file.go
generated
vendored
Normal file
247
vendor/code.gitea.io/sdk/gitea/repo_file.go
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileOptions options for all file APIs
|
||||||
|
type FileOptions struct {
|
||||||
|
// message (optional) for the commit of this file. if not supplied, a default message will be used
|
||||||
|
Message string `json:"message"`
|
||||||
|
// branch (optional) to base this file from. if not given, the default branch is used
|
||||||
|
BranchName string `json:"branch"`
|
||||||
|
// new_branch (optional) will make a new branch from `branch` before creating the file
|
||||||
|
NewBranchName string `json:"new_branch"`
|
||||||
|
// `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
Author Identity `json:"author"`
|
||||||
|
Committer Identity `json:"committer"`
|
||||||
|
Dates CommitDateOptions `json:"dates"`
|
||||||
|
// Add a Signed-off-by trailer by the committer at the end of the commit log message.
|
||||||
|
Signoff bool `json:"signoff"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFileOptions options for creating files
|
||||||
|
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
type CreateFileOptions struct {
|
||||||
|
FileOptions
|
||||||
|
// content must be base64 encoded
|
||||||
|
// required: true
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFileOptions options for deleting files (used for other File structs below)
|
||||||
|
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
type DeleteFileOptions struct {
|
||||||
|
FileOptions
|
||||||
|
// sha is the SHA for the file that already exists
|
||||||
|
// required: true
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFileOptions options for updating files
|
||||||
|
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
|
type UpdateFileOptions struct {
|
||||||
|
FileOptions
|
||||||
|
// sha is the SHA for the file that already exists
|
||||||
|
// required: true
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
// content must be base64 encoded
|
||||||
|
// required: true
|
||||||
|
Content string `json:"content"`
|
||||||
|
// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL
|
||||||
|
FromPath string `json:"from_path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileLinksResponse contains the links for a repo's file
|
||||||
|
type FileLinksResponse struct {
|
||||||
|
Self *string `json:"self"`
|
||||||
|
GitURL *string `json:"git"`
|
||||||
|
HTMLURL *string `json:"html"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content
|
||||||
|
type ContentsResponse struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
// `type` will be `file`, `dir`, `symlink`, or `submodule`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
// `encoding` is populated when `type` is `file`, otherwise null
|
||||||
|
Encoding *string `json:"encoding"`
|
||||||
|
// `content` is populated when `type` is `file`, otherwise null
|
||||||
|
Content *string `json:"content"`
|
||||||
|
// `target` is populated when `type` is `symlink`, otherwise null
|
||||||
|
Target *string `json:"target"`
|
||||||
|
URL *string `json:"url"`
|
||||||
|
HTMLURL *string `json:"html_url"`
|
||||||
|
GitURL *string `json:"git_url"`
|
||||||
|
DownloadURL *string `json:"download_url"`
|
||||||
|
// `submodule_git_url` is populated when `type` is `submodule`, otherwise null
|
||||||
|
SubmoduleGitURL *string `json:"submodule_git_url"`
|
||||||
|
Links *FileLinksResponse `json:"_links"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileCommitResponse contains information generated from a Git commit for a repo's file.
|
||||||
|
type FileCommitResponse struct {
|
||||||
|
CommitMeta
|
||||||
|
HTMLURL string `json:"html_url"`
|
||||||
|
Author *CommitUser `json:"author"`
|
||||||
|
Committer *CommitUser `json:"committer"`
|
||||||
|
Parents []*CommitMeta `json:"parents"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tree *CommitMeta `json:"tree"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileResponse contains information about a repo's file
|
||||||
|
type FileResponse struct {
|
||||||
|
Content *ContentsResponse `json:"content"`
|
||||||
|
Commit *FileCommitResponse `json:"commit"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileDeleteResponse contains information about a repo's file that was deleted
|
||||||
|
type FileDeleteResponse struct {
|
||||||
|
Content interface{} `json:"content"` // to be set to nil
|
||||||
|
Commit *FileCommitResponse `json:"commit"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFile downloads a file of repository, ref can be branch/tag/commit.
|
||||||
|
// e.g.: ref -> master, filepath -> README.md (no leading slash)
|
||||||
|
func (c *Client) GetFile(owner, repo, ref, filepath string) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", owner, repo, ref, filepath), nil, nil)
|
||||||
|
}
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetContents get the metadata and contents of a file in a repository
|
||||||
|
// ref is optional
|
||||||
|
func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, *Response, error) {
|
||||||
|
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
cr := new(ContentsResponse)
|
||||||
|
if json.Unmarshal(data, &cr) != nil {
|
||||||
|
return nil, resp, fmt.Errorf("expect file, got directory")
|
||||||
|
}
|
||||||
|
return cr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListContents gets a list of entries in a dir
|
||||||
|
// ref is optional
|
||||||
|
func (c *Client) ListContents(owner, repo, ref, filepath string) ([]*ContentsResponse, *Response, error) {
|
||||||
|
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
crl := make([]*ContentsResponse, 0)
|
||||||
|
if json.Unmarshal(data, &crl) != nil {
|
||||||
|
return nil, resp, fmt.Errorf("expect directory, got file")
|
||||||
|
}
|
||||||
|
return crl, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getDirOrFileContents(owner, repo, ref, filepath string) ([]byte, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(strings.TrimPrefix(filepath, "/"))
|
||||||
|
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), jsonHeader, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateFile create a file in a repository
|
||||||
|
func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, *Response, error) {
|
||||||
|
var err error
|
||||||
|
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
fr := new(FileResponse)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
|
||||||
|
return fr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFile update a file in a repository
|
||||||
|
func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, *Response, error) {
|
||||||
|
var err error
|
||||||
|
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
fr := new(FileResponse)
|
||||||
|
resp, err := c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
|
||||||
|
return fr, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFile delete a file from repository
|
||||||
|
func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) (*Response, error) {
|
||||||
|
var err error
|
||||||
|
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
filepath = pathEscapeSegments(filepath)
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status != 200 && status != 204 {
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) setDefaultBranchForOldVersions(owner, repo, branch string) (string, error) {
|
||||||
|
if len(branch) == 0 {
|
||||||
|
// Gitea >= 1.12.0 Use DefaultBranch on "", mimic this for older versions
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
|
||||||
|
r, _, err := c.GetRepo(owner, repo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.DefaultBranch, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return branch, nil
|
||||||
|
}
|
91
vendor/code.gitea.io/sdk/gitea/repo_key.go
generated
vendored
Normal file
91
vendor/code.gitea.io/sdk/gitea/repo_key.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeployKey a deploy key
|
||||||
|
type DeployKey struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
KeyID int64 `json:"key_id"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Fingerprint string `json:"fingerprint"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
ReadOnly bool `json:"read_only"`
|
||||||
|
Repository *Repository `json:"repository,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDeployKeysOptions options for listing a repository's deploy keys
|
||||||
|
type ListDeployKeysOptions struct {
|
||||||
|
ListOptions
|
||||||
|
KeyID int64
|
||||||
|
Fingerprint string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *ListDeployKeysOptions) QueryEncode() string {
|
||||||
|
query := opt.getURLQuery()
|
||||||
|
if opt.KeyID > 0 {
|
||||||
|
query.Add("key_id", fmt.Sprintf("%d", opt.KeyID))
|
||||||
|
}
|
||||||
|
if len(opt.Fingerprint) > 0 {
|
||||||
|
query.Add("fingerprint", opt.Fingerprint)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListDeployKeys list all the deploy keys of one repository
|
||||||
|
func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/keys", user, repo))
|
||||||
|
opt.setDefaults()
|
||||||
|
link.RawQuery = opt.QueryEncode()
|
||||||
|
keys := make([]*DeployKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDeployKey get one deploy key with key id
|
||||||
|
func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(DeployKey)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDeployKey options when create one deploy key
|
||||||
|
func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(DeployKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDeployKey delete deploy key with key id
|
||||||
|
func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
132
vendor/code.gitea.io/sdk/gitea/repo_migrate.go
generated
vendored
Normal file
132
vendor/code.gitea.io/sdk/gitea/repo_migrate.go
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitServiceType represents a git service
|
||||||
|
type GitServiceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// GitServicePlain represents a plain git service
|
||||||
|
GitServicePlain GitServiceType = "git"
|
||||||
|
//GitServiceGithub represents github.com
|
||||||
|
GitServiceGithub GitServiceType = "github"
|
||||||
|
// GitServiceGitlab represents a gitlab service
|
||||||
|
GitServiceGitlab GitServiceType = "gitlab"
|
||||||
|
// GitServiceGitea represents a gitea service
|
||||||
|
GitServiceGitea GitServiceType = "gitea"
|
||||||
|
// GitServiceGogs represents a gogs service
|
||||||
|
GitServiceGogs GitServiceType = "gogs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateRepoOption options for migrating a repository from an external service
|
||||||
|
type MigrateRepoOption struct {
|
||||||
|
RepoName string `json:"repo_name"`
|
||||||
|
RepoOwner string `json:"repo_owner"`
|
||||||
|
// deprecated use RepoOwner
|
||||||
|
RepoOwnerID int64 `json:"uid"`
|
||||||
|
CloneAddr string `json:"clone_addr"`
|
||||||
|
Service GitServiceType `json:"service"`
|
||||||
|
AuthUsername string `json:"auth_username"`
|
||||||
|
AuthPassword string `json:"auth_password"`
|
||||||
|
AuthToken string `json:"auth_token"`
|
||||||
|
Mirror bool `json:"mirror"`
|
||||||
|
Private bool `json:"private"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Wiki bool `json:"wiki"`
|
||||||
|
Milestones bool `json:"milestones"`
|
||||||
|
Labels bool `json:"labels"`
|
||||||
|
Issues bool `json:"issues"`
|
||||||
|
PullRequests bool `json:"pull_requests"`
|
||||||
|
Releases bool `json:"releases"`
|
||||||
|
MirrorInterval string `json:"mirror_interval"`
|
||||||
|
LFS bool `json:"lfs"`
|
||||||
|
LFSEndpoint string `json:"lfs_endpoint"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the MigrateRepoOption struct
|
||||||
|
func (opt *MigrateRepoOption) Validate(c *Client) error {
|
||||||
|
// check user options
|
||||||
|
if len(opt.CloneAddr) == 0 {
|
||||||
|
return fmt.Errorf("CloneAddr required")
|
||||||
|
}
|
||||||
|
if len(opt.RepoName) == 0 {
|
||||||
|
return fmt.Errorf("RepoName required")
|
||||||
|
} else if len(opt.RepoName) > 100 {
|
||||||
|
return fmt.Errorf("RepoName to long")
|
||||||
|
}
|
||||||
|
if len(opt.Description) > 255 {
|
||||||
|
return fmt.Errorf("Description to long")
|
||||||
|
}
|
||||||
|
switch opt.Service {
|
||||||
|
case GitServiceGithub:
|
||||||
|
if len(opt.AuthToken) == 0 {
|
||||||
|
return fmt.Errorf("github requires token authentication")
|
||||||
|
}
|
||||||
|
case GitServiceGitlab, GitServiceGitea:
|
||||||
|
if len(opt.AuthToken) == 0 {
|
||||||
|
return fmt.Errorf("%s requires token authentication", opt.Service)
|
||||||
|
}
|
||||||
|
// Gitlab is supported since 1.12.0 but api cant handle it until 1.13.0
|
||||||
|
// https://github.com/go-gitea/gitea/pull/12672
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||||
|
return fmt.Errorf("migrate from service %s need gitea >= 1.13.0", opt.Service)
|
||||||
|
}
|
||||||
|
case GitServiceGogs:
|
||||||
|
if len(opt.AuthToken) == 0 {
|
||||||
|
return fmt.Errorf("gogs requires token authentication")
|
||||||
|
}
|
||||||
|
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||||
|
return fmt.Errorf("migrate from service gogs need gitea >= 1.14.0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateRepo migrates a repository from other Git hosting sources for the authenticated user.
|
||||||
|
//
|
||||||
|
// To migrate a repository for a organization, the authenticated user must be a
|
||||||
|
// owner of the specified organization.
|
||||||
|
func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := opt.Validate(c); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
if len(opt.AuthToken) != 0 {
|
||||||
|
// gitea <= 1.12 dont understand AuthToken
|
||||||
|
opt.AuthUsername = opt.AuthToken
|
||||||
|
opt.AuthPassword, opt.AuthToken = "", ""
|
||||||
|
}
|
||||||
|
if len(opt.RepoOwner) != 0 {
|
||||||
|
// gitea <= 1.12 dont understand RepoOwner
|
||||||
|
u, _, err := c.GetUserInfo(opt.RepoOwner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.RepoOwnerID = u.ID
|
||||||
|
} else if opt.RepoOwnerID == 0 {
|
||||||
|
// gitea <= 1.12 require RepoOwnerID
|
||||||
|
u, _, err := c.GetMyUserInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.RepoOwnerID = u.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
78
vendor/code.gitea.io/sdk/gitea/repo_refs.go
generated
vendored
Normal file
78
vendor/code.gitea.io/sdk/gitea/repo_refs.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference represents a Git reference.
|
||||||
|
type Reference struct {
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Object *GitObject `json:"object"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitObject represents a Git object.
|
||||||
|
type GitObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoRef get one ref's information of one repository
|
||||||
|
func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = strings.TrimPrefix(ref, "refs/")
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
r := new(Reference)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil, &r)
|
||||||
|
if _, ok := err.(*json.UnmarshalTypeError); ok {
|
||||||
|
// Multiple refs
|
||||||
|
return nil, resp, errors.New("no exact match found for this ref")
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRepoRefs get list of ref's information of one repository
|
||||||
|
func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ref = strings.TrimPrefix(ref, "refs/")
|
||||||
|
ref = pathEscapeSegments(ref)
|
||||||
|
|
||||||
|
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to unmarshal single returned ref.
|
||||||
|
r := new(Reference)
|
||||||
|
refErr := json.Unmarshal(data, r)
|
||||||
|
if refErr == nil {
|
||||||
|
return []*Reference{r}, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to unmarshal multiple refs.
|
||||||
|
var rs []*Reference
|
||||||
|
refsErr := json.Unmarshal(data, &rs)
|
||||||
|
if refsErr == nil {
|
||||||
|
if len(rs) == 0 {
|
||||||
|
return nil, resp, errors.New("unexpected response: an array of refs with length 0")
|
||||||
|
}
|
||||||
|
return rs, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", refErr, refsErr)
|
||||||
|
}
|
96
vendor/code.gitea.io/sdk/gitea/repo_stars.go
generated
vendored
Normal file
96
vendor/code.gitea.io/sdk/gitea/repo_stars.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListStargazersOptions options for listing a repository's stargazers
|
||||||
|
type ListStargazersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoStargazers list a repository's stargazers
|
||||||
|
func (c *Client) ListRepoStargazers(user, repo string, opt ListStargazersOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
stargazers := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/stargazers?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &stargazers)
|
||||||
|
return stargazers, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStarredRepos returns the repos that the given user has starred
|
||||||
|
func (c *Client) GetStarredRepos(user string) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/starred", user), jsonHeader, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyStarredRepos returns the repos that the authenticated user has starred
|
||||||
|
func (c *Client) GetMyStarredRepos() ([]*Repository, *Response, error) {
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/starred", jsonHeader, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRepoStarring returns whether the authenticated user has starred the repo or not
|
||||||
|
func (c *Client) IsRepoStarring(user, repo string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||||
|
if resp != nil {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return true, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StarRepo star specified repo as the authenticated user
|
||||||
|
func (c *Client) StarRepo(user, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||||
|
if resp != nil {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return resp, nil
|
||||||
|
default:
|
||||||
|
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnStarRepo remove star to specified repo as the authenticated user
|
||||||
|
func (c *Client) UnStarRepo(user, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||||
|
if resp != nil {
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusNoContent:
|
||||||
|
return resp, nil
|
||||||
|
default:
|
||||||
|
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
130
vendor/code.gitea.io/sdk/gitea/repo_tag.go
generated
vendored
Normal file
130
vendor/code.gitea.io/sdk/gitea/repo_tag.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tag represents a repository tag
|
||||||
|
type Tag struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
Commit *CommitMeta `json:"commit"`
|
||||||
|
ZipballURL string `json:"zipball_url"`
|
||||||
|
TarballURL string `json:"tarball_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedTag represents an annotated tag
|
||||||
|
type AnnotatedTag struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Tagger *CommitUser `json:"tagger"`
|
||||||
|
Object *AnnotatedTagObject `json:"object"`
|
||||||
|
Verification *PayloadCommitVerification `json:"verification"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnotatedTagObject contains meta information of the tag object
|
||||||
|
type AnnotatedTagObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTagsOptions options for listing a repository's tags
|
||||||
|
type ListRepoTagsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTags list all the branches of one repository
|
||||||
|
func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
tags := make([]*Tag, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags)
|
||||||
|
return tags, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTag get the tag of a repository
|
||||||
|
func (c *Client) GetTag(user, repo, tag string) (*Tag, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Tag)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag), nil, nil, &t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAnnotatedTag get the tag object of an annotated tag (not lightweight tags) of a repository
|
||||||
|
func (c *Client) GetAnnotatedTag(user, repo, sha string) (*AnnotatedTag, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(AnnotatedTag)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/tags/%s", user, repo, sha), nil, nil, &t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTagOption options when creating a tag
|
||||||
|
type CreateTagOption struct {
|
||||||
|
TagName string `json:"tag_name"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Target string `json:"target"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates CreateTagOption
|
||||||
|
func (opt CreateTagOption) Validate() error {
|
||||||
|
if len(opt.TagName) == 0 {
|
||||||
|
return fmt.Errorf("TagName is required")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateTag create a new git tag in a repository
|
||||||
|
func (c *Client) CreateTag(user, repo string, opt CreateTagOption) (*Tag, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Tag)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/tags", user, repo), jsonHeader, bytes.NewReader(body), &t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteTag deletes a tag from a repository, if no release refers to it
|
||||||
|
func (c *Client) DeleteTag(user, repo, tag string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE",
|
||||||
|
fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag),
|
||||||
|
nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
65
vendor/code.gitea.io/sdk/gitea/repo_team.go
generated
vendored
Normal file
65
vendor/code.gitea.io/sdk/gitea/repo_team.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRepoTeams return teams from a repository
|
||||||
|
func (c *Client) GetRepoTeams(user, repo string) ([]*Team, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
teams := make([]*Team, 0, 5)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams", user, repo), nil, nil, &teams)
|
||||||
|
return teams, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRepoTeam add a team to a repository
|
||||||
|
func (c *Client) AddRepoTeam(user, repo, team string) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveRepoTeam delete a team from a repository
|
||||||
|
func (c *Client) RemoveRepoTeam(user, repo, team string) (*Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckRepoTeam check if team is assigned to repo by name and return it.
|
||||||
|
// If not assigned, it will return nil.
|
||||||
|
func (c *Client) CheckRepoTeam(user, repo, team string) (*Team, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(Team)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil, &t)
|
||||||
|
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||||
|
// if not found it's not an error, it indicates it's not assigned
|
||||||
|
return nil, resp, nil
|
||||||
|
}
|
||||||
|
return t, resp, err
|
||||||
|
}
|
65
vendor/code.gitea.io/sdk/gitea/repo_template.go
generated
vendored
Normal file
65
vendor/code.gitea.io/sdk/gitea/repo_template.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateRepoFromTemplateOption options when creating repository using a template
|
||||||
|
type CreateRepoFromTemplateOption struct {
|
||||||
|
// Owner is the organization or person who will own the new repository
|
||||||
|
Owner string `json:"owner"`
|
||||||
|
// Name of the repository to create
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Description of the repository to create
|
||||||
|
Description string `json:"description"`
|
||||||
|
// Private is whether the repository is private
|
||||||
|
Private bool `json:"private"`
|
||||||
|
// GitContent include git content of default branch in template repo
|
||||||
|
GitContent bool `json:"git_content"`
|
||||||
|
// Topics include topics of template repo
|
||||||
|
Topics bool `json:"topics"`
|
||||||
|
// GitHooks include git hooks of template repo
|
||||||
|
GitHooks bool `json:"git_hooks"`
|
||||||
|
// Webhooks include webhooks of template repo
|
||||||
|
Webhooks bool `json:"webhooks"`
|
||||||
|
// Avatar include avatar of the template repo
|
||||||
|
Avatar bool `json:"avatar"`
|
||||||
|
// Labels include labels of template repo
|
||||||
|
Labels bool `json:"labels"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate validates CreateRepoFromTemplateOption
|
||||||
|
func (opt CreateRepoFromTemplateOption) Validate() error {
|
||||||
|
if len(opt.Owner) == 0 {
|
||||||
|
return fmt.Errorf("field Owner is required")
|
||||||
|
}
|
||||||
|
if len(opt.Name) == 0 {
|
||||||
|
return fmt.Errorf("field Name is required")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRepoFromTemplate create a repository using a template
|
||||||
|
func (c *Client) CreateRepoFromTemplate(templateOwner, templateRepo string, opt CreateRepoFromTemplateOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&templateOwner, &templateRepo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := opt.Validate(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/generate", templateOwner, templateRepo), jsonHeader, bytes.NewReader(body), &repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
68
vendor/code.gitea.io/sdk/gitea/repo_topics.go
generated
vendored
Normal file
68
vendor/code.gitea.io/sdk/gitea/repo_topics.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListRepoTopicsOptions options for listing repo's topics
|
||||||
|
type ListRepoTopicsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// topicsList represents a list of repo's topics
|
||||||
|
type topicsList struct {
|
||||||
|
Topics []string `json:"topics"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRepoTopics list all repository's topics
|
||||||
|
func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
|
||||||
|
list := new(topicsList)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
return list.Topics, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRepoTopics replaces the list of repo's topics
|
||||||
|
func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
l := topicsList{Topics: list}
|
||||||
|
body, err := json.Marshal(&l)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRepoTopic adds a topic to a repo's topics list
|
||||||
|
func (c *Client) AddRepoTopic(user, repo, topic string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRepoTopic deletes a topic from repo's topics list
|
||||||
|
func (c *Client) DeleteRepoTopic(user, repo, topic string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
36
vendor/code.gitea.io/sdk/gitea/repo_transfer.go
generated
vendored
Normal file
36
vendor/code.gitea.io/sdk/gitea/repo_transfer.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TransferRepoOption options when transfer a repository's ownership
|
||||||
|
type TransferRepoOption struct {
|
||||||
|
// required: true
|
||||||
|
NewOwner string `json:"new_owner"`
|
||||||
|
// ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.
|
||||||
|
TeamIDs *[]int64 `json:"team_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransferRepo transfers the ownership of a repository
|
||||||
|
func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repo := new(Repository)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
|
||||||
|
return repo, resp, err
|
||||||
|
}
|
44
vendor/code.gitea.io/sdk/gitea/repo_tree.go
generated
vendored
Normal file
44
vendor/code.gitea.io/sdk/gitea/repo_tree.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitEntry represents a git tree
|
||||||
|
type GitEntry struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Mode string `json:"mode"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitTreeResponse returns a git tree
|
||||||
|
type GitTreeResponse struct {
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Entries []GitEntry `json:"tree"`
|
||||||
|
Truncated bool `json:"truncated"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
TotalCount int `json:"total_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTrees downloads a file of repository, ref can be branch/tag/commit.
|
||||||
|
// e.g.: ref -> master, tree -> macaron.go(no leading slash)
|
||||||
|
func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &repo, &ref); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
trees := new(GitTreeResponse)
|
||||||
|
var path = fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref)
|
||||||
|
if recursive {
|
||||||
|
path += "?recursive=1"
|
||||||
|
}
|
||||||
|
resp, err := c.getParsedResponse("GET", path, nil, nil, trees)
|
||||||
|
return trees, resp, err
|
||||||
|
}
|
87
vendor/code.gitea.io/sdk/gitea/repo_watch.go
generated
vendored
Normal file
87
vendor/code.gitea.io/sdk/gitea/repo_watch.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WatchInfo represents an API watch status of one repository
|
||||||
|
type WatchInfo struct {
|
||||||
|
Subscribed bool `json:"subscribed"`
|
||||||
|
Ignored bool `json:"ignored"`
|
||||||
|
Reason interface{} `json:"reason"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
RepositoryURL string `json:"repository_url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWatchedRepos list all the watched repos of user
|
||||||
|
func (c *Client) GetWatchedRepos(user string) ([]*Repository, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyWatchedRepos list repositories watched by the authenticated user
|
||||||
|
func (c *Client) GetMyWatchedRepos() ([]*Repository, *Response, error) {
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/subscriptions"), nil, nil, &repos)
|
||||||
|
return repos, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckRepoWatch check if the current user is watching a repo
|
||||||
|
func (c *Client) CheckRepoWatch(owner, repo string) (bool, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case http.StatusNotFound:
|
||||||
|
return false, resp, nil
|
||||||
|
case http.StatusOK:
|
||||||
|
return true, resp, nil
|
||||||
|
default:
|
||||||
|
return false, resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WatchRepo start to watch a repository
|
||||||
|
func (c *Client) WatchRepo(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusOK {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnWatchRepo stop to watch a repository
|
||||||
|
func (c *Client) UnWatchRepo(owner, repo string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if status == http.StatusNoContent {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
return resp, fmt.Errorf("unexpected Status: %d", status)
|
||||||
|
}
|
78
vendor/code.gitea.io/sdk/gitea/settings.go
generated
vendored
Normal file
78
vendor/code.gitea.io/sdk/gitea/settings.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
// GlobalUISettings represent the global ui settings of a gitea instance witch is exposed by API
|
||||||
|
type GlobalUISettings struct {
|
||||||
|
DefaultTheme string `json:"default_theme"`
|
||||||
|
AllowedReactions []string `json:"allowed_reactions"`
|
||||||
|
CustomEmojis []string `json:"custom_emojis"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalRepoSettings represent the global repository settings of a gitea instance witch is exposed by API
|
||||||
|
type GlobalRepoSettings struct {
|
||||||
|
MirrorsDisabled bool `json:"mirrors_disabled"`
|
||||||
|
HTTPGitDisabled bool `json:"http_git_disabled"`
|
||||||
|
MigrationsDisabled bool `json:"migrations_disabled"`
|
||||||
|
StarsDisabled bool `json:"stars_disabled"`
|
||||||
|
TimeTrackingDisabled bool `json:"time_tracking_disabled"`
|
||||||
|
LFSDisabled bool `json:"lfs_disabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalAPISettings contains global api settings exposed by it
|
||||||
|
type GlobalAPISettings struct {
|
||||||
|
MaxResponseItems int `json:"max_response_items"`
|
||||||
|
DefaultPagingNum int `json:"default_paging_num"`
|
||||||
|
DefaultGitTreesPerPage int `json:"default_git_trees_per_page"`
|
||||||
|
DefaultMaxBlobSize int64 `json:"default_max_blob_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalAttachmentSettings contains global Attachment settings exposed by API
|
||||||
|
type GlobalAttachmentSettings struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
AllowedTypes string `json:"allowed_types"`
|
||||||
|
MaxSize int64 `json:"max_size"`
|
||||||
|
MaxFiles int `json:"max_files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalUISettings get global ui settings witch are exposed by API
|
||||||
|
func (c *Client) GetGlobalUISettings() (*GlobalUISettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalUISettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/ui", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalRepoSettings get global repository settings witch are exposed by API
|
||||||
|
func (c *Client) GetGlobalRepoSettings() (*GlobalRepoSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalRepoSettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/repository", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalAPISettings get global api settings witch are exposed by it
|
||||||
|
func (c *Client) GetGlobalAPISettings() (*GlobalAPISettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalAPISettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/api", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGlobalAttachmentSettings get global repository settings witch are exposed by API
|
||||||
|
func (c *Client) GetGlobalAttachmentSettings() (*GlobalAttachmentSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
conf := new(GlobalAttachmentSettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/settings/attachment", jsonHeader, nil, &conf)
|
||||||
|
return conf, resp, err
|
||||||
|
}
|
108
vendor/code.gitea.io/sdk/gitea/status.go
generated
vendored
Normal file
108
vendor/code.gitea.io/sdk/gitea/status.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StatusState holds the state of a Status
|
||||||
|
// It can be "pending", "success", "error", "failure", and "warning"
|
||||||
|
type StatusState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StatusPending is for when the Status is Pending
|
||||||
|
StatusPending StatusState = "pending"
|
||||||
|
// StatusSuccess is for when the Status is Success
|
||||||
|
StatusSuccess StatusState = "success"
|
||||||
|
// StatusError is for when the Status is Error
|
||||||
|
StatusError StatusState = "error"
|
||||||
|
// StatusFailure is for when the Status is Failure
|
||||||
|
StatusFailure StatusState = "failure"
|
||||||
|
// StatusWarning is for when the Status is Warning
|
||||||
|
StatusWarning StatusState = "warning"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Status holds a single Status of a single Commit
|
||||||
|
type Status struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
State StatusState `json:"status"`
|
||||||
|
TargetURL string `json:"target_url"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Context string `json:"context"`
|
||||||
|
Creator *User `json:"creator"`
|
||||||
|
Created time.Time `json:"created_at"`
|
||||||
|
Updated time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStatusOption holds the information needed to create a new Status for a Commit
|
||||||
|
type CreateStatusOption struct {
|
||||||
|
State StatusState `json:"state"`
|
||||||
|
TargetURL string `json:"target_url"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Context string `json:"context"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStatus creates a new Status for a given Commit
|
||||||
|
func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
status := new(Status)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, url.QueryEscape(sha)), jsonHeader, bytes.NewReader(body), status)
|
||||||
|
return status, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListStatusesOption options for listing a repository's commit's statuses
|
||||||
|
type ListStatusesOption struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListStatuses returns all statuses for a given Commit by ref
|
||||||
|
func (c *Client) ListStatuses(owner, repo, ref string, opt ListStatusesOption) ([]*Status, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &ref); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
statuses := make([]*Status, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, ref, opt.getURLQuery().Encode()), jsonHeader, nil, &statuses)
|
||||||
|
return statuses, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CombinedStatus holds the combined state of several statuses for a single commit
|
||||||
|
type CombinedStatus struct {
|
||||||
|
State StatusState `json:"state"`
|
||||||
|
SHA string `json:"sha"`
|
||||||
|
TotalCount int `json:"total_count"`
|
||||||
|
Statuses []*Status `json:"statuses"`
|
||||||
|
Repository *Repository `json:"repository"`
|
||||||
|
CommitURL string `json:"commit_url"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCombinedStatus returns the CombinedStatus for a given Commit
|
||||||
|
func (c *Client) GetCombinedStatus(owner, repo, ref string) (*CombinedStatus, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&owner, &repo, &ref); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
status := new(CombinedStatus)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, ref), jsonHeader, nil, status)
|
||||||
|
|
||||||
|
// gitea api return empty body if nothing here jet
|
||||||
|
if resp != nil && resp.StatusCode == 200 && err != nil {
|
||||||
|
return status, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, resp, err
|
||||||
|
}
|
90
vendor/code.gitea.io/sdk/gitea/user.go
generated
vendored
Normal file
90
vendor/code.gitea.io/sdk/gitea/user.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// User represents a user
|
||||||
|
type User struct {
|
||||||
|
// the user's id
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
// the user's username
|
||||||
|
UserName string `json:"login"`
|
||||||
|
// the user's full name
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
// URL to the user's avatar
|
||||||
|
AvatarURL string `json:"avatar_url"`
|
||||||
|
// User locale
|
||||||
|
Language string `json:"language"`
|
||||||
|
// Is the user an administrator
|
||||||
|
IsAdmin bool `json:"is_admin"`
|
||||||
|
// Date and Time of last login
|
||||||
|
LastLogin time.Time `json:"last_login"`
|
||||||
|
// Date and Time of user creation
|
||||||
|
Created time.Time `json:"created"`
|
||||||
|
// Is user restricted
|
||||||
|
Restricted bool `json:"restricted"`
|
||||||
|
// Is user active
|
||||||
|
IsActive bool `json:"active"`
|
||||||
|
// Is user login prohibited
|
||||||
|
ProhibitLogin bool `json:"prohibit_login"`
|
||||||
|
// the user's location
|
||||||
|
Location string `json:"location"`
|
||||||
|
// the user's website
|
||||||
|
Website string `json:"website"`
|
||||||
|
// the user's description
|
||||||
|
Description string `json:"description"`
|
||||||
|
// User visibility level option
|
||||||
|
Visibility VisibleType `json:"visibility"`
|
||||||
|
|
||||||
|
// user counts
|
||||||
|
FollowerCount int `json:"followers_count"`
|
||||||
|
FollowingCount int `json:"following_count"`
|
||||||
|
StarredRepoCount int `json:"starred_repos_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserInfo get user info by user's name
|
||||||
|
func (c *Client) GetUserInfo(user string) (*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
u := new(User)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
|
||||||
|
return u, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyUserInfo get user info of current user
|
||||||
|
func (c *Client) GetMyUserInfo() (*User, *Response, error) {
|
||||||
|
u := new(User)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user", nil, nil, u)
|
||||||
|
return u, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserByID returns user by a given user ID
|
||||||
|
func (c *Client) GetUserByID(id int64) (*User, *Response, error) {
|
||||||
|
if id < 0 {
|
||||||
|
return nil, nil, fmt.Errorf("invalid user id %d", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
query := make(url.Values)
|
||||||
|
query.Add("uid", strconv.FormatInt(id, 10))
|
||||||
|
users, resp, err := c.searchUsers(query.Encode())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(users) == 1 {
|
||||||
|
return users[0], resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, resp, fmt.Errorf("user not found with id %d", id)
|
||||||
|
}
|
90
vendor/code.gitea.io/sdk/gitea/user_app.go
generated
vendored
Normal file
90
vendor/code.gitea.io/sdk/gitea/user_app.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AccessToken represents an API access token.
|
||||||
|
type AccessToken struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Token string `json:"sha1"`
|
||||||
|
TokenLastEight string `json:"token_last_eight"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAccessTokensOptions options for listing a users's access tokens
|
||||||
|
type ListAccessTokensOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAccessTokens lists all the access tokens of user
|
||||||
|
func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, *Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
username := c.username
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
if len(username) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||||
|
}
|
||||||
|
opts.setDefaults()
|
||||||
|
tokens := make([]*AccessToken, 0, opts.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", url.PathEscape(username), opts.getURLQuery().Encode()), jsonHeader, nil, &tokens)
|
||||||
|
return tokens, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAccessTokenOption options when create access token
|
||||||
|
type CreateAccessTokenOption struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAccessToken create one access token with options
|
||||||
|
func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, *Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
username := c.username
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
if len(username) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
t := new(AccessToken)
|
||||||
|
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", url.PathEscape(username)), jsonHeader, bytes.NewReader(body), t)
|
||||||
|
return t, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAccessToken delete token, identified by ID and if not available by name
|
||||||
|
func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
username := c.username
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
if len(username) == 0 {
|
||||||
|
return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = ""
|
||||||
|
|
||||||
|
switch reflect.ValueOf(value).Kind() {
|
||||||
|
case reflect.Int64:
|
||||||
|
token = fmt.Sprintf("%d", value.(int64))
|
||||||
|
case reflect.String:
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
token = value.(string)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("only string and int64 supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", url.PathEscape(username), url.PathEscape(token)), jsonHeader, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
64
vendor/code.gitea.io/sdk/gitea/user_email.go
generated
vendored
Normal file
64
vendor/code.gitea.io/sdk/gitea/user_email.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Email an email address belonging to a user
|
||||||
|
type Email struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
Primary bool `json:"primary"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmailsOptions options for listing current's user emails
|
||||||
|
type ListEmailsOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListEmails all the email addresses of user
|
||||||
|
func (c *Client) ListEmails(opt ListEmailsOptions) ([]*Email, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
emails := make([]*Email, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/emails?%s", opt.getURLQuery().Encode()), nil, nil, &emails)
|
||||||
|
return emails, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateEmailOption options when creating email addresses
|
||||||
|
type CreateEmailOption struct {
|
||||||
|
// email addresses to add
|
||||||
|
Emails []string `json:"emails"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEmail add one email to current user with options
|
||||||
|
func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, *Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
emails := make([]*Email, 0, 3)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), &emails)
|
||||||
|
return emails, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmailOption options when deleting email addresses
|
||||||
|
type DeleteEmailOption struct {
|
||||||
|
// email addresses to delete
|
||||||
|
Emails []string `json:"emails"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEmail delete one email of current users'
|
||||||
|
func (c *Client) DeleteEmail(opt DeleteEmailOption) (*Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body))
|
||||||
|
return resp, err
|
||||||
|
}
|
93
vendor/code.gitea.io/sdk/gitea/user_follow.go
generated
vendored
Normal file
93
vendor/code.gitea.io/sdk/gitea/user_follow.go
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// ListFollowersOptions options for listing followers
|
||||||
|
type ListFollowersOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyFollowers list all the followers of current user
|
||||||
|
func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/followers?%s", opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFollowers list all the followers of one user
|
||||||
|
func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFollowingOptions options for listing a user's users being followed
|
||||||
|
type ListFollowingOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyFollowing list all the users current user followed
|
||||||
|
func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/following?%s", opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFollowing list all the users the user followed
|
||||||
|
func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
users := make([]*User, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
|
||||||
|
return users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFollowing if current user followed the target
|
||||||
|
func (c *Client) IsFollowing(target string) (bool, *Response) {
|
||||||
|
if err := escapeValidatePathSegments(&target); err != nil {
|
||||||
|
// ToDo return err
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||||
|
return err == nil, resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUserFollowing if the user followed the target
|
||||||
|
func (c *Client) IsUserFollowing(user, target string) (bool, *Response) {
|
||||||
|
if err := escapeValidatePathSegments(&user, &target); err != nil {
|
||||||
|
// ToDo return err
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil)
|
||||||
|
return err == nil, resp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Follow set current user follow the target
|
||||||
|
func (c *Client) Follow(target string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&target); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfollow set current user unfollow the target
|
||||||
|
func (c *Client) Unfollow(target string) (*Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&target); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
89
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go
generated
vendored
Normal file
89
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright 2017 Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GPGKey a user GPG key to sign commit and tag in repository
|
||||||
|
type GPGKey struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
PrimaryKeyID string `json:"primary_key_id"`
|
||||||
|
KeyID string `json:"key_id"`
|
||||||
|
PublicKey string `json:"public_key"`
|
||||||
|
Emails []*GPGKeyEmail `json:"emails"`
|
||||||
|
SubsKey []*GPGKey `json:"subkeys"`
|
||||||
|
CanSign bool `json:"can_sign"`
|
||||||
|
CanEncryptComms bool `json:"can_encrypt_comms"`
|
||||||
|
CanEncryptStorage bool `json:"can_encrypt_storage"`
|
||||||
|
CanCertify bool `json:"can_certify"`
|
||||||
|
Created time.Time `json:"created_at,omitempty"`
|
||||||
|
Expires time.Time `json:"expires_at,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPGKeyEmail an email attached to a GPGKey
|
||||||
|
type GPGKeyEmail struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListGPGKeysOptions options for listing a user's GPGKeys
|
||||||
|
type ListGPGKeysOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListGPGKeys list all the GPG keys of the user
|
||||||
|
func (c *Client) ListGPGKeys(user string, opt ListGPGKeysOptions) ([]*GPGKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*GPGKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyGPGKeys list all the GPG keys of current user
|
||||||
|
func (c *Client) ListMyGPGKeys(opt *ListGPGKeysOptions) ([]*GPGKey, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*GPGKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGPGKey get current user's GPG key by key id
|
||||||
|
func (c *Client) GetGPGKey(keyID int64) (*GPGKey, *Response, error) {
|
||||||
|
key := new(GPGKey)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil, &key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateGPGKeyOption options create user GPG key
|
||||||
|
type CreateGPGKeyOption struct {
|
||||||
|
// An armored GPG key to add
|
||||||
|
//
|
||||||
|
ArmoredKey string `json:"armored_public_key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateGPGKey create GPG key with options
|
||||||
|
func (c *Client) CreateGPGKey(opt CreateGPGKeyOption) (*GPGKey, *Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(GPGKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/gpg_keys", jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteGPGKey delete GPG key with key id
|
||||||
|
func (c *Client) DeleteGPGKey(keyID int64) (*Response, error) {
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
83
vendor/code.gitea.io/sdk/gitea/user_key.go
generated
vendored
Normal file
83
vendor/code.gitea.io/sdk/gitea/user_key.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PublicKey publickey is a user key to push code to repository
|
||||||
|
type PublicKey struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
Fingerprint string `json:"fingerprint,omitempty"`
|
||||||
|
Created time.Time `json:"created_at,omitempty"`
|
||||||
|
Owner *User `json:"user,omitempty"`
|
||||||
|
ReadOnly bool `json:"read_only,omitempty"`
|
||||||
|
KeyType string `json:"key_type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPublicKeysOptions options for listing a user's PublicKeys
|
||||||
|
type ListPublicKeysOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListPublicKeys list all the public keys of the user
|
||||||
|
func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
|
||||||
|
if err := escapeValidatePathSegments(&user); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*PublicKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMyPublicKeys list all the public keys of current user
|
||||||
|
func (c *Client) ListMyPublicKeys(opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
|
||||||
|
opt.setDefaults()
|
||||||
|
keys := make([]*PublicKey, 0, opt.PageSize)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||||
|
return keys, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublicKey get current user's public key by key id
|
||||||
|
func (c *Client) GetPublicKey(keyID int64) (*PublicKey, *Response, error) {
|
||||||
|
key := new(PublicKey)
|
||||||
|
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateKeyOption options when creating a key
|
||||||
|
type CreateKeyOption struct {
|
||||||
|
// Title of the key to add
|
||||||
|
Title string `json:"title"`
|
||||||
|
// An armored SSH key to add
|
||||||
|
Key string `json:"key"`
|
||||||
|
// Describe if the key has only read access or read/write
|
||||||
|
ReadOnly bool `json:"read_only"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePublicKey create public key with options
|
||||||
|
func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, *Response, error) {
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
key := new(PublicKey)
|
||||||
|
resp, err := c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key)
|
||||||
|
return key, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePublicKey delete public key with key id
|
||||||
|
func (c *Client) DeletePublicKey(keyID int64) (*Response, error) {
|
||||||
|
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
48
vendor/code.gitea.io/sdk/gitea/user_search.go
generated
vendored
Normal file
48
vendor/code.gitea.io/sdk/gitea/user_search.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type searchUsersResponse struct {
|
||||||
|
Users []*User `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchUsersOption options for SearchUsers
|
||||||
|
type SearchUsersOption struct {
|
||||||
|
ListOptions
|
||||||
|
KeyWord string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryEncode turns options into querystring argument
|
||||||
|
func (opt *SearchUsersOption) QueryEncode() string {
|
||||||
|
query := make(url.Values)
|
||||||
|
if opt.Page > 0 {
|
||||||
|
query.Add("page", fmt.Sprintf("%d", opt.Page))
|
||||||
|
}
|
||||||
|
if opt.PageSize > 0 {
|
||||||
|
query.Add("limit", fmt.Sprintf("%d", opt.PageSize))
|
||||||
|
}
|
||||||
|
if len(opt.KeyWord) > 0 {
|
||||||
|
query.Add("q", opt.KeyWord)
|
||||||
|
}
|
||||||
|
return query.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) searchUsers(rawQuery string) ([]*User, *Response, error) {
|
||||||
|
link, _ := url.Parse("/users/search")
|
||||||
|
link.RawQuery = rawQuery
|
||||||
|
userResp := new(searchUsersResponse)
|
||||||
|
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &userResp)
|
||||||
|
return userResp.Users, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchUsers finds users by query
|
||||||
|
func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, *Response, error) {
|
||||||
|
return c.searchUsers(opt.QueryEncode())
|
||||||
|
}
|
62
vendor/code.gitea.io/sdk/gitea/user_settings.go
generated
vendored
Normal file
62
vendor/code.gitea.io/sdk/gitea/user_settings.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UserSettings represents user settings
|
||||||
|
type UserSettings struct {
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Website string `json:"website"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
Theme string `json:"theme"`
|
||||||
|
DiffViewStyle string `json:"diff_view_style"`
|
||||||
|
// Privacy
|
||||||
|
HideEmail bool `json:"hide_email"`
|
||||||
|
HideActivity bool `json:"hide_activity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserSettingsOptions represents options to change user settings
|
||||||
|
type UserSettingsOptions struct {
|
||||||
|
FullName *string `json:"full_name,omitempty"`
|
||||||
|
Website *string `json:"website,omitempty"`
|
||||||
|
Description *string `json:"description,omitempty"`
|
||||||
|
Location *string `json:"location,omitempty"`
|
||||||
|
Language *string `json:"language,omitempty"`
|
||||||
|
Theme *string `json:"theme,omitempty"`
|
||||||
|
DiffViewStyle *string `json:"diff_view_style,omitempty"`
|
||||||
|
// Privacy
|
||||||
|
HideEmail *bool `json:"hide_email,omitempty"`
|
||||||
|
HideActivity *bool `json:"hide_activity,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserSettings returns user settings
|
||||||
|
func (c *Client) GetUserSettings() (*UserSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
userConfig := new(UserSettings)
|
||||||
|
resp, err := c.getParsedResponse("GET", "/user/settings", nil, nil, userConfig)
|
||||||
|
return userConfig, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUserSettings returns user settings
|
||||||
|
func (c *Client) UpdateUserSettings(opt UserSettingsOptions) (*UserSettings, *Response, error) {
|
||||||
|
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(&opt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
userConfig := new(UserSettings)
|
||||||
|
resp, err := c.getParsedResponse("PATCH", "/user/settings", jsonHeader, bytes.NewReader(body), userConfig)
|
||||||
|
return userConfig, resp, err
|
||||||
|
}
|
101
vendor/code.gitea.io/sdk/gitea/version.go
generated
vendored
Normal file
101
vendor/code.gitea.io/sdk/gitea/version.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gitea
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServerVersion returns the version of the server
|
||||||
|
func (c *Client) ServerVersion() (string, *Response, error) {
|
||||||
|
var v = struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
}{}
|
||||||
|
resp, err := c.getParsedResponse("GET", "/version", nil, nil, &v)
|
||||||
|
return v.Version, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckServerVersionConstraint validates that the login's server satisfies a
|
||||||
|
// given version constraint such as ">= 1.11.0+dev"
|
||||||
|
func (c *Client) CheckServerVersionConstraint(constraint string) error {
|
||||||
|
if err := c.loadServerVersion(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
check, err := version.NewConstraint(constraint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !check.Check(c.serverVersion) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
url := c.url
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return fmt.Errorf("gitea server at %s does not satisfy version constraint %s", url, constraint)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGiteaVersion configures the Client to assume the given version of the
|
||||||
|
// Gitea server, instead of querying the server for it when initializing.
|
||||||
|
// Use "" to skip all canonical ways in the SDK to check for versions
|
||||||
|
func SetGiteaVersion(v string) ClientOption {
|
||||||
|
if v == "" {
|
||||||
|
return func(c *Client) error {
|
||||||
|
c.ignoreVersion = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func(c *Client) (err error) {
|
||||||
|
c.getVersionOnce.Do(func() {
|
||||||
|
c.serverVersion, err = version.NewVersion(v)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// predefined versions only have to be parsed by library once
|
||||||
|
var (
|
||||||
|
version1_11_0, _ = version.NewVersion("1.11.0")
|
||||||
|
version1_12_0, _ = version.NewVersion("1.12.0")
|
||||||
|
version1_13_0, _ = version.NewVersion("1.13.0")
|
||||||
|
version1_14_0, _ = version.NewVersion("1.14.0")
|
||||||
|
version1_15_0, _ = version.NewVersion("1.15.0")
|
||||||
|
)
|
||||||
|
|
||||||
|
// checkServerVersionGreaterThanOrEqual is the canonical way in the SDK to check for versions for API compatibility reasons
|
||||||
|
func (c *Client) checkServerVersionGreaterThanOrEqual(v *version.Version) error {
|
||||||
|
if c.ignoreVersion {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := c.loadServerVersion(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.serverVersion.GreaterThanOrEqual(v) {
|
||||||
|
c.mutex.RLock()
|
||||||
|
url := c.url
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return fmt.Errorf("gitea server at %s is older than %s", url, v.Original())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadServerVersion init the serverVersion variable
|
||||||
|
func (c *Client) loadServerVersion() (err error) {
|
||||||
|
c.getVersionOnce.Do(func() {
|
||||||
|
raw, _, err2 := c.ServerVersion()
|
||||||
|
if err2 != nil {
|
||||||
|
err = err2
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c.serverVersion, err = version.NewVersion(raw); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
18
vendor/github.com/Masterminds/goutils/.travis.yml
generated
vendored
Normal file
18
vendor/github.com/Masterminds/goutils/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.6
|
||||||
|
- 1.7
|
||||||
|
- 1.8
|
||||||
|
- tip
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/06e3328629952dabe3e0
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: never # options: [always|never|change] default: always
|
8
vendor/github.com/Masterminds/goutils/CHANGELOG.md
generated
vendored
Normal file
8
vendor/github.com/Masterminds/goutils/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# 1.0.1 (2017-05-31)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #21: Fix generation of alphanumeric strings (thanks @dbarranco)
|
||||||
|
|
||||||
|
# 1.0.0 (2014-04-30)
|
||||||
|
|
||||||
|
- Initial release.
|
202
vendor/github.com/Masterminds/goutils/LICENSE.txt
generated
vendored
Normal file
202
vendor/github.com/Masterminds/goutils/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
70
vendor/github.com/Masterminds/goutils/README.md
generated
vendored
Normal file
70
vendor/github.com/Masterminds/goutils/README.md
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
GoUtils
|
||||||
|
===========
|
||||||
|
[![Stability: Maintenance](https://masterminds.github.io/stability/maintenance.svg)](https://masterminds.github.io/stability/maintenance.html)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/Masterminds/goutils?status.png)](https://godoc.org/github.com/Masterminds/goutils) [![Build Status](https://travis-ci.org/Masterminds/goutils.svg?branch=master)](https://travis-ci.org/Masterminds/goutils) [![Build status](https://ci.appveyor.com/api/projects/status/sc2b1ew0m7f0aiju?svg=true)](https://ci.appveyor.com/project/mattfarina/goutils)
|
||||||
|
|
||||||
|
|
||||||
|
GoUtils provides users with utility functions to manipulate strings in various ways. It is a Go implementation of some
|
||||||
|
string manipulation libraries of Java Apache Commons. GoUtils includes the following Java Apache Commons classes:
|
||||||
|
* WordUtils
|
||||||
|
* RandomStringUtils
|
||||||
|
* StringUtils (partial implementation)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
If you have Go set up on your system, from the GOPATH directory within the command line/terminal, enter this:
|
||||||
|
|
||||||
|
go get github.com/Masterminds/goutils
|
||||||
|
|
||||||
|
If you do not have Go set up on your system, please follow the [Go installation directions from the documenation](http://golang.org/doc/install), and then follow the instructions above to install GoUtils.
|
||||||
|
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
GoUtils doc is available here: [![GoDoc](https://godoc.org/github.com/Masterminds/goutils?status.png)](https://godoc.org/github.com/Masterminds/goutils)
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
The code snippets below show examples of how to use GoUtils. Some functions return errors while others do not. The first instance below, which does not return an error, is the `Initials` function (located within the `wordutils.go` file).
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/Masterminds/goutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// EXAMPLE 1: A goutils function which returns no errors
|
||||||
|
fmt.Println (goutils.Initials("John Doe Foo")) // Prints out "JDF"
|
||||||
|
|
||||||
|
}
|
||||||
|
Some functions return errors mainly due to illegal arguements used as parameters. The code example below illustrates how to deal with function that returns an error. In this instance, the function is the `Random` function (located within the `randomstringutils.go` file).
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/Masterminds/goutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// EXAMPLE 2: A goutils function which returns an error
|
||||||
|
rand1, err1 := goutils.Random (-1, 0, 0, true, true)
|
||||||
|
|
||||||
|
if err1 != nil {
|
||||||
|
fmt.Println(err1) // Prints out error message because -1 was entered as the first parameter in goutils.Random(...)
|
||||||
|
} else {
|
||||||
|
fmt.Println(rand1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
## License
|
||||||
|
GoUtils is licensed under the Apache License, Version 2.0. Please check the LICENSE.txt file or visit http://www.apache.org/licenses/LICENSE-2.0 for a copy of the license.
|
||||||
|
|
||||||
|
## Issue Reporting
|
||||||
|
Make suggestions or report issues using the Git issue tracker: https://github.com/Masterminds/goutils/issues
|
||||||
|
|
||||||
|
## Website
|
||||||
|
* [GoUtils webpage](http://Masterminds.github.io/goutils/)
|
21
vendor/github.com/Masterminds/goutils/appveyor.yml
generated
vendored
Normal file
21
vendor/github.com/Masterminds/goutils/appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
version: build-{build}.{branch}
|
||||||
|
|
||||||
|
clone_folder: C:\gopath\src\github.com\Masterminds\goutils
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: C:\gopath
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
|
||||||
|
build: off
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- go test -v
|
||||||
|
|
||||||
|
deploy: off
|
251
vendor/github.com/Masterminds/goutils/cryptorandomstringutils.go
generated
vendored
Normal file
251
vendor/github.com/Masterminds/goutils/cryptorandomstringutils.go
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Alexander Okoli
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package goutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"regexp"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomNonAlphaNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of all characters (ASCII/Unicode values between 0 to 2,147,483,647 (math.MaxInt32)).
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomNonAlphaNumeric(count int) (string, error) {
|
||||||
|
return CryptoRandomAlphaNumericCustom(count, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAscii creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of characters whose ASCII value is between 32 and 126 (inclusive).
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAscii(count int) (string, error) {
|
||||||
|
return CryptoRandom(count, 32, 127, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of numeric characters.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomNumeric(count int) (string, error) {
|
||||||
|
return CryptoRandom(count, 0, 0, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAlphabetic creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAlphabetic(count int) (string, error) {
|
||||||
|
return CryptoRandom(count, 0, 0, true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAlphaNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAlphaNumeric(count int) (string, error) {
|
||||||
|
if count == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
RandomString, err := CryptoRandom(count, 0, 0, true, true)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error: %s", err)
|
||||||
|
}
|
||||||
|
match, err := regexp.MatchString("([0-9]+)", RandomString)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !match {
|
||||||
|
//Get the position between 0 and the length of the string-1 to insert a random number
|
||||||
|
position := getCryptoRandomInt(count)
|
||||||
|
//Insert a random number between [0-9] in the position
|
||||||
|
RandomString = RandomString[:position] + string('0' + getCryptoRandomInt(10)) + RandomString[position + 1:]
|
||||||
|
return RandomString, err
|
||||||
|
}
|
||||||
|
return RandomString, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAlphaNumericCustom creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAlphaNumericCustom(count int, letters bool, numbers bool) (string, error) {
|
||||||
|
return CryptoRandom(count, 0, 0, letters, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandom creates a random string based on a variety of options, using using golang's crypto/rand source of randomness.
|
||||||
|
If the parameters start and end are both 0, start and end are set to ' ' and 'z', the ASCII printable characters, will be used,
|
||||||
|
unless letters and numbers are both false, in which case, start and end are set to 0 and math.MaxInt32, respectively.
|
||||||
|
If chars is not nil, characters stored in chars that are between start and end are chosen.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
start - the position in set of chars (ASCII/Unicode int) to start at
|
||||||
|
end - the position in set of chars (ASCII/Unicode int) to end before
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
chars - the set of chars to choose randoms from. If nil, then it will use the set of all chars.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from invalid parameters: if count < 0; or the provided chars array is empty; or end <= start; or end > len(chars)
|
||||||
|
*/
|
||||||
|
func CryptoRandom(count int, start int, end int, letters bool, numbers bool, chars ...rune) (string, error) {
|
||||||
|
if count == 0 {
|
||||||
|
return "", nil
|
||||||
|
} else if count < 0 {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Requested random string length %v is less than 0.", count) // equiv to err := errors.New("...")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if chars != nil && len(chars) == 0 {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: The chars array must not be empty")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if start == 0 && end == 0 {
|
||||||
|
if chars != nil {
|
||||||
|
end = len(chars)
|
||||||
|
} else {
|
||||||
|
if !letters && !numbers {
|
||||||
|
end = math.MaxInt32
|
||||||
|
} else {
|
||||||
|
end = 'z' + 1
|
||||||
|
start = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if end <= start {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) must be greater than start (%v)", end, start)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if chars != nil && end > len(chars) {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) cannot be greater than len(chars) (%v)", end, len(chars))
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]rune, count)
|
||||||
|
gap := end - start
|
||||||
|
|
||||||
|
// high-surrogates range, (\uD800-\uDBFF) = 55296 - 56319
|
||||||
|
// low-surrogates range, (\uDC00-\uDFFF) = 56320 - 57343
|
||||||
|
|
||||||
|
for count != 0 {
|
||||||
|
count--
|
||||||
|
var ch rune
|
||||||
|
if chars == nil {
|
||||||
|
ch = rune(getCryptoRandomInt(gap) + int64(start))
|
||||||
|
} else {
|
||||||
|
ch = chars[getCryptoRandomInt(gap) + int64(start)]
|
||||||
|
}
|
||||||
|
|
||||||
|
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
|
||||||
|
if ch >= 56320 && ch <= 57343 { // low surrogate range
|
||||||
|
if count == 0 {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// Insert low surrogate
|
||||||
|
buffer[count] = ch
|
||||||
|
count--
|
||||||
|
// Insert high surrogate
|
||||||
|
buffer[count] = rune(55296 + getCryptoRandomInt(128))
|
||||||
|
}
|
||||||
|
} else if ch >= 55296 && ch <= 56191 { // High surrogates range (Partial)
|
||||||
|
if count == 0 {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// Insert low surrogate
|
||||||
|
buffer[count] = rune(56320 + getCryptoRandomInt(128))
|
||||||
|
count--
|
||||||
|
// Insert high surrogate
|
||||||
|
buffer[count] = ch
|
||||||
|
}
|
||||||
|
} else if ch >= 56192 && ch <= 56319 {
|
||||||
|
// private high surrogate, skip it
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// not one of the surrogates*
|
||||||
|
buffer[count] = ch
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buffer), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCryptoRandomInt(count int) int64 {
|
||||||
|
nBig, err := rand.Int(rand.Reader, big.NewInt(int64(count)))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nBig.Int64()
|
||||||
|
}
|
268
vendor/github.com/Masterminds/goutils/randomstringutils.go
generated
vendored
Normal file
268
vendor/github.com/Masterminds/goutils/randomstringutils.go
generated
vendored
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Alexander Okoli
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package goutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
"regexp"
|
||||||
|
"time"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RANDOM provides the time-based seed used to generate random numbers
|
||||||
|
var RANDOM = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomNonAlphaNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of all characters (ASCII/Unicode values between 0 to 2,147,483,647 (math.MaxInt32)).
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func RandomNonAlphaNumeric(count int) (string, error) {
|
||||||
|
return RandomAlphaNumericCustom(count, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomAscii creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of characters whose ASCII value is between 32 and 126 (inclusive).
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func RandomAscii(count int) (string, error) {
|
||||||
|
return Random(count, 32, 127, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of numeric characters.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func RandomNumeric(count int) (string, error) {
|
||||||
|
return Random(count, 0, 0, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomAlphabetic creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func RandomAlphabetic(count int) (string, error) {
|
||||||
|
return Random(count, 0, 0, true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomAlphaNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func RandomAlphaNumeric(count int) (string, error) {
|
||||||
|
RandomString, err := Random(count, 0, 0, true, true)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error: %s", err)
|
||||||
|
}
|
||||||
|
match, err := regexp.MatchString("([0-9]+)", RandomString)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !match {
|
||||||
|
//Get the position between 0 and the length of the string-1 to insert a random number
|
||||||
|
position := rand.Intn(count)
|
||||||
|
//Insert a random number between [0-9] in the position
|
||||||
|
RandomString = RandomString[:position] + string('0'+rand.Intn(10)) + RandomString[position+1:]
|
||||||
|
return RandomString, err
|
||||||
|
}
|
||||||
|
return RandomString, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomAlphaNumericCustom creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func RandomAlphaNumericCustom(count int, letters bool, numbers bool) (string, error) {
|
||||||
|
return Random(count, 0, 0, letters, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Random creates a random string based on a variety of options, using default source of randomness.
|
||||||
|
This method has exactly the same semantics as RandomSeed(int, int, int, bool, bool, []char, *rand.Rand), but
|
||||||
|
instead of using an externally supplied source of randomness, it uses the internal *rand.Rand instance.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
start - the position in set of chars (ASCII/Unicode int) to start at
|
||||||
|
end - the position in set of chars (ASCII/Unicode int) to end before
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
chars - the set of chars to choose randoms from. If nil, then it will use the set of all chars.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
|
||||||
|
*/
|
||||||
|
func Random(count int, start int, end int, letters bool, numbers bool, chars ...rune) (string, error) {
|
||||||
|
return RandomSeed(count, start, end, letters, numbers, chars, RANDOM)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
RandomSeed creates a random string based on a variety of options, using supplied source of randomness.
|
||||||
|
If the parameters start and end are both 0, start and end are set to ' ' and 'z', the ASCII printable characters, will be used,
|
||||||
|
unless letters and numbers are both false, in which case, start and end are set to 0 and math.MaxInt32, respectively.
|
||||||
|
If chars is not nil, characters stored in chars that are between start and end are chosen.
|
||||||
|
This method accepts a user-supplied *rand.Rand instance to use as a source of randomness. By seeding a single *rand.Rand instance
|
||||||
|
with a fixed seed and using it for each call, the same random sequence of strings can be generated repeatedly and predictably.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
start - the position in set of chars (ASCII/Unicode decimals) to start at
|
||||||
|
end - the position in set of chars (ASCII/Unicode decimals) to end before
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
chars - the set of chars to choose randoms from. If nil, then it will use the set of all chars.
|
||||||
|
random - a source of randomness.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from invalid parameters: if count < 0; or the provided chars array is empty; or end <= start; or end > len(chars)
|
||||||
|
*/
|
||||||
|
func RandomSeed(count int, start int, end int, letters bool, numbers bool, chars []rune, random *rand.Rand) (string, error) {
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return "", nil
|
||||||
|
} else if count < 0 {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Requested random string length %v is less than 0.", count) // equiv to err := errors.New("...")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if chars != nil && len(chars) == 0 {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: The chars array must not be empty")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if start == 0 && end == 0 {
|
||||||
|
if chars != nil {
|
||||||
|
end = len(chars)
|
||||||
|
} else {
|
||||||
|
if !letters && !numbers {
|
||||||
|
end = math.MaxInt32
|
||||||
|
} else {
|
||||||
|
end = 'z' + 1
|
||||||
|
start = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if end <= start {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) must be greater than start (%v)", end, start)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if chars != nil && end > len(chars) {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) cannot be greater than len(chars) (%v)", end, len(chars))
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]rune, count)
|
||||||
|
gap := end - start
|
||||||
|
|
||||||
|
// high-surrogates range, (\uD800-\uDBFF) = 55296 - 56319
|
||||||
|
// low-surrogates range, (\uDC00-\uDFFF) = 56320 - 57343
|
||||||
|
|
||||||
|
for count != 0 {
|
||||||
|
count--
|
||||||
|
var ch rune
|
||||||
|
if chars == nil {
|
||||||
|
ch = rune(random.Intn(gap) + start)
|
||||||
|
} else {
|
||||||
|
ch = chars[random.Intn(gap)+start]
|
||||||
|
}
|
||||||
|
|
||||||
|
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
|
||||||
|
if ch >= 56320 && ch <= 57343 { // low surrogate range
|
||||||
|
if count == 0 {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// Insert low surrogate
|
||||||
|
buffer[count] = ch
|
||||||
|
count--
|
||||||
|
// Insert high surrogate
|
||||||
|
buffer[count] = rune(55296 + random.Intn(128))
|
||||||
|
}
|
||||||
|
} else if ch >= 55296 && ch <= 56191 { // High surrogates range (Partial)
|
||||||
|
if count == 0 {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// Insert low surrogate
|
||||||
|
buffer[count] = rune(56320 + random.Intn(128))
|
||||||
|
count--
|
||||||
|
// Insert high surrogate
|
||||||
|
buffer[count] = ch
|
||||||
|
}
|
||||||
|
} else if ch >= 56192 && ch <= 56319 {
|
||||||
|
// private high surrogate, skip it
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// not one of the surrogates*
|
||||||
|
buffer[count] = ch
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buffer), nil
|
||||||
|
}
|
224
vendor/github.com/Masterminds/goutils/stringutils.go
generated
vendored
Normal file
224
vendor/github.com/Masterminds/goutils/stringutils.go
generated
vendored
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Alexander Okoli
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package goutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Typically returned by functions where a searched item cannot be found
|
||||||
|
const INDEX_NOT_FOUND = -1
|
||||||
|
|
||||||
|
/*
|
||||||
|
Abbreviate abbreviates a string using ellipses. This will turn the string "Now is the time for all good men" into "Now is the time for..."
|
||||||
|
|
||||||
|
Specifically, the algorithm is as follows:
|
||||||
|
|
||||||
|
- If str is less than maxWidth characters long, return it.
|
||||||
|
- Else abbreviate it to (str[0:maxWidth - 3] + "...").
|
||||||
|
- If maxWidth is less than 4, return an illegal argument error.
|
||||||
|
- In no case will it return a string of length greater than maxWidth.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to check
|
||||||
|
maxWidth - maximum length of result string, must be at least 4
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - abbreviated string
|
||||||
|
error - if the width is too small
|
||||||
|
*/
|
||||||
|
func Abbreviate(str string, maxWidth int) (string, error) {
|
||||||
|
return AbbreviateFull(str, 0, maxWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
AbbreviateFull abbreviates a string using ellipses. This will turn the string "Now is the time for all good men" into "...is the time for..."
|
||||||
|
This function works like Abbreviate(string, int), but allows you to specify a "left edge" offset. Note that this left edge is not
|
||||||
|
necessarily going to be the leftmost character in the result, or the first character following the ellipses, but it will appear
|
||||||
|
somewhere in the result.
|
||||||
|
In no case will it return a string of length greater than maxWidth.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to check
|
||||||
|
offset - left edge of source string
|
||||||
|
maxWidth - maximum length of result string, must be at least 4
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - abbreviated string
|
||||||
|
error - if the width is too small
|
||||||
|
*/
|
||||||
|
func AbbreviateFull(str string, offset int, maxWidth int) (string, error) {
|
||||||
|
if str == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if maxWidth < 4 {
|
||||||
|
err := fmt.Errorf("stringutils illegal argument: Minimum abbreviation width is 4")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(str) <= maxWidth {
|
||||||
|
return str, nil
|
||||||
|
}
|
||||||
|
if offset > len(str) {
|
||||||
|
offset = len(str)
|
||||||
|
}
|
||||||
|
if len(str)-offset < (maxWidth - 3) { // 15 - 5 < 10 - 3 = 10 < 7
|
||||||
|
offset = len(str) - (maxWidth - 3)
|
||||||
|
}
|
||||||
|
abrevMarker := "..."
|
||||||
|
if offset <= 4 {
|
||||||
|
return str[0:maxWidth-3] + abrevMarker, nil // str.substring(0, maxWidth - 3) + abrevMarker;
|
||||||
|
}
|
||||||
|
if maxWidth < 7 {
|
||||||
|
err := fmt.Errorf("stringutils illegal argument: Minimum abbreviation width with offset is 7")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if (offset + maxWidth - 3) < len(str) { // 5 + (10-3) < 15 = 12 < 15
|
||||||
|
abrevStr, _ := Abbreviate(str[offset:len(str)], (maxWidth - 3))
|
||||||
|
return abrevMarker + abrevStr, nil // abrevMarker + abbreviate(str.substring(offset), maxWidth - 3);
|
||||||
|
}
|
||||||
|
return abrevMarker + str[(len(str)-(maxWidth-3)):len(str)], nil // abrevMarker + str.substring(str.length() - (maxWidth - 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
DeleteWhiteSpace deletes all whitespaces from a string as defined by unicode.IsSpace(rune).
|
||||||
|
It returns the string without whitespaces.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
str - the string to delete whitespace from, may be nil
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the string without whitespaces
|
||||||
|
*/
|
||||||
|
func DeleteWhiteSpace(str string) string {
|
||||||
|
if str == "" {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
sz := len(str)
|
||||||
|
var chs bytes.Buffer
|
||||||
|
count := 0
|
||||||
|
for i := 0; i < sz; i++ {
|
||||||
|
ch := rune(str[i])
|
||||||
|
if !unicode.IsSpace(ch) {
|
||||||
|
chs.WriteRune(ch)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if count == sz {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
return chs.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IndexOfDifference compares two strings, and returns the index at which the strings begin to differ.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str1 - the first string
|
||||||
|
str2 - the second string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the index where str1 and str2 begin to differ; -1 if they are equal
|
||||||
|
*/
|
||||||
|
func IndexOfDifference(str1 string, str2 string) int {
|
||||||
|
if str1 == str2 {
|
||||||
|
return INDEX_NOT_FOUND
|
||||||
|
}
|
||||||
|
if IsEmpty(str1) || IsEmpty(str2) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
for i = 0; i < len(str1) && i < len(str2); i++ {
|
||||||
|
if rune(str1[i]) != rune(str2[i]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i < len(str2) || i < len(str1) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return INDEX_NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IsBlank checks if a string is whitespace or empty (""). Observe the following behavior:
|
||||||
|
|
||||||
|
goutils.IsBlank("") = true
|
||||||
|
goutils.IsBlank(" ") = true
|
||||||
|
goutils.IsBlank("bob") = false
|
||||||
|
goutils.IsBlank(" bob ") = false
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
str - the string to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
true - if the string is whitespace or empty ("")
|
||||||
|
*/
|
||||||
|
func IsBlank(str string) bool {
|
||||||
|
strLen := len(str)
|
||||||
|
if str == "" || strLen == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for i := 0; i < strLen; i++ {
|
||||||
|
if unicode.IsSpace(rune(str[i])) == false {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
IndexOf returns the index of the first instance of sub in str, with the search beginning from the
|
||||||
|
index start point specified. -1 is returned if sub is not present in str.
|
||||||
|
|
||||||
|
An empty string ("") will return -1 (INDEX_NOT_FOUND). A negative start position is treated as zero.
|
||||||
|
A start position greater than the string length returns -1.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to check
|
||||||
|
sub - the substring to find
|
||||||
|
start - the start position; negative treated as zero
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the first index where the sub string was found (always >= start)
|
||||||
|
*/
|
||||||
|
func IndexOf(str string, sub string, start int) int {
|
||||||
|
|
||||||
|
if start < 0 {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(str) < start {
|
||||||
|
return INDEX_NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsEmpty(str) || IsEmpty(sub) {
|
||||||
|
return INDEX_NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
partialIndex := strings.Index(str[start:len(str)], sub)
|
||||||
|
if partialIndex == -1 {
|
||||||
|
return INDEX_NOT_FOUND
|
||||||
|
}
|
||||||
|
return partialIndex + start
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks if a string is empty (""). Returns true if empty, and false otherwise.
|
||||||
|
func IsEmpty(str string) bool {
|
||||||
|
return len(str) == 0
|
||||||
|
}
|
357
vendor/github.com/Masterminds/goutils/wordutils.go
generated
vendored
Normal file
357
vendor/github.com/Masterminds/goutils/wordutils.go
generated
vendored
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Alexander Okoli
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package goutils provides utility functions to manipulate strings in various ways.
|
||||||
|
The code snippets below show examples of how to use goutils. Some functions return
|
||||||
|
errors while others do not, so usage would vary as a result.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/aokoli/goutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// EXAMPLE 1: A goutils function which returns no errors
|
||||||
|
fmt.Println (goutils.Initials("John Doe Foo")) // Prints out "JDF"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// EXAMPLE 2: A goutils function which returns an error
|
||||||
|
rand1, err1 := goutils.Random (-1, 0, 0, true, true)
|
||||||
|
|
||||||
|
if err1 != nil {
|
||||||
|
fmt.Println(err1) // Prints out error message because -1 was entered as the first parameter in goutils.Random(...)
|
||||||
|
} else {
|
||||||
|
fmt.Println(rand1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package goutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VERSION indicates the current version of goutils
|
||||||
|
const VERSION = "1.0.0"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wrap wraps a single line of text, identifying words by ' '.
|
||||||
|
New lines will be separated by '\n'. Very long words, such as URLs will not be wrapped.
|
||||||
|
Leading spaces on a new line are stripped. Trailing spaces are not stripped.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to be word wrapped
|
||||||
|
wrapLength - the column (a column can fit only one character) to wrap the words at, less than 1 is treated as 1
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a line with newlines inserted
|
||||||
|
*/
|
||||||
|
func Wrap(str string, wrapLength int) string {
|
||||||
|
return WrapCustom(str, wrapLength, "", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
WrapCustom wraps a single line of text, identifying words by ' '.
|
||||||
|
Leading spaces on a new line are stripped. Trailing spaces are not stripped.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to be word wrapped
|
||||||
|
wrapLength - the column number (a column can fit only one character) to wrap the words at, less than 1 is treated as 1
|
||||||
|
newLineStr - the string to insert for a new line, "" uses '\n'
|
||||||
|
wrapLongWords - true if long words (such as URLs) should be wrapped
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
a line with newlines inserted
|
||||||
|
*/
|
||||||
|
func WrapCustom(str string, wrapLength int, newLineStr string, wrapLongWords bool) string {
|
||||||
|
|
||||||
|
if str == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if newLineStr == "" {
|
||||||
|
newLineStr = "\n" // TODO Assumes "\n" is seperator. Explore SystemUtils.LINE_SEPARATOR from Apache Commons
|
||||||
|
}
|
||||||
|
if wrapLength < 1 {
|
||||||
|
wrapLength = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
inputLineLength := len(str)
|
||||||
|
offset := 0
|
||||||
|
|
||||||
|
var wrappedLine bytes.Buffer
|
||||||
|
|
||||||
|
for inputLineLength-offset > wrapLength {
|
||||||
|
|
||||||
|
if rune(str[offset]) == ' ' {
|
||||||
|
offset++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
end := wrapLength + offset + 1
|
||||||
|
spaceToWrapAt := strings.LastIndex(str[offset:end], " ") + offset
|
||||||
|
|
||||||
|
if spaceToWrapAt >= offset {
|
||||||
|
// normal word (not longer than wrapLength)
|
||||||
|
wrappedLine.WriteString(str[offset:spaceToWrapAt])
|
||||||
|
wrappedLine.WriteString(newLineStr)
|
||||||
|
offset = spaceToWrapAt + 1
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// long word or URL
|
||||||
|
if wrapLongWords {
|
||||||
|
end := wrapLength + offset
|
||||||
|
// long words are wrapped one line at a time
|
||||||
|
wrappedLine.WriteString(str[offset:end])
|
||||||
|
wrappedLine.WriteString(newLineStr)
|
||||||
|
offset += wrapLength
|
||||||
|
} else {
|
||||||
|
// long words aren't wrapped, just extended beyond limit
|
||||||
|
end := wrapLength + offset
|
||||||
|
index := strings.IndexRune(str[end:len(str)], ' ')
|
||||||
|
if index == -1 {
|
||||||
|
wrappedLine.WriteString(str[offset:len(str)])
|
||||||
|
offset = inputLineLength
|
||||||
|
} else {
|
||||||
|
spaceToWrapAt = index + end
|
||||||
|
wrappedLine.WriteString(str[offset:spaceToWrapAt])
|
||||||
|
wrappedLine.WriteString(newLineStr)
|
||||||
|
offset = spaceToWrapAt + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wrappedLine.WriteString(str[offset:len(str)])
|
||||||
|
|
||||||
|
return wrappedLine.String()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Capitalize capitalizes all the delimiter separated words in a string. Only the first letter of each word is changed.
|
||||||
|
To convert the rest of each word to lowercase at the same time, use CapitalizeFully(str string, delimiters ...rune).
|
||||||
|
The delimiters represent a set of characters understood to separate words. The first string character
|
||||||
|
and the first non-delimiter character after a delimiter will be capitalized. A "" input string returns "".
|
||||||
|
Capitalization uses the Unicode title case, normally equivalent to upper case.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to capitalize
|
||||||
|
delimiters - set of characters to determine capitalization, exclusion of this parameter means whitespace would be delimeter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
capitalized string
|
||||||
|
*/
|
||||||
|
func Capitalize(str string, delimiters ...rune) string {
|
||||||
|
|
||||||
|
var delimLen int
|
||||||
|
|
||||||
|
if delimiters == nil {
|
||||||
|
delimLen = -1
|
||||||
|
} else {
|
||||||
|
delimLen = len(delimiters)
|
||||||
|
}
|
||||||
|
|
||||||
|
if str == "" || delimLen == 0 {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := []rune(str)
|
||||||
|
capitalizeNext := true
|
||||||
|
for i := 0; i < len(buffer); i++ {
|
||||||
|
ch := buffer[i]
|
||||||
|
if isDelimiter(ch, delimiters...) {
|
||||||
|
capitalizeNext = true
|
||||||
|
} else if capitalizeNext {
|
||||||
|
buffer[i] = unicode.ToTitle(ch)
|
||||||
|
capitalizeNext = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buffer)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CapitalizeFully converts all the delimiter separated words in a string into capitalized words, that is each word is made up of a
|
||||||
|
titlecase character and then a series of lowercase characters. The delimiters represent a set of characters understood
|
||||||
|
to separate words. The first string character and the first non-delimiter character after a delimiter will be capitalized.
|
||||||
|
Capitalization uses the Unicode title case, normally equivalent to upper case.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to capitalize fully
|
||||||
|
delimiters - set of characters to determine capitalization, exclusion of this parameter means whitespace would be delimeter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
capitalized string
|
||||||
|
*/
|
||||||
|
func CapitalizeFully(str string, delimiters ...rune) string {
|
||||||
|
|
||||||
|
var delimLen int
|
||||||
|
|
||||||
|
if delimiters == nil {
|
||||||
|
delimLen = -1
|
||||||
|
} else {
|
||||||
|
delimLen = len(delimiters)
|
||||||
|
}
|
||||||
|
|
||||||
|
if str == "" || delimLen == 0 {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
str = strings.ToLower(str)
|
||||||
|
return Capitalize(str, delimiters...)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Uncapitalize uncapitalizes all the whitespace separated words in a string. Only the first letter of each word is changed.
|
||||||
|
The delimiters represent a set of characters understood to separate words. The first string character and the first non-delimiter
|
||||||
|
character after a delimiter will be uncapitalized. Whitespace is defined by unicode.IsSpace(char).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to uncapitalize fully
|
||||||
|
delimiters - set of characters to determine capitalization, exclusion of this parameter means whitespace would be delimeter
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
uncapitalized string
|
||||||
|
*/
|
||||||
|
func Uncapitalize(str string, delimiters ...rune) string {
|
||||||
|
|
||||||
|
var delimLen int
|
||||||
|
|
||||||
|
if delimiters == nil {
|
||||||
|
delimLen = -1
|
||||||
|
} else {
|
||||||
|
delimLen = len(delimiters)
|
||||||
|
}
|
||||||
|
|
||||||
|
if str == "" || delimLen == 0 {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := []rune(str)
|
||||||
|
uncapitalizeNext := true // TODO Always makes capitalize/un apply to first char.
|
||||||
|
for i := 0; i < len(buffer); i++ {
|
||||||
|
ch := buffer[i]
|
||||||
|
if isDelimiter(ch, delimiters...) {
|
||||||
|
uncapitalizeNext = true
|
||||||
|
} else if uncapitalizeNext {
|
||||||
|
buffer[i] = unicode.ToLower(ch)
|
||||||
|
uncapitalizeNext = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SwapCase swaps the case of a string using a word based algorithm.
|
||||||
|
|
||||||
|
Conversion algorithm:
|
||||||
|
|
||||||
|
Upper case character converts to Lower case
|
||||||
|
Title case character converts to Lower case
|
||||||
|
Lower case character after Whitespace or at start converts to Title case
|
||||||
|
Other Lower case character converts to Upper case
|
||||||
|
Whitespace is defined by unicode.IsSpace(char).
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to swap case
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
the changed string
|
||||||
|
*/
|
||||||
|
func SwapCase(str string) string {
|
||||||
|
if str == "" {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
buffer := []rune(str)
|
||||||
|
|
||||||
|
whitespace := true
|
||||||
|
|
||||||
|
for i := 0; i < len(buffer); i++ {
|
||||||
|
ch := buffer[i]
|
||||||
|
if unicode.IsUpper(ch) {
|
||||||
|
buffer[i] = unicode.ToLower(ch)
|
||||||
|
whitespace = false
|
||||||
|
} else if unicode.IsTitle(ch) {
|
||||||
|
buffer[i] = unicode.ToLower(ch)
|
||||||
|
whitespace = false
|
||||||
|
} else if unicode.IsLower(ch) {
|
||||||
|
if whitespace {
|
||||||
|
buffer[i] = unicode.ToTitle(ch)
|
||||||
|
whitespace = false
|
||||||
|
} else {
|
||||||
|
buffer[i] = unicode.ToUpper(ch)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
whitespace = unicode.IsSpace(ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initials extracts the initial letters from each word in the string. The first letter of the string and all first
|
||||||
|
letters after the defined delimiters are returned as a new string. Their case is not changed. If the delimiters
|
||||||
|
parameter is excluded, then Whitespace is used. Whitespace is defined by unicode.IsSpacea(char). An empty delimiter array returns an empty string.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
str - the string to get initials from
|
||||||
|
delimiters - set of characters to determine words, exclusion of this parameter means whitespace would be delimeter
|
||||||
|
Returns:
|
||||||
|
string of initial letters
|
||||||
|
*/
|
||||||
|
func Initials(str string, delimiters ...rune) string {
|
||||||
|
if str == "" {
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
if delimiters != nil && len(delimiters) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
strLen := len(str)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
lastWasGap := true
|
||||||
|
for i := 0; i < strLen; i++ {
|
||||||
|
ch := rune(str[i])
|
||||||
|
|
||||||
|
if isDelimiter(ch, delimiters...) {
|
||||||
|
lastWasGap = true
|
||||||
|
} else if lastWasGap {
|
||||||
|
buf.WriteRune(ch)
|
||||||
|
lastWasGap = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// private function (lower case func name)
|
||||||
|
func isDelimiter(ch rune, delimiters ...rune) bool {
|
||||||
|
if delimiters == nil {
|
||||||
|
return unicode.IsSpace(ch)
|
||||||
|
}
|
||||||
|
for _, delimiter := range delimiters {
|
||||||
|
if ch == delimiter {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
29
vendor/github.com/Masterminds/semver/.travis.yml
generated
vendored
Normal file
29
vendor/github.com/Masterminds/semver/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.6.x
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
|
- 1.12.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
# Setting sudo access to false will let Travis CI use containers rather than
|
||||||
|
# VMs to run the tests. For more details see:
|
||||||
|
# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/
|
||||||
|
# - http://docs.travis-ci.com/user/workers/standard-infrastructure/
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make setup
|
||||||
|
- make test
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/06e3328629952dabe3e0
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: never # options: [always|never|change] default: always
|
109
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
Normal file
109
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# 1.5.0 (2019-09-11)
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- #103: Add basic fuzzing for `NewVersion()` (thanks @jesse-c)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- #82: Clarify wildcard meaning in range constraints and update tests for it (thanks @greysteil)
|
||||||
|
- #83: Clarify caret operator range for pre-1.0.0 dependencies (thanks @greysteil)
|
||||||
|
- #72: Adding docs comment pointing to vert for a cli
|
||||||
|
- #71: Update the docs on pre-release comparator handling
|
||||||
|
- #89: Test with new go versions (thanks @thedevsaddam)
|
||||||
|
- #87: Added $ to ValidPrerelease for better validation (thanks @jeremycarroll)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- #78: Fix unchecked error in example code (thanks @ravron)
|
||||||
|
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
|
||||||
|
- #97: Fixed copyright file for proper display on GitHub
|
||||||
|
- #107: Fix handling prerelease when sorting alphanum and num
|
||||||
|
- #109: Fixed where Validate sometimes returns wrong message on error
|
||||||
|
|
||||||
|
# 1.4.2 (2018-04-10)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- #72: Updated the docs to point to vert for a console appliaction
|
||||||
|
- #71: Update the docs on pre-release comparator handling
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
|
||||||
|
|
||||||
|
# 1.4.1 (2018-04-02)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Fixed #64: Fix pre-release precedence issue (thanks @uudashr)
|
||||||
|
|
||||||
|
# 1.4.0 (2017-10-04)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill)
|
||||||
|
|
||||||
|
# 1.3.1 (2017-07-10)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Fixed #57: number comparisons in prerelease sometimes inaccurate
|
||||||
|
|
||||||
|
# 1.3.0 (2017-05-02)
|
||||||
|
|
||||||
|
## Added
|
||||||
|
- #45: Added json (un)marshaling support (thanks @mh-cbon)
|
||||||
|
- Stability marker. See https://masterminds.github.io/stability/
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #51: Fix handling of single digit tilde constraint (thanks @dgodd)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- #55: The godoc icon moved from png to svg
|
||||||
|
|
||||||
|
# 1.2.3 (2017-04-03)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #46: Fixed 0.x.x and 0.0.x in constraints being treated as *
|
||||||
|
|
||||||
|
# Release 1.2.2 (2016-12-13)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #34: Fixed issue where hyphen range was not working with pre-release parsing.
|
||||||
|
|
||||||
|
# Release 1.2.1 (2016-11-28)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha"
|
||||||
|
properly.
|
||||||
|
|
||||||
|
# Release 1.2.0 (2016-11-04)
|
||||||
|
|
||||||
|
## Added
|
||||||
|
- #20: Added MustParse function for versions (thanks @adamreese)
|
||||||
|
- #15: Added increment methods on versions (thanks @mh-cbon)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and
|
||||||
|
might not satisfy the intended compatibility. The change here ignores pre-releases
|
||||||
|
on constraint checks (e.g., ~ or ^) when a pre-release is not part of the
|
||||||
|
constraint. For example, `^1.2.3` will ignore pre-releases while
|
||||||
|
`^1.2.3-alpha` will include them.
|
||||||
|
|
||||||
|
# Release 1.1.1 (2016-06-30)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- Issue #9: Speed up version comparison performance (thanks @sdboyer)
|
||||||
|
- Issue #8: Added benchmarks (thanks @sdboyer)
|
||||||
|
- Updated Go Report Card URL to new location
|
||||||
|
- Updated Readme to add code snippet formatting (thanks @mh-cbon)
|
||||||
|
- Updating tagging to v[SemVer] structure for compatibility with other tools.
|
||||||
|
|
||||||
|
# Release 1.1.0 (2016-03-11)
|
||||||
|
|
||||||
|
- Issue #2: Implemented validation to provide reasons a versions failed a
|
||||||
|
constraint.
|
||||||
|
|
||||||
|
# Release 1.0.1 (2015-12-31)
|
||||||
|
|
||||||
|
- Fixed #1: * constraint failing on valid versions.
|
||||||
|
|
||||||
|
# Release 1.0.0 (2015-10-20)
|
||||||
|
|
||||||
|
- Initial release
|
19
vendor/github.com/Masterminds/semver/LICENSE.txt
generated
vendored
Normal file
19
vendor/github.com/Masterminds/semver/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (C) 2014-2019, Matt Butcher and Matt Farina
|
||||||
|
|
||||||
|
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.
|
36
vendor/github.com/Masterminds/semver/Makefile
generated
vendored
Normal file
36
vendor/github.com/Masterminds/semver/Makefile
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
.PHONY: setup
|
||||||
|
setup:
|
||||||
|
go get -u gopkg.in/alecthomas/gometalinter.v1
|
||||||
|
gometalinter.v1 --install
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: validate lint
|
||||||
|
@echo "==> Running tests"
|
||||||
|
go test -v
|
||||||
|
|
||||||
|
.PHONY: validate
|
||||||
|
validate:
|
||||||
|
@echo "==> Running static validations"
|
||||||
|
@gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable deadcode \
|
||||||
|
--severity deadcode:error \
|
||||||
|
--enable gofmt \
|
||||||
|
--enable gosimple \
|
||||||
|
--enable ineffassign \
|
||||||
|
--enable misspell \
|
||||||
|
--enable vet \
|
||||||
|
--tests \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || exit_code=1
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint:
|
||||||
|
@echo "==> Running linters"
|
||||||
|
@gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable golint \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || :
|
194
vendor/github.com/Masterminds/semver/README.md
generated
vendored
Normal file
194
vendor/github.com/Masterminds/semver/README.md
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# SemVer
|
||||||
|
|
||||||
|
The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to:
|
||||||
|
|
||||||
|
* Parse semantic versions
|
||||||
|
* Sort semantic versions
|
||||||
|
* Check if a semantic version fits within a set of constraints
|
||||||
|
* Optionally work with a `v` prefix
|
||||||
|
|
||||||
|
[![Stability:
|
||||||
|
Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html)
|
||||||
|
[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.svg)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver)
|
||||||
|
|
||||||
|
If you are looking for a command line tool for version comparisons please see
|
||||||
|
[vert](https://github.com/Masterminds/vert) which uses this library.
|
||||||
|
|
||||||
|
## Parsing Semantic Versions
|
||||||
|
|
||||||
|
To parse a semantic version use the `NewVersion` function. For example,
|
||||||
|
|
||||||
|
```go
|
||||||
|
v, err := semver.NewVersion("1.2.3-beta.1+build345")
|
||||||
|
```
|
||||||
|
|
||||||
|
If there is an error the version wasn't parseable. The version object has methods
|
||||||
|
to get the parts of the version, compare it to other versions, convert the
|
||||||
|
version back into a string, and get the original string. For more details
|
||||||
|
please see the [documentation](https://godoc.org/github.com/Masterminds/semver).
|
||||||
|
|
||||||
|
## Sorting Semantic Versions
|
||||||
|
|
||||||
|
A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/)
|
||||||
|
package from the standard library. For example,
|
||||||
|
|
||||||
|
```go
|
||||||
|
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
|
||||||
|
vs := make([]*semver.Version, len(raw))
|
||||||
|
for i, r := range raw {
|
||||||
|
v, err := semver.NewVersion(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error parsing version: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vs[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(semver.Collection(vs))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Checking Version Constraints
|
||||||
|
|
||||||
|
Checking a version against version constraints is one of the most featureful
|
||||||
|
parts of the package.
|
||||||
|
|
||||||
|
```go
|
||||||
|
c, err := semver.NewConstraint(">= 1.2.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle constraint not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _ := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parseable.
|
||||||
|
}
|
||||||
|
// Check if the version meets the constraints. The a variable will be true.
|
||||||
|
a := c.Check(v)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic Comparisons
|
||||||
|
|
||||||
|
There are two elements to the comparisons. First, a comparison string is a list
|
||||||
|
of comma separated and comparisons. These are then separated by || separated or
|
||||||
|
comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a
|
||||||
|
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
|
||||||
|
greater than or equal to 4.2.3.
|
||||||
|
|
||||||
|
The basic comparisons are:
|
||||||
|
|
||||||
|
* `=`: equal (aliased to no operator)
|
||||||
|
* `!=`: not equal
|
||||||
|
* `>`: greater than
|
||||||
|
* `<`: less than
|
||||||
|
* `>=`: greater than or equal to
|
||||||
|
* `<=`: less than or equal to
|
||||||
|
|
||||||
|
## Working With Pre-release Versions
|
||||||
|
|
||||||
|
Pre-releases, for those not familiar with them, are used for software releases
|
||||||
|
prior to stable or generally available releases. Examples of pre-releases include
|
||||||
|
development, alpha, beta, and release candidate releases. A pre-release may be
|
||||||
|
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
|
||||||
|
order of precidence, pre-releases come before their associated releases. In this
|
||||||
|
example `1.2.3-beta.1 < 1.2.3`.
|
||||||
|
|
||||||
|
According to the Semantic Version specification pre-releases may not be
|
||||||
|
API compliant with their release counterpart. It says,
|
||||||
|
|
||||||
|
> A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
|
||||||
|
|
||||||
|
SemVer comparisons without a pre-release comparator will skip pre-release versions.
|
||||||
|
For example, `>=1.2.3` will skip pre-releases when looking at a list of releases
|
||||||
|
while `>=1.2.3-0` will evaluate and find pre-releases.
|
||||||
|
|
||||||
|
The reason for the `0` as a pre-release version in the example comparison is
|
||||||
|
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
|
||||||
|
`.` separators), per the spec. Sorting happens in ASCII sort order, again per the spec. The lowest character is a `0` in ASCII sort order (see an [ASCII Table](http://www.asciitable.com/))
|
||||||
|
|
||||||
|
Understanding ASCII sort ordering is important because A-Z comes before a-z. That
|
||||||
|
means `>=1.2.3-BETA` will return `1.2.3-alpha`. What you might expect from case
|
||||||
|
sensitivity doesn't apply here. This is due to ASCII sort ordering which is what
|
||||||
|
the spec specifies.
|
||||||
|
|
||||||
|
## Hyphen Range Comparisons
|
||||||
|
|
||||||
|
There are multiple methods to handle ranges and the first is hyphens ranges.
|
||||||
|
These look like:
|
||||||
|
|
||||||
|
* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
|
||||||
|
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5`
|
||||||
|
|
||||||
|
## Wildcards In Comparisons
|
||||||
|
|
||||||
|
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
|
||||||
|
for all comparison operators. When used on the `=` operator it falls
|
||||||
|
back to the pack level comparison (see tilde below). For example,
|
||||||
|
|
||||||
|
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
|
||||||
|
* `>= 1.2.x` is equivalent to `>= 1.2.0`
|
||||||
|
* `<= 2.x` is equivalent to `< 3`
|
||||||
|
* `*` is equivalent to `>= 0.0.0`
|
||||||
|
|
||||||
|
## Tilde Range Comparisons (Patch)
|
||||||
|
|
||||||
|
The tilde (`~`) comparison operator is for patch level ranges when a minor
|
||||||
|
version is specified and major level changes when the minor number is missing.
|
||||||
|
For example,
|
||||||
|
|
||||||
|
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
|
||||||
|
* `~1` is equivalent to `>= 1, < 2`
|
||||||
|
* `~2.3` is equivalent to `>= 2.3, < 2.4`
|
||||||
|
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
|
||||||
|
* `~1.x` is equivalent to `>= 1, < 2`
|
||||||
|
|
||||||
|
## Caret Range Comparisons (Major)
|
||||||
|
|
||||||
|
The caret (`^`) comparison operator is for major level changes. This is useful
|
||||||
|
when comparisons of API versions as a major change is API breaking. For example,
|
||||||
|
|
||||||
|
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
|
||||||
|
* `^0.0.1` is equivalent to `>= 0.0.1, < 1.0.0`
|
||||||
|
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
|
||||||
|
* `^2.3` is equivalent to `>= 2.3, < 3`
|
||||||
|
* `^2.x` is equivalent to `>= 2.0.0, < 3`
|
||||||
|
|
||||||
|
# Validation
|
||||||
|
|
||||||
|
In addition to testing a version against a constraint, a version can be validated
|
||||||
|
against a constraint. When validation fails a slice of errors containing why a
|
||||||
|
version didn't meet the constraint is returned. For example,
|
||||||
|
|
||||||
|
```go
|
||||||
|
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
|
||||||
|
if err != nil {
|
||||||
|
// Handle constraint not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _ := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate a version against a constraint.
|
||||||
|
a, msgs := c.Validate(v)
|
||||||
|
// a is false
|
||||||
|
for _, m := range msgs {
|
||||||
|
fmt.Println(m)
|
||||||
|
|
||||||
|
// Loops over the errors which would read
|
||||||
|
// "1.3 is greater than 1.2.3"
|
||||||
|
// "1.3 is less than 1.4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Fuzzing
|
||||||
|
|
||||||
|
[dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz) is used for fuzzing.
|
||||||
|
|
||||||
|
1. `go-fuzz-build`
|
||||||
|
2. `go-fuzz -workdir=fuzz`
|
||||||
|
|
||||||
|
# Contribute
|
||||||
|
|
||||||
|
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
|
||||||
|
or [create a pull request](https://github.com/Masterminds/semver/pulls).
|
44
vendor/github.com/Masterminds/semver/appveyor.yml
generated
vendored
Normal file
44
vendor/github.com/Masterminds/semver/appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
version: build-{build}.{branch}
|
||||||
|
|
||||||
|
clone_folder: C:\gopath\src\github.com\Masterminds\semver
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: C:\gopath
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
- go get -u gopkg.in/alecthomas/gometalinter.v1
|
||||||
|
- set PATH=%PATH%;%GOPATH%\bin
|
||||||
|
- gometalinter.v1.exe --install
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- go install -v ./...
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- "gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable deadcode \
|
||||||
|
--severity deadcode:error \
|
||||||
|
--enable gofmt \
|
||||||
|
--enable gosimple \
|
||||||
|
--enable ineffassign \
|
||||||
|
--enable misspell \
|
||||||
|
--enable vet \
|
||||||
|
--tests \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || exit_code=1"
|
||||||
|
- "gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable golint \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || :"
|
||||||
|
- go test -v
|
||||||
|
|
||||||
|
deploy: off
|
24
vendor/github.com/Masterminds/semver/collection.go
generated
vendored
Normal file
24
vendor/github.com/Masterminds/semver/collection.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
// Collection is a collection of Version instances and implements the sort
|
||||||
|
// interface. See the sort package for more details.
|
||||||
|
// https://golang.org/pkg/sort/
|
||||||
|
type Collection []*Version
|
||||||
|
|
||||||
|
// Len returns the length of a collection. The number of Version instances
|
||||||
|
// on the slice.
|
||||||
|
func (c Collection) Len() int {
|
||||||
|
return len(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less is needed for the sort interface to compare two Version objects on the
|
||||||
|
// slice. If checks if one is less than the other.
|
||||||
|
func (c Collection) Less(i, j int) bool {
|
||||||
|
return c[i].LessThan(c[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap is needed for the sort interface to replace the Version objects
|
||||||
|
// at two different positions in the slice.
|
||||||
|
func (c Collection) Swap(i, j int) {
|
||||||
|
c[i], c[j] = c[j], c[i]
|
||||||
|
}
|
423
vendor/github.com/Masterminds/semver/constraints.go
generated
vendored
Normal file
423
vendor/github.com/Masterminds/semver/constraints.go
generated
vendored
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
package semver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constraints is one or more constraint that a semantic version can be
|
||||||
|
// checked against.
|
||||||
|
type Constraints struct {
|
||||||
|
constraints [][]*constraint
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConstraint returns a Constraints instance that a Version instance can
|
||||||
|
// be checked against. If there is a parse error it will be returned.
|
||||||
|
func NewConstraint(c string) (*Constraints, error) {
|
||||||
|
|
||||||
|
// Rewrite - ranges into a comparison operation.
|
||||||
|
c = rewriteRange(c)
|
||||||
|
|
||||||
|
ors := strings.Split(c, "||")
|
||||||
|
or := make([][]*constraint, len(ors))
|
||||||
|
for k, v := range ors {
|
||||||
|
cs := strings.Split(v, ",")
|
||||||
|
result := make([]*constraint, len(cs))
|
||||||
|
for i, s := range cs {
|
||||||
|
pc, err := parseConstraint(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = pc
|
||||||
|
}
|
||||||
|
or[k] = result
|
||||||
|
}
|
||||||
|
|
||||||
|
o := &Constraints{constraints: or}
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check tests if a version satisfies the constraints.
|
||||||
|
func (cs Constraints) Check(v *Version) bool {
|
||||||
|
// loop over the ORs and check the inner ANDs
|
||||||
|
for _, o := range cs.constraints {
|
||||||
|
joy := true
|
||||||
|
for _, c := range o {
|
||||||
|
if !c.check(v) {
|
||||||
|
joy = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if joy {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks if a version satisfies a constraint. If not a slice of
|
||||||
|
// reasons for the failure are returned in addition to a bool.
|
||||||
|
func (cs Constraints) Validate(v *Version) (bool, []error) {
|
||||||
|
// loop over the ORs and check the inner ANDs
|
||||||
|
var e []error
|
||||||
|
|
||||||
|
// Capture the prerelease message only once. When it happens the first time
|
||||||
|
// this var is marked
|
||||||
|
var prerelesase bool
|
||||||
|
for _, o := range cs.constraints {
|
||||||
|
joy := true
|
||||||
|
for _, c := range o {
|
||||||
|
// Before running the check handle the case there the version is
|
||||||
|
// a prerelease and the check is not searching for prereleases.
|
||||||
|
if c.con.pre == "" && v.pre != "" {
|
||||||
|
if !prerelesase {
|
||||||
|
em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
|
||||||
|
e = append(e, em)
|
||||||
|
prerelesase = true
|
||||||
|
}
|
||||||
|
joy = false
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if !c.check(v) {
|
||||||
|
em := fmt.Errorf(c.msg, v, c.orig)
|
||||||
|
e = append(e, em)
|
||||||
|
joy = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if joy {
|
||||||
|
return true, []error{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, e
|
||||||
|
}
|
||||||
|
|
||||||
|
var constraintOps map[string]cfunc
|
||||||
|
var constraintMsg map[string]string
|
||||||
|
var constraintRegex *regexp.Regexp
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
constraintOps = map[string]cfunc{
|
||||||
|
"": constraintTildeOrEqual,
|
||||||
|
"=": constraintTildeOrEqual,
|
||||||
|
"!=": constraintNotEqual,
|
||||||
|
">": constraintGreaterThan,
|
||||||
|
"<": constraintLessThan,
|
||||||
|
">=": constraintGreaterThanEqual,
|
||||||
|
"=>": constraintGreaterThanEqual,
|
||||||
|
"<=": constraintLessThanEqual,
|
||||||
|
"=<": constraintLessThanEqual,
|
||||||
|
"~": constraintTilde,
|
||||||
|
"~>": constraintTilde,
|
||||||
|
"^": constraintCaret,
|
||||||
|
}
|
||||||
|
|
||||||
|
constraintMsg = map[string]string{
|
||||||
|
"": "%s is not equal to %s",
|
||||||
|
"=": "%s is not equal to %s",
|
||||||
|
"!=": "%s is equal to %s",
|
||||||
|
">": "%s is less than or equal to %s",
|
||||||
|
"<": "%s is greater than or equal to %s",
|
||||||
|
">=": "%s is less than %s",
|
||||||
|
"=>": "%s is less than %s",
|
||||||
|
"<=": "%s is greater than %s",
|
||||||
|
"=<": "%s is greater than %s",
|
||||||
|
"~": "%s does not have same major and minor version as %s",
|
||||||
|
"~>": "%s does not have same major and minor version as %s",
|
||||||
|
"^": "%s does not have same major version as %s",
|
||||||
|
}
|
||||||
|
|
||||||
|
ops := make([]string, 0, len(constraintOps))
|
||||||
|
for k := range constraintOps {
|
||||||
|
ops = append(ops, regexp.QuoteMeta(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
constraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`^\s*(%s)\s*(%s)\s*$`,
|
||||||
|
strings.Join(ops, "|"),
|
||||||
|
cvRegex))
|
||||||
|
|
||||||
|
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
|
||||||
|
`\s*(%s)\s+-\s+(%s)\s*`,
|
||||||
|
cvRegex, cvRegex))
|
||||||
|
}
|
||||||
|
|
||||||
|
// An individual constraint
|
||||||
|
type constraint struct {
|
||||||
|
// The callback function for the restraint. It performs the logic for
|
||||||
|
// the constraint.
|
||||||
|
function cfunc
|
||||||
|
|
||||||
|
msg string
|
||||||
|
|
||||||
|
// The version used in the constraint check. For example, if a constraint
|
||||||
|
// is '<= 2.0.0' the con a version instance representing 2.0.0.
|
||||||
|
con *Version
|
||||||
|
|
||||||
|
// The original parsed version (e.g., 4.x from != 4.x)
|
||||||
|
orig string
|
||||||
|
|
||||||
|
// When an x is used as part of the version (e.g., 1.x)
|
||||||
|
minorDirty bool
|
||||||
|
dirty bool
|
||||||
|
patchDirty bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a version meets the constraint
|
||||||
|
func (c *constraint) check(v *Version) bool {
|
||||||
|
return c.function(v, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
type cfunc func(v *Version, c *constraint) bool
|
||||||
|
|
||||||
|
func parseConstraint(c string) (*constraint, error) {
|
||||||
|
m := constraintRegex.FindStringSubmatch(c)
|
||||||
|
if m == nil {
|
||||||
|
return nil, fmt.Errorf("improper constraint: %s", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
ver := m[2]
|
||||||
|
orig := ver
|
||||||
|
minorDirty := false
|
||||||
|
patchDirty := false
|
||||||
|
dirty := false
|
||||||
|
if isX(m[3]) {
|
||||||
|
ver = "0.0.0"
|
||||||
|
dirty = true
|
||||||
|
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
|
||||||
|
minorDirty = true
|
||||||
|
dirty = true
|
||||||
|
ver = fmt.Sprintf("%s.0.0%s", m[3], m[6])
|
||||||
|
} else if isX(strings.TrimPrefix(m[5], ".")) {
|
||||||
|
dirty = true
|
||||||
|
patchDirty = true
|
||||||
|
ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6])
|
||||||
|
}
|
||||||
|
|
||||||
|
con, err := NewVersion(ver)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
// The constraintRegex should catch any regex parsing errors. So,
|
||||||
|
// we should never get here.
|
||||||
|
return nil, errors.New("constraint Parser Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := &constraint{
|
||||||
|
function: constraintOps[m[1]],
|
||||||
|
msg: constraintMsg[m[1]],
|
||||||
|
con: con,
|
||||||
|
orig: orig,
|
||||||
|
minorDirty: minorDirty,
|
||||||
|
patchDirty: patchDirty,
|
||||||
|
dirty: dirty,
|
||||||
|
}
|
||||||
|
return cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint functions
|
||||||
|
func constraintNotEqual(v *Version, c *constraint) bool {
|
||||||
|
if c.dirty {
|
||||||
|
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.con.Major() != v.Major() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if c.con.Minor() != v.Minor() && !c.minorDirty {
|
||||||
|
return true
|
||||||
|
} else if c.minorDirty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !v.Equal(c.con)
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintGreaterThan(v *Version, c *constraint) bool {
|
||||||
|
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Compare(c.con) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintLessThan(v *Version, c *constraint) bool {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.dirty {
|
||||||
|
return v.Compare(c.con) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() > c.con.Major() {
|
||||||
|
return false
|
||||||
|
} else if v.Minor() > c.con.Minor() && !c.minorDirty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintGreaterThanEqual(v *Version, c *constraint) bool {
|
||||||
|
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Compare(c.con) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func constraintLessThanEqual(v *Version, c *constraint) bool {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.dirty {
|
||||||
|
return v.Compare(c.con) <= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() > c.con.Major() {
|
||||||
|
return false
|
||||||
|
} else if v.Minor() > c.con.Minor() && !c.minorDirty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~*, ~>* --> >= 0.0.0 (any)
|
||||||
|
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0
|
||||||
|
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0
|
||||||
|
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
|
||||||
|
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
|
||||||
|
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
|
||||||
|
func constraintTilde(v *Version, c *constraint) bool {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.LessThan(c.con) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~0.0.0 is a special case where all constraints are accepted. It's
|
||||||
|
// equivalent to >= 0.0.0.
|
||||||
|
if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 &&
|
||||||
|
!c.minorDirty && !c.patchDirty {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() != c.con.Major() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Minor() != c.con.Minor() && !c.minorDirty {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
|
||||||
|
// it's a straight =
|
||||||
|
func constraintTildeOrEqual(v *Version, c *constraint) bool {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.dirty {
|
||||||
|
c.msg = constraintMsg["~"]
|
||||||
|
return constraintTilde(v, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Equal(c.con)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^* --> (any)
|
||||||
|
// ^2, ^2.x, ^2.x.x --> >=2.0.0, <3.0.0
|
||||||
|
// ^2.0, ^2.0.x --> >=2.0.0, <3.0.0
|
||||||
|
// ^1.2, ^1.2.x --> >=1.2.0, <2.0.0
|
||||||
|
// ^1.2.3 --> >=1.2.3, <2.0.0
|
||||||
|
// ^1.2.0 --> >=1.2.0, <2.0.0
|
||||||
|
func constraintCaret(v *Version, c *constraint) bool {
|
||||||
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
|
// more details.
|
||||||
|
if v.Prerelease() != "" && c.con.Prerelease() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.LessThan(c.con) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Major() != c.con.Major() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var constraintRangeRegex *regexp.Regexp
|
||||||
|
|
||||||
|
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
|
||||||
|
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
||||||
|
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
|
||||||
|
|
||||||
|
func isX(x string) bool {
|
||||||
|
switch x {
|
||||||
|
case "x", "*", "X":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewriteRange(i string) string {
|
||||||
|
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
|
||||||
|
if m == nil {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
o := i
|
||||||
|
for _, v := range m {
|
||||||
|
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
|
||||||
|
o = strings.Replace(o, v[0], t, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
115
vendor/github.com/Masterminds/semver/doc.go
generated
vendored
Normal file
115
vendor/github.com/Masterminds/semver/doc.go
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go.
|
||||||
|
|
||||||
|
Specifically it provides the ability to:
|
||||||
|
|
||||||
|
* Parse semantic versions
|
||||||
|
* Sort semantic versions
|
||||||
|
* Check if a semantic version fits within a set of constraints
|
||||||
|
* Optionally work with a `v` prefix
|
||||||
|
|
||||||
|
Parsing Semantic Versions
|
||||||
|
|
||||||
|
To parse a semantic version use the `NewVersion` function. For example,
|
||||||
|
|
||||||
|
v, err := semver.NewVersion("1.2.3-beta.1+build345")
|
||||||
|
|
||||||
|
If there is an error the version wasn't parseable. The version object has methods
|
||||||
|
to get the parts of the version, compare it to other versions, convert the
|
||||||
|
version back into a string, and get the original string. For more details
|
||||||
|
please see the documentation at https://godoc.org/github.com/Masterminds/semver.
|
||||||
|
|
||||||
|
Sorting Semantic Versions
|
||||||
|
|
||||||
|
A set of versions can be sorted using the `sort` package from the standard library.
|
||||||
|
For example,
|
||||||
|
|
||||||
|
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
|
||||||
|
vs := make([]*semver.Version, len(raw))
|
||||||
|
for i, r := range raw {
|
||||||
|
v, err := semver.NewVersion(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error parsing version: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vs[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(semver.Collection(vs))
|
||||||
|
|
||||||
|
Checking Version Constraints
|
||||||
|
|
||||||
|
Checking a version against version constraints is one of the most featureful
|
||||||
|
parts of the package.
|
||||||
|
|
||||||
|
c, err := semver.NewConstraint(">= 1.2.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle constraint not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parseable.
|
||||||
|
}
|
||||||
|
// Check if the version meets the constraints. The a variable will be true.
|
||||||
|
a := c.Check(v)
|
||||||
|
|
||||||
|
Basic Comparisons
|
||||||
|
|
||||||
|
There are two elements to the comparisons. First, a comparison string is a list
|
||||||
|
of comma separated and comparisons. These are then separated by || separated or
|
||||||
|
comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a
|
||||||
|
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
|
||||||
|
greater than or equal to 4.2.3.
|
||||||
|
|
||||||
|
The basic comparisons are:
|
||||||
|
|
||||||
|
* `=`: equal (aliased to no operator)
|
||||||
|
* `!=`: not equal
|
||||||
|
* `>`: greater than
|
||||||
|
* `<`: less than
|
||||||
|
* `>=`: greater than or equal to
|
||||||
|
* `<=`: less than or equal to
|
||||||
|
|
||||||
|
Hyphen Range Comparisons
|
||||||
|
|
||||||
|
There are multiple methods to handle ranges and the first is hyphens ranges.
|
||||||
|
These look like:
|
||||||
|
|
||||||
|
* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
|
||||||
|
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5`
|
||||||
|
|
||||||
|
Wildcards In Comparisons
|
||||||
|
|
||||||
|
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
|
||||||
|
for all comparison operators. When used on the `=` operator it falls
|
||||||
|
back to the pack level comparison (see tilde below). For example,
|
||||||
|
|
||||||
|
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
|
||||||
|
* `>= 1.2.x` is equivalent to `>= 1.2.0`
|
||||||
|
* `<= 2.x` is equivalent to `<= 3`
|
||||||
|
* `*` is equivalent to `>= 0.0.0`
|
||||||
|
|
||||||
|
Tilde Range Comparisons (Patch)
|
||||||
|
|
||||||
|
The tilde (`~`) comparison operator is for patch level ranges when a minor
|
||||||
|
version is specified and major level changes when the minor number is missing.
|
||||||
|
For example,
|
||||||
|
|
||||||
|
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
|
||||||
|
* `~1` is equivalent to `>= 1, < 2`
|
||||||
|
* `~2.3` is equivalent to `>= 2.3, < 2.4`
|
||||||
|
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
|
||||||
|
* `~1.x` is equivalent to `>= 1, < 2`
|
||||||
|
|
||||||
|
Caret Range Comparisons (Major)
|
||||||
|
|
||||||
|
The caret (`^`) comparison operator is for major level changes. This is useful
|
||||||
|
when comparisons of API versions as a major change is API breaking. For example,
|
||||||
|
|
||||||
|
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
|
||||||
|
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
|
||||||
|
* `^2.3` is equivalent to `>= 2.3, < 3`
|
||||||
|
* `^2.x` is equivalent to `>= 2.0.0, < 3`
|
||||||
|
*/
|
||||||
|
package semver
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user