func (c *Client) NewRequest(method, path string, opt interface{}, options []OptionFunc) (*http.Request, error) {
	u := *c.baseURL
	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,
	}
	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 {
			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
}
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.
package gitlab
import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"github.com/google/go-querystring/query"
)
const (
	libraryVersion = "0.2.0"
	defaultBaseURL = "https://gitlab.com/api/v4/"
	userAgent      = "go-gitlab/" + libraryVersion
)
type tokenType int
const (
	privateToken tokenType = iota
	oAuthToken
)
type AccessLevelValue int
const (
	GuestPermissions     AccessLevelValue = 10
	ReporterPermissions  AccessLevelValue = 20
	DeveloperPermissions AccessLevelValue = 30
	MasterPermissions    AccessLevelValue = 40
	OwnerPermission      AccessLevelValue = 50
)
type NotificationLevelValue int
func (l NotificationLevelValue) String() string {
	return notificationLevelNames[l]
}
func (l NotificationLevelValue) MarshalJSON() ([]byte, error) {
	return json.Marshal(l.String())
}
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
}
const (
	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,
}
type VisibilityValue string
const (
	PrivateVisibility  VisibilityValue = "private"
	InternalVisibility VisibilityValue = "internal"
	PublicVisibility   VisibilityValue = "public"
)
type Client struct {
	client *http.Client
	baseURL *url.URL
	tokenType tokenType
	token string
	UserAgent string
	Branches             *BranchesService
	BuildVariables       *BuildVariablesService
	Commits              *CommitsService
	DeployKeys           *DeployKeysService
	Environments         *EnvironmentsService
	Features             *FeaturesService
	Groups               *GroupsService
	GroupMembers         *GroupMembersService
	Issues               *IssuesService
	Jobs                 *JobsService
	Labels               *LabelsService
	MergeRequests        *MergeRequestsService
	Milestones           *MilestonesService
	Namespaces           *NamespacesService
	Notes                *NotesService
	NotificationSettings *NotificationSettingsService
	Projects             *ProjectsService
	ProjectMembers       *ProjectMembersService
	ProjectSnippets      *ProjectSnippetsService
	Pipelines            *PipelinesService
	PipelineTriggers     *PipelineTriggersService
	Repositories         *RepositoriesService
	RepositoryFiles      *RepositoryFilesService
	Services             *ServicesService
	Session              *SessionService
	Settings             *SettingsService
	SystemHooks          *SystemHooksService
	Tags                 *TagsService
	Todos                *TodosService
	Users                *UsersService
	Version              *VersionService
	Wikis                *WikisService
}
type ListOptions struct {
	Page int `url:"page,omitempty" json:"page,omitempty"`
	PerPage int `url:"per_page,omitempty" json:"per_page,omitempty"`
}
func NewClient(httpClient *http.Client, token string) *Client {
	return newClient(httpClient, privateToken, 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 {
		panic(err)
	}
	timeStats := &timeStatsService{client: c}
	c.Branches = &BranchesService{client: c}
	c.BuildVariables = &BuildVariablesService{client: c}
	c.Commits = &CommitsService{client: c}
	c.DeployKeys = &DeployKeysService{client: c}
	c.Environments = &EnvironmentsService{client: c}
	c.Features = &FeaturesService{client: c}
	c.Groups = &GroupsService{client: c}
	c.GroupMembers = &GroupMembersService{client: c}
	c.Issues = &IssuesService{client: c, timeStats: timeStats}
	c.Jobs = &JobsService{client: c}
	c.Labels = &LabelsService{client: c}
	c.MergeRequests = &MergeRequestsService{client: c, timeStats: timeStats}
	c.Milestones = &MilestonesService{client: c}
	c.Namespaces = &NamespacesService{client: c}
	c.Notes = &NotesService{client: c}
	c.NotificationSettings = &NotificationSettingsService{client: c}
	c.Projects = &ProjectsService{client: c}
	c.ProjectMembers = &ProjectMembersService{client: c}
	c.ProjectSnippets = &ProjectSnippetsService{client: c}
	c.Pipelines = &PipelinesService{client: c}
	c.PipelineTriggers = &PipelineTriggersService{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.Todos = &TodosService{client: c}
	c.Users = &UsersService{client: c}
	c.Version = &VersionService{client: c}
	c.Wikis = &WikisService{client: c}
	return c
}
func (c *Client) BaseURL() *url.URL {
	u := *c.baseURL
	return &u
}
func (c *Client) SetBaseURL(urlStr string) error {
	if !strings.HasSuffix(urlStr, "/") {
		urlStr += "/"
	}
	var err error
	c.baseURL, err = url.Parse(urlStr)
	return err
}