diff options
Diffstat (limited to 'vendor/github.com/xanzy/go-gitlab/gitlab.go')
-rw-r--r-- | vendor/github.com/xanzy/go-gitlab/gitlab.go | 258 |
1 files changed, 180 insertions, 78 deletions
diff --git a/vendor/github.com/xanzy/go-gitlab/gitlab.go b/vendor/github.com/xanzy/go-gitlab/gitlab.go index 296e32c..35d65a4 100644 --- a/vendor/github.com/xanzy/go-gitlab/gitlab.go +++ b/vendor/github.com/xanzy/go-gitlab/gitlab.go @@ -24,6 +24,7 @@ import ( "io/ioutil" "net/http" "net/url" + "sort" "strconv" "strings" @@ -65,22 +66,66 @@ const ( OwnerPermission AccessLevelValue = 50 ) -// NotificationLevelValue represents a notification level within Gitlab. -// -// GitLab API docs: https://docs.gitlab.com/ce/api/ +// NotificationLevelValue represents a notification level. type NotificationLevelValue int -// List of available notification levels -// -// GitLab API docs: https://docs.gitlab.com/ce/api/ +// String implements the fmt.Stringer interface. +func (l NotificationLevelValue) String() string { + return notificationLevelNames[l] +} + +// MarshalJSON implements the json.Marshaler interface. +func (l NotificationLevelValue) MarshalJSON() ([]byte, error) { + return json.Marshal(l.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (l *NotificationLevelValue) UnmarshalJSON(data []byte) error { + var raw interface{} + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + + switch raw := raw.(type) { + case float64: + *l = NotificationLevelValue(raw) + case string: + *l = notificationLevelTypes[raw] + default: + return fmt.Errorf("json: cannot unmarshal %T into Go value of type %T", raw, *l) + } + + return nil +} + +// List of valid notification levels. const ( - DisabledNotifications NotificationLevelValue = iota - ParticipatingNotifications - WatchNotifications - GlobalNotifications - MentionNotifications + DisabledNotificationLevel NotificationLevelValue = iota + ParticipatingNotificationLevel + WatchNotificationLevel + GlobalNotificationLevel + MentionNotificationLevel + CustomNotificationLevel ) +var notificationLevelNames = [...]string{ + "disabled", + "participating", + "watch", + "global", + "mention", + "custom", +} + +var notificationLevelTypes = map[string]NotificationLevelValue{ + "disabled": DisabledNotificationLevel, + "participating": ParticipatingNotificationLevel, + "watch": WatchNotificationLevel, + "global": GlobalNotificationLevel, + "mention": MentionNotificationLevel, + "custom": CustomNotificationLevel, +} + // VisibilityLevelValue represents a visibility level within GitLab. // // GitLab API docs: https://docs.gitlab.com/ce/api/ @@ -115,30 +160,31 @@ type Client struct { 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 - TimeStats *TimeStatsService - Users *UsersService + Branches *BranchesService + BuildVariables *BuildVariablesService + Builds *BuildsService + Commits *CommitsService + DeployKeys *DeployKeysService + Groups *GroupsService + Issues *IssuesService + Labels *LabelsService + MergeRequests *MergeRequestsService + Milestones *MilestonesService + Namespaces *NamespacesService + Notes *NotesService + NotificationSettings *NotificationSettingsService + Projects *ProjectsService + ProjectSnippets *ProjectSnippetsService + Pipelines *PipelinesService + Repositories *RepositoriesService + RepositoryFiles *RepositoryFilesService + Services *ServicesService + Session *SessionService + Settings *SettingsService + SystemHooks *SystemHooksService + Tags *TagsService + TimeStats *TimeStatsService + Users *UsersService } // ListOptions specifies the optional parameters to various List methods that @@ -186,8 +232,9 @@ func newClient(httpClient *http.Client, tokenType tokenType, token string) *Clie 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.Notes = &NotesService{client: c} + c.NotificationSettings = &NotificationSettingsService{client: c} c.Projects = &ProjectsService{client: c} c.ProjectSnippets = &ProjectSnippetsService{client: c} c.Pipelines = &PipelinesService{client: c} @@ -228,7 +275,7 @@ func (c *Client) SetBaseURL(urlStr string) error { // 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) { +func (c *Client) NewRequest(method, path string, opt interface{}, options []OptionFunc) (*http.Request, error) { u := *c.baseURL // Set the encoded opaque data u.Opaque = c.baseURL.Path + path @@ -251,6 +298,12 @@ func (c *Client) NewRequest(method, path string, opt interface{}) (*http.Request Host: u.Host, } + for _, fn := range options { + if err := fn(req); err != nil { + return nil, err + } + } + if method == "POST" || method == "PUT" { bodyBytes, err := json.Marshal(opt) if err != nil { @@ -397,61 +450,102 @@ func parseID(id interface{}) (string, error) { // 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 + Response *http.Response + Message string } -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) +func (e *ErrorResponse) Error() string { + path, _ := url.QueryUnescape(e.Response.Request.URL.Opaque) + u := fmt.Sprintf("%s://%s%s", e.Response.Request.URL.Scheme, e.Response.Request.URL.Host, path) + return fmt.Sprintf("%s %s: %d %s", e.Response.Request.Method, u, e.Response.StatusCode, e.Message) } -// 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. +// CheckResponse checks the API response for errors, and returns them if present. func CheckResponse(r *http.Response) error { - if c := r.StatusCode; 200 <= c && c <= 299 { + switch r.StatusCode { + case 200, 201, 304: return nil } + errorResponse := &ErrorResponse{Response: r} data, err := ioutil.ReadAll(r.Body) if err == nil && data != nil { - json.Unmarshal(data, errorResponse) + var raw interface{} + if err := json.Unmarshal(data, &raw); err != nil { + errorResponse.Message = "failed to parse unknown error format" + } + + errorResponse.Message = parseError(raw) } + return errorResponse } +// Format: +// { +// "message": { +// "<property-name>": [ +// "<error-message>", +// "<error-message>", +// ... +// ], +// "<embed-entity>": { +// "<property-name>": [ +// "<error-message>", +// "<error-message>", +// ... +// ], +// } +// }, +// "error": "<error-message>" +// } +func parseError(raw interface{}) string { + switch raw := raw.(type) { + case string: + return raw + + case []interface{}: + var errs []string + for _, v := range raw { + errs = append(errs, parseError(v)) + } + return fmt.Sprintf("[%s]", strings.Join(errs, ", ")) + + case map[string]interface{}: + var errs []string + for k, v := range raw { + errs = append(errs, fmt.Sprintf("{%s: %s}", k, parseError(v))) + } + sort.Strings(errs) + return fmt.Sprintf("%s", strings.Join(errs, ", ")) + + default: + return fmt.Sprintf("failed to parse unexpected error type: %T", raw) + } +} + +// OptionFunc can be passed to all API requests to make the API call as if you were +// another user, provided your private token is from an administrator account. +// +// GitLab docs: https://docs.gitlab.com/ce/api/README.html#sudo +type OptionFunc func(*http.Request) error + +// WithSudo takes either a username or user ID and sets the SUDO request header +func WithSudo(uid interface{}) OptionFunc { + return func(req *http.Request) error { + switch uid := uid.(type) { + case int: + req.Header.Set("SUDO", strconv.Itoa(uid)) + return nil + case string: + req.Header.Set("SUDO", uid) + return nil + default: + return fmt.Errorf("uid must be either a username or user ID") + } + } +} + // 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 { @@ -485,6 +579,14 @@ func AccessLevel(v AccessLevelValue) *AccessLevelValue { return p } +// NotificationLevel is a helper routine that allocates a new NotificationLevelValue +// to store v and returns a pointer to it. +func NotificationLevel(v NotificationLevelValue) *NotificationLevelValue { + p := new(NotificationLevelValue) + *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 { |