aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/xanzy/go-gitlab/gitlab.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/xanzy/go-gitlab/gitlab.go')
-rw-r--r--vendor/github.com/xanzy/go-gitlab/gitlab.go492
1 files changed, 492 insertions, 0 deletions
diff --git a/vendor/github.com/xanzy/go-gitlab/gitlab.go b/vendor/github.com/xanzy/go-gitlab/gitlab.go
new file mode 100644
index 0000000..eb0ca76
--- /dev/null
+++ b/vendor/github.com/xanzy/go-gitlab/gitlab.go
@@ -0,0 +1,492 @@
+//
+// Copyright 2015, Sander van Harmelen
+//
+// 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 gitlab
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+
+ "github.com/google/go-querystring/query"
+)
+
+const (
+ libraryVersion = "0.1.1"
+ defaultBaseURL = "https://gitlab.com/api/v3/"
+ userAgent = "go-gitlab/" + libraryVersion
+)
+
+// tokenType represents a token type within GitLab.
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/
+type tokenType int
+
+// List of available token type
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/
+const (
+ privateToken tokenType = iota
+ oAuthToken
+)
+
+// AccessLevelValue represents a permission level within GitLab.
+//
+// GitLab API docs: https://docs.gitlab.com/ce/permissions/permissions.html
+type AccessLevelValue int
+
+// List of available access levels
+//
+// GitLab API docs: https://docs.gitlab.com/ce/permissions/permissions.html
+const (
+ GuestPermissions AccessLevelValue = 10
+ ReporterPermissions AccessLevelValue = 20
+ DeveloperPermissions AccessLevelValue = 30
+ MasterPermissions AccessLevelValue = 40
+ OwnerPermission AccessLevelValue = 50
+)
+
+// NotificationLevelValue represents a notification level within Gitlab.
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/
+type NotificationLevelValue int
+
+// List of available notification levels
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/
+const (
+ DisabledNotifications NotificationLevelValue = iota
+ ParticipatingNotifications
+ WatchNotifications
+ GlobalNotifications
+ MentionNotifications
+)
+
+// VisibilityLevelValue represents a visibility level within GitLab.
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/
+type VisibilityLevelValue int
+
+// List of available visibility levels
+//
+// GitLab API docs: https://docs.gitlab.com/ce/api/
+const (
+ PrivateVisibility VisibilityLevelValue = 0
+ InternalVisibility VisibilityLevelValue = 10
+ PublicVisibility VisibilityLevelValue = 20
+)
+
+// A Client manages communication with the GitLab API.
+type Client struct {
+ // HTTP client used to communicate with the API.
+ client *http.Client
+
+ // Base URL for API requests. Defaults to the public GitLab API, but can be
+ // set to a domain endpoint to use with aself hosted GitLab server. baseURL
+ // should always be specified with a trailing slash.
+ baseURL *url.URL
+
+ // token type used to make authenticated API calls.
+ tokenType tokenType
+
+ // token used to make authenticated API calls.
+ token string
+
+ // User agent used when communicating with the GitLab API.
+ UserAgent string
+
+ // Services used for talking to different parts of the GitLab API.
+ Branches *BranchesService
+ BuildVariables *BuildVariablesService
+ Builds *BuildsService
+ Commits *CommitsService
+ DeployKeys *DeployKeysService
+ Groups *GroupsService
+ Issues *IssuesService
+ Labels *LabelsService
+ MergeRequests *MergeRequestsService
+ Milestones *MilestonesService
+ Namespaces *NamespacesService
+ Notes *NotesService
+ Projects *ProjectsService
+ ProjectSnippets *ProjectSnippetsService
+ Pipelines *PipelinesService
+ Repositories *RepositoriesService
+ RepositoryFiles *RepositoryFilesService
+ Services *ServicesService
+ Session *SessionService
+ Settings *SettingsService
+ SystemHooks *SystemHooksService
+ Tags *TagsService
+ Users *UsersService
+}
+
+// ListOptions specifies the optional parameters to various List methods that
+// support pagination.
+type ListOptions struct {
+ // For paginated result sets, page of results to retrieve.
+ Page int `url:"page,omitempty" json:"page,omitempty"`
+
+ // For paginated result sets, the number of results to include per page.
+ PerPage int `url:"per_page,omitempty" json:"per_page,omitempty"`
+}
+
+// NewClient returns a new GitLab API client. If a nil httpClient is
+// provided, http.DefaultClient will be used. To use API methods which require
+// authentication, provide a valid private token.
+func NewClient(httpClient *http.Client, token string) *Client {
+ return newClient(httpClient, privateToken, token)
+}
+
+// NewOAuthClient returns a new GitLab API client. If a nil httpClient is
+// provided, http.DefaultClient will be used. To use API methods which require
+// authentication, provide a valid oauth token.
+func NewOAuthClient(httpClient *http.Client, token string) *Client {
+ return newClient(httpClient, oAuthToken, token)
+}
+
+func newClient(httpClient *http.Client, tokenType tokenType, token string) *Client {
+ if httpClient == nil {
+ httpClient = http.DefaultClient
+ }
+
+ c := &Client{client: httpClient, tokenType: tokenType, token: token, UserAgent: userAgent}
+ if err := c.SetBaseURL(defaultBaseURL); err != nil {
+ // should never happen since defaultBaseURL is our constant
+ panic(err)
+ }
+
+ c.Branches = &BranchesService{client: c}
+ c.BuildVariables = &BuildVariablesService{client: c}
+ c.Builds = &BuildsService{client: c}
+ c.Commits = &CommitsService{client: c}
+ c.DeployKeys = &DeployKeysService{client: c}
+ c.Groups = &GroupsService{client: c}
+ c.Issues = &IssuesService{client: c}
+ c.Labels = &LabelsService{client: c}
+ c.MergeRequests = &MergeRequestsService{client: c}
+ c.Milestones = &MilestonesService{client: c}
+ c.Notes = &NotesService{client: c}
+ c.Namespaces = &NamespacesService{client: c}
+ c.Projects = &ProjectsService{client: c}
+ c.ProjectSnippets = &ProjectSnippetsService{client: c}
+ c.Pipelines = &PipelinesService{client: c}
+ c.Repositories = &RepositoriesService{client: c}
+ c.RepositoryFiles = &RepositoryFilesService{client: c}
+ c.Services = &ServicesService{client: c}
+ c.Session = &SessionService{client: c}
+ c.Settings = &SettingsService{client: c}
+ c.SystemHooks = &SystemHooksService{client: c}
+ c.Tags = &TagsService{client: c}
+ c.Users = &UsersService{client: c}
+
+ return c
+}
+
+// BaseURL return a copy of the baseURL.
+func (c *Client) BaseURL() *url.URL {
+ u := *c.baseURL
+ return &u
+}
+
+// SetBaseURL sets the base URL for API requests to a custom endpoint. urlStr
+// should always be specified with a trailing slash.
+func (c *Client) SetBaseURL(urlStr string) error {
+ // Make sure the given URL end with a slash
+ if !strings.HasSuffix(urlStr, "/") {
+ urlStr += "/"
+ }
+
+ var err error
+ c.baseURL, err = url.Parse(urlStr)
+ return err
+}
+
+// NewRequest creates an API request. A relative URL path can be provided in
+// urlStr, in which case it is resolved relative to the base URL of the Client.
+// Relative URL paths should always be specified without a preceding slash. If
+// specified, the value pointed to by body is JSON encoded and included as the
+// request body.
+func (c *Client) NewRequest(method, path string, opt interface{}) (*http.Request, error) {
+ u := *c.baseURL
+ // Set the encoded opaque data
+ u.Opaque = c.baseURL.Path + path
+
+ if opt != nil {
+ q, err := query.Values(opt)
+ if err != nil {
+ return nil, err
+ }
+ u.RawQuery = q.Encode()
+ }
+
+ req := &http.Request{
+ Method: method,
+ URL: &u,
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: make(http.Header),
+ Host: u.Host,
+ }
+
+ if method == "POST" || method == "PUT" {
+ bodyBytes, err := json.Marshal(opt)
+ if err != nil {
+ return nil, err
+ }
+ bodyReader := bytes.NewReader(bodyBytes)
+
+ u.RawQuery = ""
+ req.Body = ioutil.NopCloser(bodyReader)
+ req.ContentLength = int64(bodyReader.Len())
+ req.Header.Set("Content-Type", "application/json")
+ }
+
+ req.Header.Set("Accept", "application/json")
+
+ switch c.tokenType {
+ case privateToken:
+ req.Header.Set("PRIVATE-TOKEN", c.token)
+ case oAuthToken:
+ req.Header.Set("Authorization", "Bearer "+c.token)
+ }
+
+ if c.UserAgent != "" {
+ req.Header.Set("User-Agent", c.UserAgent)
+ }
+
+ return req, nil
+}
+
+// Response is a GitLab API response. This wraps the standard http.Response
+// returned from GitLab and provides convenient access to things like
+// pagination links.
+type Response struct {
+ *http.Response
+
+ // These fields provide the page values for paginating through a set of
+ // results. Any or all of these may be set to the zero value for
+ // responses that are not part of a paginated set, or for which there
+ // are no additional pages.
+
+ NextPage int
+ PrevPage int
+ FirstPage int
+ LastPage int
+}
+
+// newResponse creats a new Response for the provided http.Response.
+func newResponse(r *http.Response) *Response {
+ response := &Response{Response: r}
+ response.populatePageValues()
+ return response
+}
+
+// populatePageValues parses the HTTP Link response headers and populates the
+// various pagination link values in the Reponse.
+func (r *Response) populatePageValues() {
+ if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 {
+ for _, link := range strings.Split(links[0], ",") {
+ segments := strings.Split(strings.TrimSpace(link), ";")
+
+ // link must at least have href and rel
+ if len(segments) < 2 {
+ continue
+ }
+
+ // ensure href is properly formatted
+ if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") {
+ continue
+ }
+
+ // try to pull out page parameter
+ url, err := url.Parse(segments[0][1 : len(segments[0])-1])
+ if err != nil {
+ continue
+ }
+ page := url.Query().Get("page")
+ if page == "" {
+ continue
+ }
+
+ for _, segment := range segments[1:] {
+ switch strings.TrimSpace(segment) {
+ case `rel="next"`:
+ r.NextPage, _ = strconv.Atoi(page)
+ case `rel="prev"`:
+ r.PrevPage, _ = strconv.Atoi(page)
+ case `rel="first"`:
+ r.FirstPage, _ = strconv.Atoi(page)
+ case `rel="last"`:
+ r.LastPage, _ = strconv.Atoi(page)
+ }
+
+ }
+ }
+ }
+}
+
+// Do sends an API request and returns the API response. The API response is
+// JSON decoded and stored in the value pointed to by v, or returned as an
+// error if an API error has occurred. If v implements the io.Writer
+// interface, the raw response body will be written to v, without attempting to
+// first decode it.
+func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
+ resp, err := c.client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ response := newResponse(resp)
+
+ err = CheckResponse(resp)
+ if err != nil {
+ // even though there was an error, we still return the response
+ // in case the caller wants to inspect it further
+ return response, err
+ }
+
+ if v != nil {
+ if w, ok := v.(io.Writer); ok {
+ _, err = io.Copy(w, resp.Body)
+ } else {
+ err = json.NewDecoder(resp.Body).Decode(v)
+ }
+ }
+ return response, err
+}
+
+// Helper function to accept and format both the project ID or name as project
+// identifier for all API calls.
+func parseID(id interface{}) (string, error) {
+ switch v := id.(type) {
+ case int:
+ return strconv.Itoa(v), nil
+ case string:
+ return v, nil
+ default:
+ return "", fmt.Errorf("invalid ID type %#v, the ID must be an int or a string", id)
+ }
+}
+
+// An ErrorResponse reports one or more errors caused by an API request.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ce/api/README.html#data-validation-and-error-reporting
+type ErrorResponse struct {
+ Response *http.Response // HTTP response that caused this error
+ Message string `json:"message"` // error message
+ Errors []Error `json:"errors"` // more detail on individual errors
+}
+
+func (r *ErrorResponse) Error() string {
+ path, _ := url.QueryUnescape(r.Response.Request.URL.Opaque)
+ ru := fmt.Sprintf("%s://%s%s", r.Response.Request.URL.Scheme, r.Response.Request.URL.Host, path)
+
+ return fmt.Sprintf("%v %s: %d %v %+v",
+ r.Response.Request.Method, ru, r.Response.StatusCode, r.Message, r.Errors)
+}
+
+// An Error reports more details on an individual error in an ErrorResponse.
+// These are the possible validation error codes:
+//
+// missing:
+// resource does not exist
+// missing_field:
+// a required field on a resource has not been set
+// invalid:
+// the formatting of a field is invalid
+// already_exists:
+// another resource has the same valid as this field
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ce/api/README.html#data-validation-and-error-reporting
+type Error struct {
+ Resource string `json:"resource"` // resource on which the error occurred
+ Field string `json:"field"` // field on which the error occurred
+ Code string `json:"code"` // validation error code
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("%v error caused by %v field on %v resource",
+ e.Code, e.Field, e.Resource)
+}
+
+// CheckResponse checks the API response for errors, and returns them if
+// present. A response is considered an error if it has a status code outside
+// the 200 range. API error responses are expected to have either no response
+// body, or a JSON response body that maps to ErrorResponse. Any other
+// response body will be silently ignored.
+func CheckResponse(r *http.Response) error {
+ if c := r.StatusCode; 200 <= c && c <= 299 {
+ return nil
+ }
+ errorResponse := &ErrorResponse{Response: r}
+ data, err := ioutil.ReadAll(r.Body)
+ if err == nil && data != nil {
+ json.Unmarshal(data, errorResponse)
+ }
+ return errorResponse
+}
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool {
+ p := new(bool)
+ *p = v
+ return p
+}
+
+// Int is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it, but unlike Int32
+// its argument value is an int.
+func Int(v int) *int {
+ p := new(int)
+ *p = v
+ return p
+}
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string {
+ p := new(string)
+ *p = v
+ return p
+}
+
+// AccessLevel is a helper routine that allocates a new AccessLevelValue
+// to store v and returns a pointer to it.
+func AccessLevel(v AccessLevelValue) *AccessLevelValue {
+ p := new(AccessLevelValue)
+ *p = v
+ return p
+}
+
+// VisibilityLevel is a helper routine that allocates a new VisibilityLevelValue
+// to store v and returns a pointer to it.
+func VisibilityLevel(v VisibilityLevelValue) *VisibilityLevelValue {
+ p := new(VisibilityLevelValue)
+ *p = v
+ return p
+}