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.go258
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 {