Commit a5a8ecfd authored by Sander van Harmelen's avatar Sander van Harmelen

Merge pull request #1 from svanharmelen/dev

First release v0.1.0
parents bf270563 dc25ceb5
go-github CHANGELOG
===================
0.1.0
-----
- Initial release
# go-gitlab # go-gitlab
A GitLab API client enabling Go programs to interact with GitLab in a simple and uniform way A GitLab API client enabling Go programs to interact with GitLab in a simple and uniform way
**Documentation:** [![GoDoc](https://godoc.org/github.com/xanzy/go-gitlab?status.svg)](https://godoc.org/github.com/xanzy/go-gitlab)
**Build Status:** [![Build Status](https://travis-ci.org/xanzy/go-gitlab.svg?branch=master)](https://travis-ci.org/xanzy/go-gitlab)
## Coverage
This API client package covers **100%** of the existing GitLab API calls! So this
includes all calls to the following services:
- [x] Users
- [x] Session
- [x] Projects (including setting Webhooks)
- [x] Project Snippets
- [x] Services
- [x] Repositories
- [x] Repository Files
- [x] Commits
- [x] Branches
- [x] Merge Requests
- [x] Issues
- [x] Labels
- [x] Milestones
- [x] Notes (comments)
- [x] Deploy Keys
- [x] System Hooks
- [x] Groups
- [x] Namespaces
- [x] Settings
## Usage
```go
import "github.com/xanzy/go-gitlab"
```
Construct a new GitLab client, then use the various services on the client to
access different parts of the GitLab API. For example, to list all
users:
```go
git := gitlab.NewClient(nil, "yourtokengoeshere")
users, _, err := git.Users.ListUsers()
```
Some API methods have optional parameters that can be passed. For example,
to list all projects for user "svanharmelen":
```go
client := github.NewClient(nil)
opt := &ListProjectsOptions{Search: "svanharmelen"})
projects, _, err := client.Projects.ListProjects(opt)
```
### Examples
The [examples](https://github.com/xanzy/go-gitlab/tree/master/examples) directory
contains a couple for clear examples, of which one is partially listed here as well:
```go
package main
import (
"log"
"github.com/xanzy/go-gitlab"
)
func main() {
git := gitlab.NewClient(nil, "yourtokengoeshere")
// Create new project
p := &gitlab.CreateProjectOptions{
Name: "My Project",
Description: "Just a test project to play with",
MergeRequestsEnabled: true,
SnippetsEnabled: true,
VisibilityLevel: gitlab.PublicVisibility,
}
project, _, err := git.Projects.CreateProject(p)
if err != nil {
log.Fatal(err)
}
// Add a new snippet
s := &gitlab.CreateSnippetOptions{
Title: "Dummy Snippet",
FileName: "snippet.go",
Code: "package main....",
VisibilityLevel: gitlab.PublicVisibility,
}
_, _, err = git.ProjectSnippets.CreateSnippet(project.ID, s)
if err != nil {
log.Fatal(err)
}
}
```
For complete usage of go-gitlab, see the full [package docs](https://godoc.org/github.com/xanzy/go-gitlab).
## ToDo
- The biggest thing this package still needs is tests :disappointed:
## Issues
- If you have an issue: report it on the [issue tracker](https://github.com/xanzy/go-gitlab/issues)
## Author
Sander van Harmelen (<sander@xanzy.io>)
## License
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>
//
// 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 (
"fmt"
"net/url"
)
// BranchesService handles communication with the branch related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/branches.html
type BranchesService struct {
client *Client
}
// Branch represents a GitLab branch.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/branches.html
type Branch struct {
Commit *Commit `json:"commit"`
Name string `json:"name"`
Protected bool `json:"protected"`
}
func (b Branch) String() string {
return Stringify(b)
}
// ListBranches gets a list of repository branches from a project, sorted by
// name alphabetically.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#list-repository-branches
func (s *BranchesService) ListBranches(pid interface{}) ([]*Branch, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var b []*Branch
resp, err := s.client.Do(req, &b)
if err != nil {
return nil, resp, err
}
return b, resp, err
}
// GetBranch gets a single project repository branch.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#get-single-repository-branch
func (s *BranchesService) GetBranch(pid interface{}, branch string) (*Branch, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches/%s", url.QueryEscape(project), branch)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
b := new(Branch)
resp, err := s.client.Do(req, b)
if err != nil {
return nil, resp, err
}
return b, resp, err
}
// ProtectBranch protects a single project repository branch. This is an
// idempotent function, protecting an already protected repository branch
// still returns a 200 OK status code.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#protect-repository-branch
func (s *BranchesService) ProtectBranch(pid interface{}, branch string) (*Branch, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches/%s/protect", url.QueryEscape(project), branch)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, nil, err
}
b := new(Branch)
resp, err := s.client.Do(req, b)
if err != nil {
return nil, resp, err
}
return b, resp, err
}
// UnprotectBranch unprotects a single project repository branch. This is an
// idempotent function, unprotecting an already unprotected repository branch
// still returns a 200 OK status code.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#unprotect-repository-branch
func (s *BranchesService) UnprotectBranch(
pid interface{},
branch string) (*Branch, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches/%s/unprotect", url.QueryEscape(project), branch)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, nil, err
}
b := new(Branch)
resp, err := s.client.Do(req, b)
if err != nil {
return nil, resp, err
}
return b, resp, err
}
// CreateBranchOptions represents the available CreateBranch() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#create-repository-branch
type CreateBranchOptions struct {
BranchName string `url:"branch_name,omitempty"`
Ref string `url:"ref,omitempty"`
}
// CreateBranch creates branch from commit SHA or existing branch.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#create-repository-branch
func (s *BranchesService) CreateBranch(
pid interface{},
opt *CreateBranchOptions) (*Branch, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
b := new(Branch)
resp, err := s.client.Do(req, b)
if err != nil {
return nil, resp, err
}
return b, resp, err
}
// DeleteBranch deletes an existing branch.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/branches.html#delete-repository-branch
func (s *BranchesService) DeleteBranch(pid interface{}, branch string) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/repository/branches/%s", url.QueryEscape(project), branch)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
//
// 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 (
"fmt"
"net/url"
"time"
)
// CommitsService handles communication with the commit related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html
type CommitsService struct {
client *Client
}
// Commit represents a GitLab commit.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html
type Commit struct {
ID string `json:"id"`
ShortID string `json:"short_id"`
Title string `json:"title"`
AuthorName string `json:"author_name"`
AuthorEmail string `json:"author_email"`
AuthoredDate time.Time `json:"authored_date"`
CommittedDate time.Time `json:"committed_date"`
CommitterName string `json:"committer_name"`
CommitterEmail string `json:"committer_email"`
CreatedAt time.Time `json:"created_at"`
Message string `json:"message"`
ParentsIds []string `json:"parents_ids"`
}
func (c Commit) String() string {
return Stringify(c)
}
// ListCommitsOptions represents the available ListCommits() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html#list-commits
type ListCommitsOptions struct {
RefName string `url:"ref_name,omitempty"`
}
// ListCommits gets a list of repository commits in a project.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html#list-commits
func (s *CommitsService) ListCommits(
pid interface{},
opt *ListCommitsOptions) ([]*Commit, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/commits", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var c []*Commit
resp, err := s.client.Do(req, &c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
// GetCommit gets a specific commit identified by the commit hash or name of a
// branch or tag.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html#get-a-single-commit
func (s *CommitsService) GetCommit(
pid interface{},
sha string) (*Commit, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/commits/%s", url.QueryEscape(project), sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
c := new(Commit)
resp, err := s.client.Do(req, c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
// Diff represents a GitLab diff.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html
type Diff struct {
Diff string `json:"diff"`
NewPath string `json:"new_path"`
OldPath string `json:"old_path"`
AMode string `json:"a_mode"`
BMode string `json:"b_mode"`
NewFile bool `json:"new_file"`
RenamedFile bool `json:"renamed_file"`
DeletedFile bool `json:"deleted_file"`
}
func (d Diff) String() string {
return Stringify(d)
}
// GetCommitDiff gets the diff of a commit in a project..
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/commits.html#get-the-diff-of-a-commit
func (s *CommitsService) GetCommitDiff(
pid interface{},
sha string) ([]*Diff, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/commits/%s/diff", url.QueryEscape(project), sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var d []*Diff
resp, err := s.client.Do(req, &d)
if err != nil {
return nil, resp, err
}
return d, resp, err
}
// CommitComment represents a GitLab commit comment.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/commits.html
type CommitComment struct {
Note string `json:"note"`
Path string `json:"path"`
Line int `json:"line"`
LineType string `json:"line_type"`
Author struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
Blocked bool `json:"blocked"`
CreatedAt time.Time `json:"created_at"`
} `json:"author"`
}
func (c CommitComment) String() string {
return Stringify(c)
}
// GetCommitComments gets the comments of a commit in a project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/commits.html#get-the-comments-of-a-commit
func (s *CommitsService) GetCommitComments(
pid interface{},
sha string) ([]*CommitComment, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", url.QueryEscape(project), sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var c []*CommitComment
resp, err := s.client.Do(req, &c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
// PostCommitCommentOptions represents the available PostCommitComment()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/commits.html#post-comment-to-commit
type PostCommitCommentOptions struct {
Note string `url:"note,omitempty"`
Path string `url:"path"`
Line int `url:"line"`
LineType string `url:"line_type"`
}
// PostCommitComment adds a comment to a commit. Optionally you can post
// comments on a specific line of a commit. Therefor both path, line_new and
// line_old are required.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/commits.html#post-comment-to-commit
func (s *CommitsService) PostCommitComment(
pid interface{},
sha string,
opt *PostCommitCommentOptions) (*CommitComment, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/commits/%s/comments", url.QueryEscape(project), sha)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
c := new(CommitComment)
resp, err := s.client.Do(req, c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
//
// 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 (
"fmt"
"net/url"
"time"
)
// DeployKeysService handles communication with the keys related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/deploy_keys.html
type DeployKeysService struct {
client *Client
}
// DeployKey represents a GitLab deploy key.
type DeployKey struct {
ID int `json:"id"`
Title string `json:"title"`
Key string `json:"key"`
CreatedAt time.Time `json:"created_at"`
}
func (k DeployKey) String() string {
return Stringify(k)
}
// ListDeployKeys gets a list of a project's deploy keys
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/deploy_keys.html#list-deploy-keys
func (s *DeployKeysService) ListDeployKeys(pid interface{}) ([]*DeployKey, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/keys", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var k []*DeployKey
resp, err := s.client.Do(req, &k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// GetDeployKey gets a single deploy key.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/deploy_keys.html#single-deploy-key
func (s *DeployKeysService) GetDeployKey(
pid interface{},
deployKey int) (*DeployKey, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/keys/%d", url.QueryEscape(project), deployKey)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
k := new(DeployKey)
resp, err := s.client.Do(req, k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// AddDeployKeyOptions represents the available ADDDeployKey() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/deploy_keys.html#add-deploy-key
type AddDeployKeyOptions struct {
Title string `url:"title,omitempty"`
Key string `url:"key,omitempty"`
}
// AddDeployKey creates a new deploy key for a project. If deploy key already
// exists in another project - it will be joined to project but only if
// original one was is accessible by same user.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/deploy_keys.html#add-deploy-key
func (s *DeployKeysService) AddDeployKey(
pid interface{},
opt *AddDeployKeyOptions) (*DeployKey, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/keys", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
k := new(DeployKey)
resp, err := s.client.Do(req, k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// DeleteDeployKey deletes a deploy key from a project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/deploy_keys.html#delete-deploy-key
func (s *DeployKeysService) DeleteDeployKey(pid interface{}, deployKey int) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/keys/%d", url.QueryEscape(project), deployKey)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
package main
import (
"log"
"github.com/xanzy/go-gitlab"
)
func main() {
git := gitlab.NewClient(nil, "yourtokengoeshere")
// Create new label
l := &gitlab.CreateLabelOptions{
Name: "My Label",
Color: "#11FF22",
}
label, _, err := git.Labels.CreateLabel("myname/myproject", l)
if err != nil {
log.Fatal(err)
}
log.Printf("Created label: %s\nWith color: %s\n", label.Name, label.Color)
// List all labels
labels, _, err := git.Labels.ListLabels("myname/myproject")
if err != nil {
log.Fatal(err)
}
for _, label := range labels {
log.Printf("Found label: %s", label.Name)
}
}
package main
import (
"log"
"github.com/xanzy/go-gitlab"
)
func main() {
git := gitlab.NewClient(nil, "yourtokengoeshere")
// Create new project
p := &gitlab.CreateProjectOptions{
Name: "My Project",
Description: "Just a test project to play with",
MergeRequestsEnabled: true,
SnippetsEnabled: true,
VisibilityLevel: gitlab.PublicVisibility,
}
project, _, err := git.Projects.CreateProject(p)
if err != nil {
log.Fatal(err)
}
// Add a new snippet
s := &gitlab.CreateSnippetOptions{
Title: "Dummy Snippet",
FileName: "snippet.go",
Code: "package main....",
VisibilityLevel: gitlab.PublicVisibility,
}
_, _, err = git.ProjectSnippets.CreateSnippet(project.ID, s)
if err != nil {
log.Fatal(err)
}
// List all project snippets
snippets, _, err := git.ProjectSnippets.ListSnippits(project.PathWithNamespace)
if err != nil {
log.Fatal(err)
}
for _, snippet := range snippets {
log.Printf("Found snippet: %s", snippet.Title)
}
}
package main
import (
"encoding/base64"
"log"
"github.com/xanzy/go-gitlab"
)
func main() {
git := gitlab.NewClient(nil, "yourtokengoeshere")
// Create a new repository file
cf := &gitlab.CreateFileOptions{
FilePath: "file.go",
BranchName: "master",
Encoding: "text",
Content: "My file contenxst",
CommitMessage: "Adding a test file",
}
file, _, err := git.RepositoryFiles.CreateFile("myname/myproject", cf)
if err != nil {
log.Fatal(err)
}
// Update a repository file
uf := &gitlab.UpdateFileOptions{
FilePath: file.FilePath,
BranchName: "master",
Encoding: "text",
Content: "My file content",
CommitMessage: "Fixing typo",
}
_, _, err = git.RepositoryFiles.UpdateFile("myname/myproject", uf)
if err != nil {
log.Fatal(err)
}
gf := &gitlab.GetFileOptions{
FilePath: file.FilePath,
Ref: "master",
}
f, _, err := git.RepositoryFiles.GetFile("myname/myproject", gf)
if err != nil {
log.Fatal(err)
}
if f.Encoding == "base64" {
content, err := base64.StdEncoding.DecodeString(f.Content)
if err != nil {
log.Fatal(err)
}
log.Printf("File contains: %s", string(content))
} else {
log.Printf("File contains: %s", f.Content)
}
}
//
// 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 (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/google/go-querystring/query"
)
const (
libraryVersion = "0.1"
defaultBaseURL = "https://gitlab.com/api/v3/"
userAgent = "go-gitlab/" + libraryVersion
)
// AccessLevel represents a premission level within GitLab.
//
// GitLab API docs: http://doc.gitlab.com/ce/permissions/permissions.html
type AccessLevel int
// List of available access levels
//
// GitLab API docs: http://doc.gitlab.com/ce/permissions/permissions.html
const (
GuestPermissions AccessLevel = 10
ReporterPermissions AccessLevel = 20
DeveloperPermissions AccessLevel = 30
MasterPermissions AccessLevel = 40
OwnerPermission AccessLevel = 50
)
// VisibilityLevel represents a visibility level within GitLab.
//
// GitLab API docs: http://doc.gitlab.com/ce/...?
type VisibilityLevel int
// List of available visibility levels
//
// GitLab API docs: http://doc.gitlab.com/ce/...?
const (
PrivateVisibility VisibilityLevel = 0
InternalVisibility VisibilityLevel = 10
PublicVisibility VisibilityLevel = 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
// Private 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
Commits *CommitsService
DeployKeys *DeployKeysService
Groups *GroupsService
Issues *IssuesService
Labels *LabelsService
MergeRequests *MergeRequestsService
Milestones *MilestonesService
Namespaces *NamespacesService
Notes *NotesService
Projects *ProjectsService
ProjectSnippets *ProjectSnippetsService
Repositories *RepositoriesService
RepositoryFiles *RepositoryFilesService
Services *ServicesService
Session *SessionService
Settings *SettingsService
SystemHooks *SystemHooksService
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"`
// For paginated result sets, the number of results to include per page.
PerPage int `url:"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 {
if httpClient == nil {
httpClient = http.DefaultClient
}
c := &Client{client: httpClient, token: token, UserAgent: userAgent}
c.SetBaseURL(defaultBaseURL)
c.Branches = &BranchesService{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.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.Users = &UsersService{client: c}
return c
}
// 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)
if err != nil {
return err
}
// Set the encoded opaque data
c.baseURL.Opaque = fmt.Sprintf("//%s%s", c.baseURL.Host, c.baseURL.Path)
return 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.
func (c *Client) NewRequest(method, path string, opt interface{}) (*http.Request, error) {
u := *c.baseURL
u.Opaque += path
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,
}
req.Header.Set("Accept", "application/json")
req.Header.Set("PRIVATE-TOKEN", 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 {
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 "", errors.New("the ID must be an int or a string")
}
}
// An ErrorResponse reports one or more errors caused by an API request.
//
// GitLab API docs:
// http://doc.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 {
return fmt.Sprintf("%v %v: %d %v %+v",
r.Response.Request.Method, r.Response.Request.URL,
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:
// http://doc.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
}
// parseBoolResponse determines the boolean result from a GitLab API response.
// Several GitLab API methods return boolean responses indicated by the HTTP
// status code in the response (true indicated by a 204, false indicated by a
// 404). This helper function will determine that result and hide the 404 error
// if present. Any other error will be returned through as-is.
func parseBoolResponse(err error) (bool, error) {
if err == nil {
return true, nil
}
if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound {
// Simply false. In this one case, we do not pass the error through.
return false, nil
}
// some other real error occurred
return false, err
}
// cloneRequest returns a clone of the provided *http.Request. The clone is a
// shallow copy of the struct and its Header map.
func cloneRequest(r *http.Request) *http.Request {
// shallow copy of the struct
r2 := new(http.Request)
*r2 = *r
// deep copy of the Header
r2.Header = make(http.Header)
for k, s := range r.Header {
r2.Header[k] = s
}
return r2
}
// 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
}
//
// 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 (
"fmt"
"time"
)
// GroupsService handles communication with the group related methods of
// the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html
type GroupsService struct {
client *Client
}
// Group represents a GitLab group.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html
type Group struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Description string `json:"description"`
}
// ListGroups gets a list of groups. (As user: my groups, as admin: all groups)
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#list-project-groups
func (s *GroupsService) ListGroups() ([]*Group, *Response, error) {
req, err := s.client.NewRequest("GET", "groups", nil)
if err != nil {
return nil, nil, err
}
var g []*Group
resp, err := s.client.Do(req, &g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// GetGroup gets all details of a group.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html#details-of-a-group
func (s *GroupsService) GetGroup(gid interface{}) (*Group, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("groups/%s", group)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
g := new(Group)
resp, err := s.client.Do(req, g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// CreateGroupOptions represents the available CreateGroup() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html#new-group
type CreateGroupOptions struct {
Name string `url:"name,omitempty"`
Path string `url:"path,omitempty"`
Description string `url:"description,omitempty"`
}
// CreateGroup creates a new project group. Available only for users who can
// create groups.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html#new-group
func (s *GroupsService) CreateGroup(opt *CreateGroupOptions) (*Group, *Response, error) {
req, err := s.client.NewRequest("POST", "groups", opt)
if err != nil {
return nil, nil, err
}
g := new(Group)
resp, err := s.client.Do(req, g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// TransferGroup transfers a project to the Group namespace. Available only
// for admin.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#transfer-project-to-group
func (s *GroupsService) TransferGroup(gid interface{}, project int) (*Group, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("groups/%s/projects/%d", group, project)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
g := new(Group)
resp, err := s.client.Do(req, g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// DeleteGroup removes group with all projects inside.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html#remove-group
func (s *GroupsService) DeleteGroup(gid interface{}) (*Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("groups/%s", group)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// SearchGroup get all groups that match your string in their name or path.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html#search-for-group
func (s *GroupsService) SearchGroup(query string) ([]*Group, *Response, error) {
var q struct {
Search string `url:"search,omitempty"`
}
q.Search = query
req, err := s.client.NewRequest("GET", "groups", &q)
if err != nil {
return nil, nil, err
}
var g []*Group
resp, err := s.client.Do(req, &g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// GroupMember represents a GitLab group member.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html
type GroupMember struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
AccessLevel int `json:"access_level"`
}
// ListGroupMembers get a list of group members viewable by the authenticated
// user.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#list-group-members
func (s *GroupsService) ListGroupMembers(gid interface{}) ([]*GroupMember, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("groups/%s/members", group)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var g []*GroupMember
resp, err := s.client.Do(req, &g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// AddGroupMemberOptions represents the available AddGroupMember() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/groups.html#add-group-member
type AddGroupMemberOptions struct {
UserID int `url:"user_id,omitempty"`
AccessLevel AccessLevel `url:"access_level,omitempty"`
}
// AddGroupMember adds a user to the list of group members.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#list-group-members
func (s *GroupsService) AddGroupMember(
gid interface{},
opt *AddGroupMemberOptions) (*GroupMember, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("groups/%s/members", group)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
g := new(GroupMember)
resp, err := s.client.Do(req, g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// UpdateGroupMemberOptions represents the available UpdateGroupMember()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#edit-group-team-member
type UpdateGroupMemberOptions struct {
AccessLevel AccessLevel `url:"access_level,omitempty"`
}
// UpdateGroupMember updates a group team member to a specified access level.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#list-group-members
func (s *GroupsService) UpdateGroupMember(
gid interface{},
user int,
opt *UpdateGroupMemberOptions) (*GroupMember, *Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("groups/%s/members/%d", group, user)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
g := new(GroupMember)
resp, err := s.client.Do(req, g)
if err != nil {
return nil, resp, err
}
return g, resp, err
}
// RemoveGroupMember removes user from user team.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/groups.html#remove-user-from-user-team
func (s *GroupsService) RemoveGroupMember(gid interface{}, user int) (*Response, error) {
group, err := parseID(gid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("groups/%s/members/%d", group, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
//
// 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 (
"fmt"
"log"
"net/url"
"strings"
"time"
)
// IssuesService handles communication with the issue related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html
type IssuesService struct {
client *Client
}
// Issue represents a GitLab issue.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html
type Issue struct {
ID int `json:"id"`
IID int `json:"iid"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
Labels []string `json:"labels"`
Milestone struct {
ID int `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
DueDate string `json:"due_date"`
State string `json:"state"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
} `json:"milestone"`
Assignee struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
} `json:"assignee"`
Author struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
} `json:"author"`
State string `json:"state"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}
func (i Issue) String() string {
return Stringify(i)
}
// ListIssuesOptions represents the available ListIssues() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#list-issues
type ListIssuesOptions struct {
State string `url:"state,omitempty"`
Labels []string `url:"labels,omitempty"`
OrderBy string `url:"order_by,omitempty"`
Sort string `url:"sort,omitempty"`
}
// ListIssues gets all issues created by authenticated user. This function
// takes pagination parameters page and per_page to restrict the list of issues.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#list-issues
func (s *IssuesService) ListIssues(opt *ListIssuesOptions) ([]*Issue, *Response, error) {
req, err := s.client.NewRequest("GET", "issues", opt)
if err != nil {
return nil, nil, err
}
var i []*Issue
resp, err := s.client.Do(req, &i)
if err != nil {
return nil, resp, err
}
return i, resp, err
}
// ListProjectIssuesOptions represents the available ListProjectIssues() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#list-issues
type ListProjectIssuesOptions struct {
IID int `url:"iid,omitempty"`
State string `url:"state,omitempty"`
Labels []string `url:"labels,omitempty"`
Milestone string `url:"milestone,omitempty"`
OrderBy string `url:"order_by,omitempty"`
Sort string `url:"sort,omitempty"`
}
// ListProjectIssues gets all issues created by authenticated user. This function
// takes pagination parameters page and per_page to restrict the list of issues.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#list-issues
func (s *IssuesService) ListProjectIssues(
pid interface{},
opt *ListProjectIssuesOptions) ([]*Issue, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var i []*Issue
resp, err := s.client.Do(req, &i)
if err != nil {
return nil, resp, err
}
return i, resp, err
}
// GetIssue gets a single project issue.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#single-issues
func (s *IssuesService) GetIssue(pid interface{}, issue int) (*Issue, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues/%d", url.QueryEscape(project), issue)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
i := new(Issue)
resp, err := s.client.Do(req, i)
if err != nil {
return nil, resp, err
}
return i, resp, err
}
// CreateIssueOptions represents the available CreateIssue() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#new-issues
type CreateIssueOptions struct {
Title string `url:"title,omitempty"`
Description string `url:"description,omitempty"`
AssigneeID int `url:"assignee_id,omitempty"`
MilestoneID int `url:"milestone_id,omitempty"`
Labels []string `url:"labels,omitempty"`
}
// CreateIssue creates a new project issue.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#new-issues
func (s *IssuesService) CreateIssue(
pid interface{},
opt *CreateIssueOptions) (*Issue, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues", url.QueryEscape(project))
// This is needed to get a single, comma separated string
opt.Labels = []string{strings.Join(opt.Labels, ",")}
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
log.Printf("req: %#+v\n", req.URL)
i := new(Issue)
resp, err := s.client.Do(req, i)
if err != nil {
return nil, resp, err
}
return i, resp, err
}
// UpdateIssueOptions represents the available UpdateIssue() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#edit-issues
type UpdateIssueOptions struct {
Title string `url:"title,omitempty"`
Description string `url:"description,omitempty"`
AssigneeID int `url:"assignee_id,omitempty"`
MilestoneID int `url:"milestone_id,omitempty"`
Labels []string `url:"labels,omitempty"`
StateEvent string `url:"state_event,omitempty"`
}
// UpdateIssue updates an existing project issue. This function is also used
// to mark an issue as closed.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/issues.html#edit-issues
func (s *IssuesService) UpdateIssue(
pid interface{},
issue int,
opt *UpdateIssueOptions) (*Issue, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues/%d", url.QueryEscape(project), issue)
// This is needed to get a single, comma separated string
opt.Labels = []string{strings.Join(opt.Labels, ",")}
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
i := new(Issue)
resp, err := s.client.Do(req, i)
if err != nil {
return nil, resp, err
}
return i, resp, err
}
//
// 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 (
"fmt"
"net/url"
)
// LabelsService handles communication with the label related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html
type LabelsService struct {
client *Client
}
// Label represents a GitLab label.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html
type Label struct {
Name string `json:"name"`
Color string `json:"color"`
}
func (l Label) String() string {
return Stringify(l)
}
// ListLabels gets all labels for given project.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#list-labels
func (s *LabelsService) ListLabels(pid interface{}) ([]*Label, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var l []*Label
resp, err := s.client.Do(req, &l)
if err != nil {
return nil, resp, err
}
return l, resp, err
}
// CreateLabelOptions represents the available CreateLabel() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#create-a-new-label
type CreateLabelOptions struct {
Name string `url:"name,omitempty"`
Color string `url:"color,omitempty"`
}
// CreateLabel creates a new label for given repository with given name and
// color.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#create-a-new-label
func (s *LabelsService) CreateLabel(
pid interface{},
opt *CreateLabelOptions) (*Label, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
l := new(Label)
resp, err := s.client.Do(req, l)
if err != nil {
return nil, resp, err
}
return l, resp, err
}
// DeleteLabelOptions represents the available DeleteLabel() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#delete-a-label
type DeleteLabelOptions struct {
Name string `url:"name,omitempty"`
}
// DeleteLabel deletes a label given by its name.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#delete-a-label
func (s *LabelsService) DeleteLabel(pid interface{}, opt *DeleteLabelOptions) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project))
req, err := s.client.NewRequest("DELETE", u, opt)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// UpdateLabelOptions represents the available UpdateLabel() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#delete-a-label
type UpdateLabelOptions struct {
Name string `url:"name,omitempty"`
NewName string `url:"new_name,omitempty"`
Color string `url:"color,omitempty"`
}
// UpdateLabel updates an existing label with new name or now color. At least
// one parameter is required, to update the label.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/labels.html#edit-an-existing-label
func (s *LabelsService) UpdateLabel(
pid interface{},
opt *UpdateLabelOptions) (*Label, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/labels", url.QueryEscape(project))
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
l := new(Label)
resp, err := s.client.Do(req, l)
if err != nil {
return nil, resp, err
}
return l, resp, err
}
//
// 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 (
"fmt"
"net/url"
"time"
)
// MergeRequestsService handles communication with the merge requests related
// methods of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/merge_requests.html
type MergeRequestsService struct {
client *Client
}
// MergeRequest represents a GitLab merge request.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/merge_requests.html
type MergeRequest struct {
ID int `json:"id"`
IID int `json:"iid"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
WorkInProgress bool `json:"work_in_progress"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
TargetBranch string `json:"target_branch"`
SourceBranch string `json:"source_branch"`
Upvotes int `json:"upvotes"`
Downvotes int `json:"downvotes"`
Author struct {
Name string `json:"name"`
Username string `json:"username"`
ID int `json:"id"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
} `json:"author"`
Assignee struct {
Name string `json:"name"`
Username string `json:"username"`
ID int `json:"id"`
State string `json:"state"`
AvatarURL string `json:"avatar_url"`
} `json:"assignee"`
SourceProjectID int `json:"source_project_id"`
TargetProjectID int `json:"target_project_id"`
Labels []string `json:"labels"`
Milestone struct {
ID int `json:"id"`
Iid int `json:"iid"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DueDate string `json:"due_date"`
} `json:"milestone"`
Files []struct {
OldPath string `json:"old_path"`
NewPath string `json:"new_path"`
AMode string `json:"a_mode"`
BMode string `json:"b_mode"`
Diff string `json:"diff"`
NewFile bool `json:"new_file"`
RenamedFile bool `json:"renamed_file"`
DeletedFile bool `json:"deleted_file"`
} `json:"files"`
}
func (m MergeRequest) String() string {
return Stringify(m)
}
// ListMergeRequestsOptions represents the available ListMergeRequests()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#list-merge-requests
type ListMergeRequestsOptions struct {
IID int `url:"iid,omitempty"`
State string `url:"state,omitempty"`
OrderBy string `url:"order_by,omitempty"`
Sort string `url:"sort,omitempty"`
}
// ListMergeRequests gets all merge requests for this project. The state
// parameter can be used to get only merge requests with a given state (opened,
// closed, or merged) or all of them (all). The pagination parameters page and
// per_page can be used to restrict the list of merge requests.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#list-merge-requests
func (s *MergeRequestsService) ListMergeRequests(
pid interface{},
opt *ListMergeRequestsOptions) ([]*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_requests", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var m []*MergeRequest
resp, err := s.client.Do(req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// GetMergeRequest shows information about a single merge request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#get-single-mr
func (s *MergeRequestsService) GetMergeRequest(
pid interface{},
mergeRequest int) (*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_request/%d", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
m := new(MergeRequest)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// GetMergeRequestChanges shows information about the merge request including
// its files and changes.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#get-single-mr-changes
func (s *MergeRequestsService) GetMergeRequestChanges(
pid interface{},
mergeRequest int) (*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_request/%d/changes", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
m := new(MergeRequest)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// CreateMergeRequestOptions represents the available CreateMergeRequest()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#create-mr
type CreateMergeRequestOptions struct {
Title string `url:"title,omitempty"`
Description string `url:"description,omitempty"`
SourceBranch string `url:"source_branch,omitemtpy"`
TargetBranch string `url:"target_branch,omitemtpy"`
AssigneeID int `url:"assignee_id,omitempty"`
TargetProjectID int `url:"target_project_id,omitempty"`
}
// CreateMergeRequest creates a new merge request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#create-mr
func (s *MergeRequestsService) CreateMergeRequest(
pid interface{},
opt *CreateMergeRequestOptions) (*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_requests", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
m := new(MergeRequest)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// UpdateMergeRequestOptions represents the available UpdateMergeRequest()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#update-mr
type UpdateMergeRequestOptions struct {
Title string `url:"title,omitempty"`
Description string `url:"description,omitempty"`
TargetBranch string `url:"target_branch,omitemtpy"`
AssigneeID int `url:"assignee_id,omitempty"`
StateEvent string `url:"state_event,omitempty"`
}
// UpdateMergeRequest updates an existing project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#update-mr
func (s *MergeRequestsService) UpdateMergeRequest(
pid interface{},
mergeRequest int,
opt *UpdateMergeRequestOptions) (*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_request/%d", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
m := new(MergeRequest)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// AcceptMergeRequest merges changes submitted with MR using this API. If merge
// success you get 200 OK. If it has some conflicts and can not be merged - you
// get 405 and error message 'Branch cannot be merged'. If merge request is
// already merged or closed - you get 405 and error message 'Method Not Allowed'
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#accept-mr
func (s *MergeRequestsService) AcceptMergeRequest(
pid interface{},
mergeRequest int) (*MergeRequest, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_request/%d/merge", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, nil, err
}
m := new(MergeRequest)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// MergeRequestComment represents a GitLab merge request comment.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/merge_requests.html
type MergeRequestComment struct {
Note string `json:"note"`
Author struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
} `json:"author"`
}
func (m MergeRequestComment) String() string {
return Stringify(m)
}
// GetMergeRequestComments gets all the comments associated with a merge
// request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/merge_requests.html#get-the-comments-on-a-mr
func (s *MergeRequestsService) GetMergeRequestComments(
pid interface{},
mergeRequest int) ([]*MergeRequestComment, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_request/%d/comments", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var c []*MergeRequestComment
resp, err := s.client.Do(req, &c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
// PostMergeRequestCommentOptions represents the available
// PostMergeRequestComment() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/commits.html#post-comment-to-mr
type PostMergeRequestCommentOptions struct {
Note string `url:"note,omitempty"`
}
// PostMergeRequestComment dds a comment to a merge request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/commits.html#post-comment-to-mr
func (s *MergeRequestsService) PostMergeRequestComment(
pid interface{},
mergeRequest int,
opt *PostMergeRequestCommentOptions) (*MergeRequestComment, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_request/%d/comments", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
c := new(MergeRequestComment)
resp, err := s.client.Do(req, c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
//
// 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 (
"fmt"
"net/url"
"time"
)
// MilestonesService handles communication with the milestone related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/milestones.html
type MilestonesService struct {
client *Client
}
// Milestone represents a GitLab milestone.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/branches.html
type Milestone struct {
ID int `json:"id"`
Iid int `json:"iid"`
ProjectID int `json:"project_id"`
Title string `json:"title"`
Description string `json:"description"`
DueDate string `json:"due_date"`
State string `json:"state"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}
func (m Milestone) String() string {
return Stringify(m)
}
// ListMilestonesOptions represents the available ListMilestones() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#list-project-milestones
type ListMilestonesOptions struct {
IID int `url:"iid,omitempty"`
}
// ListMilestones returns a list of project milestones.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#list-project-milestones
func (s *MilestonesService) ListMilestones(
pid interface{},
opt *ListMilestonesOptions) ([]*Milestone, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var m []*Milestone
resp, err := s.client.Do(req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// GetMilestone gets a single project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-single-milestone
func (s *MilestonesService) GetMilestone(
pid interface{},
milestone int) (*Milestone, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// CreateMilestoneOptions represents the available CreateMilestone() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#create-new-milestone
type CreateMilestoneOptions struct {
Title string `url:"title,omitempty"`
Description string `url:"description,omitempty"`
DueDate string `url:"due_date,omitempty"`
}
// CreateMilestone creates a new project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#create-new-milestone
func (s *MilestonesService) CreateMilestone(
pid interface{},
opt *CreateMilestoneOptions) (*Milestone, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// UpdateMilestoneOptions represents the available UpdateMilestone() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#edit-milestone
type UpdateMilestoneOptions struct {
Title string `url:"title,omitempty"`
Description string `url:"description,omitempty"`
DueDate string `url:"due_date,omitempty"`
StateEvent string `url:"state_event,omitempty"`
}
// UpdateMilestone updates an existing project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#edit-milestone
func (s *MilestonesService) UpdateMilestone(
pid interface{},
milestone int,
opt *UpdateMilestoneOptions) (*Milestone, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(req, m)
if err != nil {
return nil, resp, err
}
return m, resp, err
}
// GetMilestoneIssues gets all issues assigned to a single project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
func (s *MilestonesService) GetMilestoneIssues(
pid interface{},
milestone int) ([]*Issue, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/milestones/%d/issues", url.QueryEscape(project), milestone)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var i []*Issue
resp, err := s.client.Do(req, &i)
if err != nil {
return nil, resp, err
}
return i, resp, err
}
//
// 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
// NamespacesService handles communication with the namespace related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/namespaces.html
type NamespacesService struct {
client *Client
}
// Namespace represents a GitLab namespace.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/namespaces.html
type Namespace struct {
ID int `json:"id"`
Path string `json:"path"`
Kind string `json:"kind"`
}
func (n Namespace) String() string {
return Stringify(n)
}
// ListNamespaces gets a list of projects accessible by the authenticated user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/namespaces.html#list-namespaces
func (s *NamespacesService) ListNamespaces() ([]*Namespace, *Response, error) {
req, err := s.client.NewRequest("GET", "namespaces", nil)
if err != nil {
return nil, nil, err
}
var n []*Namespace
resp, err := s.client.Do(req, &n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// SearchNamespace gets all namespaces that match your string in their name
// or path.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/namespaces.html#search-for-namespace
func (s *NamespacesService) SearchNamespace(query string) ([]*Namespace, *Response, error) {
var q struct {
Search string `url:"search,omitempty"`
}
q.Search = query
req, err := s.client.NewRequest("GET", "namespaces", &q)
if err != nil {
return nil, nil, err
}
var n []*Namespace
resp, err := s.client.Do(req, &n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
//
// 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 (
"fmt"
"net/url"
"time"
)
// NotesService handles communication with the notes related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/notes.html
type NotesService struct {
client *Client
}
// Note represents a GitLab note.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/notes.html
type Note struct {
ID int `json:"id"`
Body string `json:"body"`
Attachment string `json:"attachment"`
Title string `json:"title"`
FileName string `json:"file_name"`
Author struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
} `json:"author"`
ExpiresAt *time.Time `json:"expires_at"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}
func (n Note) String() string {
return Stringify(n)
}
// ListIssueNotes gets a list of all notes for a single issue.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#list-project-issue-notes
func (s *NotesService) ListIssueNotes(pid interface{}, issue int) ([]*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues/%d/notes", url.QueryEscape(project), issue)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var n []*Note
resp, err := s.client.Do(req, &n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// GetIssueNote returns a single note for a specific project issue.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#get-single-issue-note
func (s *NotesService) GetIssueNote(
pid interface{},
issue int,
note int) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// CreateIssueNoteOptions represents the available CreateIssueNote()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#create-new-issue-note
type CreateIssueNoteOptions struct {
Body string `url:"body,omitempty"`
}
// CreateIssueNote creates a new note to a single project issue.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#create-new-issue-note
func (s *NotesService) CreateIssueNote(
pid interface{},
issue int,
opt *CreateIssueNoteOptions) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues/%d/notes", url.QueryEscape(project), issue)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// UpdateIssueNoteOptions represents the available UpdateIssueNote()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#modify-existing-issue-note
type UpdateIssueNoteOptions struct {
Body string `url:"body,omitempty"`
}
// UpdateIssueNote modifies existing note of an issue.
//
// http://doc.gitlab.com/ce/api/notes.html#modify-existing-issue-note
func (s *NotesService) UpdateIssueNote(
pid interface{},
issue int,
note int,
opt *UpdateIssueNoteOptions) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/issues/%d/notes/%d", url.QueryEscape(project), issue, note)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// ListSnippetNotes gets a list of all notes for a single snippet. Snippet
// notes are comments users can post to a snippet.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#list-all-snippet-notes
func (s *NotesService) ListSnippetNotes(pid interface{}, snippet int) ([]*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d/notes", url.QueryEscape(project), snippet)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var n []*Note
resp, err := s.client.Do(req, &n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// GetSnippetNote returns a single note for a given snippet.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#get-single-snippet-note
func (s *NotesService) GetSnippetNote(
pid interface{},
snippet int,
note int) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// CreateSnippetNoteOptions represents the available CreateSnippetNote()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#create-new-snippet-note
type CreateSnippetNoteOptions struct {
Body string `url:"body,omitempty"`
}
// CreateSnippetNote creates a new note for a single snippet. Snippet notes are
// comments users can post to a snippet.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#create-new-snippet-note
func (s *NotesService) CreateSnippetNote(
pid interface{},
snippet int,
opt *CreateSnippetNoteOptions) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d/notes", url.QueryEscape(project), snippet)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// UpdateSnippetNoteOptions represents the available UpdateSnippetNote()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
type UpdateSnippetNoteOptions struct {
Body string `url:"body,omitempty"`
}
// UpdateSnippetNote modifies existing note of a snippet.
//
// http://doc.gitlab.com/ce/api/notes.html#modify-existing-snippet-note
func (s *NotesService) UpdateSnippetNote(
pid interface{},
snippet int,
note int,
opt *UpdateSnippetNoteOptions) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d/notes/%d", url.QueryEscape(project), snippet, note)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// ListMergeRequestNotes gets a list of all notes for a single merge request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#list-all-merge-request-notes
func (s *NotesService) ListMergeRequestNotes(
pid interface{},
mergeRequest int) ([]*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var n []*Note
resp, err := s.client.Do(req, &n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// GetMergeRequestNote returns a single note for a given merge request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#get-single-merge-request-note
func (s *NotesService) GetMergeRequestNote(
pid interface{},
mergeRequest int,
note int) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// CreateMergeRequestNoteOptions represents the available
// CreateMergeRequestNote() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#create-new-merge-request-note
type CreateMergeRequestNoteOptions struct {
Body string `url:"body,omitempty"`
}
// CreateMergeRequestNote creates a new note for a single merge request.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#create-new-merge-request-note
func (s *NotesService) CreateMergeRequestNote(
pid interface{},
mergeRequest int,
opt *CreateMergeRequestNoteOptions) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/merge_requests/%d/notes", url.QueryEscape(project), mergeRequest)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
// UpdateMergeRequestNoteOptions represents the available
// UpdateMergeRequestNote() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
type UpdateMergeRequestNoteOptions struct {
Body string `url:"body,omitempty"`
}
// UpdateMergeRequestNote modifies existing note of a merge request.
//
// http://doc.gitlab.com/ce/api/notes.html#modify-existing-merge-request-note
func (s *NotesService) UpdateMergeRequestNote(
pid interface{},
mergeRequest int,
note int,
opt *UpdateMergeRequestNoteOptions) (*Note, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf(
"projects/%s/merge_requests/%d/notes/%d", url.QueryEscape(project), mergeRequest, note)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
n := new(Note)
resp, err := s.client.Do(req, n)
if err != nil {
return nil, resp, err
}
return n, resp, err
}
//
// 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"
"fmt"
"net/url"
"time"
)
// ProjectSnippetsService handles communication with the project snippets
// related methods of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/project_snippets.html
type ProjectSnippetsService struct {
client *Client
}
// Snippet represents a GitLab project snippet.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/project_snippets.html
type Snippet struct {
ID int `json:"id"`
Title string `json:"title"`
FileName string `json:"file_name"`
Author struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
} `json:"author"`
ExpiresAt *time.Time `json:"expires_at"`
UpdatedAt time.Time `json:"updated_at"`
CreatedAt time.Time `json:"created_at"`
}
func (s Snippet) String() string {
return Stringify(s)
}
// ListSnippits gets a list of project snippets.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/project_snippets.html#list-snippets
func (s *ProjectSnippetsService) ListSnippits(pid interface{}) ([]*Snippet, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var ps []*Snippet
resp, err := s.client.Do(req, &ps)
if err != nil {
return nil, resp, err
}
return ps, resp, err
}
// GetSnippit gets a single project snippet
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#single-snippet
func (s *ProjectSnippetsService) GetSnippit(
pid interface{},
snippet int) (*Snippet, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d", url.QueryEscape(project), snippet)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
ps := new(Snippet)
resp, err := s.client.Do(req, ps)
if err != nil {
return nil, resp, err
}
return ps, resp, err
}
// CreateSnippetOptions represents the available CreateSnippet() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#create-new-snippet
type CreateSnippetOptions struct {
Title string `url:"title,omitempty"`
FileName string `url:"file_name,omitempty"`
Code string `url:"code,omitempty"`
VisibilityLevel VisibilityLevel `url:"visibility_level,omitempty"`
}
// CreateSnippet creates a new project snippet. The user must have permission
// to create new snippets.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#create-new-snippet
func (s *ProjectSnippetsService) CreateSnippet(
pid interface{},
opt *CreateSnippetOptions) (*Snippet, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
ps := new(Snippet)
resp, err := s.client.Do(req, ps)
if err != nil {
return nil, resp, err
}
return ps, resp, err
}
// UpdateSnippetOptions represents the available UpdateSnippet() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#update-snippet
type UpdateSnippetOptions struct {
Title string `url:"title,omitempty"`
FileName string `url:"file_name,omitempty"`
Code string `url:"code,omitempty"`
VisibilityLevel VisibilityLevel `url:"visibility_level,omitempty"`
}
// UpdateSnippet updates an existing project snippet. The user must have
// permission to change an existing snippet.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#update-snippet
func (s *ProjectSnippetsService) UpdateSnippet(
pid interface{},
snippet int,
opt *UpdateSnippetOptions) (*Snippet, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d", url.QueryEscape(project), snippet)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
ps := new(Snippet)
resp, err := s.client.Do(req, ps)
if err != nil {
return nil, resp, err
}
return ps, resp, err
}
// DeleteSnippet deletes an existing project snippet. This is an idempotent
// function and deleting a non-existent snippet still returns a 200 OK status
// code.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#delete-snippet
func (s *ProjectSnippetsService) DeleteSnippet(pid interface{}, snippet int) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d", url.QueryEscape(project), snippet)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// SnippitContent returns the raw project snippet as plain text.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/project_snippets.html#snippet-content
func (s *ProjectSnippetsService) SnippitContent(
pid interface{},
snippet int) ([]byte, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/snippets/%d/raw", url.QueryEscape(project), snippet)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var b bytes.Buffer
resp, err := s.client.Do(req, &b)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
//
// 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 (
"fmt"
"net/url"
"time"
)
// ProjectsService handles communication with the repositories related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html
type ProjectsService struct {
client *Client
}
// Project represents a GitLab project.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html
type Project struct {
ID int `json:"id"`
Description interface{} `json:"description"`
DefaultBranch string `json:"default_branch"`
Public bool `json:"public"`
VisibilityLevel VisibilityLevel `json:"visibility_level"`
SSHURLToRepo string `json:"ssh_url_to_repo"`
HTTPURLToRepo string `json:"http_url_to_repo"`
WebURL string `json:"web_url"`
TagList []string `json:"tag_list"`
Owner *User `json:"owner"`
Name string `json:"name"`
NameWithNamespace string `json:"name_with_namespace"`
Path string `json:"path"`
PathWithNamespace string `json:"path_with_namespace"`
IssuesEnabled bool `json:"issues_enabled"`
MergeRequestsEnabled bool `json:"merge_requests_enabled"`
WikiEnabled bool `json:"wiki_enabled"`
SnippetsEnabled bool `json:"snippets_enabled"`
CreatedAt string `json:"created_at"`
LastActivityAt string `json:"last_activity_at"`
CreatorID int `json:"creator_id"`
Namespace struct {
CreatedAt string `json:"created_at"`
Description string `json:"description"`
ID int `json:"id"`
Name string `json:"name"`
OwnerID int `json:"owner_id"`
Path string `json:"path"`
UpdatedAt string `json:"updated_at"`
} `json:"namespace"`
Archived bool `json:"archived"`
AvatarURL string `json:"avatar_url"`
}
func (s Project) String() string {
return Stringify(s)
}
// ListProjectsOptions represents the available ListProjects() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#list-projects
type ListProjectsOptions struct {
Archived bool `url:"archived,omitempty"`
OrderBy string `url:"order_by,omitempty"`
Sort string `url:"sort,omitempty"`
Search string `url:"search,omitempty"`
CIEnabledFirst bool `url:"ci_enabled_first,omitempty"`
}
// ListProjects gets a list of projects accessible by the authenticated user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#list-projects
func (s *ProjectsService) ListProjects(opt *ListProjectsOptions) ([]*Project, *Response, error) {
req, err := s.client.NewRequest("GET", "projects", opt)
if err != nil {
return nil, nil, err
}
var p []*Project
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ListOwnedProjects gets a list of projects which are owned by the
// authenticated user.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-owned-projects
func (s *ProjectsService) ListOwnedProjects(
opt *ListProjectsOptions) ([]*Project, *Response, error) {
req, err := s.client.NewRequest("GET", "projects/owned", opt)
if err != nil {
return nil, nil, err
}
var p []*Project
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ListAllProjects gets a list of all GitLab projects (admin only).
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-all-projects
func (s *ProjectsService) ListAllProjects(opt *ListProjectsOptions) ([]*Project, *Response, error) {
req, err := s.client.NewRequest("GET", "projects/all", opt)
if err != nil {
return nil, nil, err
}
var p []*Project
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// GetProject gets a specific project, identified by project ID or
// NAMESPACE/PROJECT_NAME, which is owned by the authenticated user.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-single-project
func (s *ProjectsService) GetProject(pid interface{}) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// SearchProjectsOptions represents the available SearchProjects() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#search-for-projects-by-name
type SearchProjectsOptions struct {
PerPage int `url:"per_page,omitempty"`
Page int `url:"page,omitempty"`
OrderBy string `url:"order_by,omitempty"`
Sort string `url:"sort,omitempty"`
}
// SearchProjects searches for projects by name which are accessible to the
// authenticated user.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#search-for-projects-by-name
func (s *ProjectsService) SearchProjects(
query string,
opt *SearchProjectsOptions) ([]*Project, *Response, error) {
u := fmt.Sprintf("projects/search/%s", query)
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var p []*Project
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ProjectEvent represents a GitLab project event.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-project-events
type ProjectEvent struct {
Title interface{} `json:"title"`
ProjectID int `json:"project_id"`
ActionName string `json:"action_name"`
TargetID interface{} `json:"target_id"`
TargetType interface{} `json:"target_type"`
AuthorID int `json:"author_id"`
AuthorUsername string `json:"author_username"`
Data struct {
Before string `json:"before"`
After string `json:"after"`
Ref string `json:"ref"`
UserID int `json:"user_id"`
UserName string `json:"user_name"`
Repository struct {
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description"`
Homepage string `json:"homepage"`
} `json:"repository"`
Commits []struct {
ID string `json:"id"`
Message string `json:"message"`
Timestamp time.Time `json:"timestamp"`
URL string `json:"url"`
Author struct {
Name string `json:"name"`
Email string `json:"email"`
} `json:"author"`
} `json:"commits"`
TotalCommitsCount int `json:"total_commits_count"`
} `json:"data"`
TargetTitle interface{} `json:"target_title"`
}
func (s ProjectEvent) String() string {
return Stringify(s)
}
// GetProjectEvents gets the events for the specified project. Sorted from
// newest to latest.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-project-events
func (s *ProjectsService) GetProjectEvents(pid interface{}) ([]*ProjectEvent, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/events", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var p []*ProjectEvent
resp, err := s.client.Do(req, &p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// CreateProjectOptions represents the available CreateProjects() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#create-project
type CreateProjectOptions struct {
Name string `url:"name,omitempty"`
Path string `url:"path,omitempty"`
NamespaceID string `url:"namespace_id,omitempty"`
Description string `url:"description,omitempty"`
IssuesEnabled bool `url:"issues_enabled,omitempty"`
MergeRequestsEnabled bool `url:"merge_requests_enabled,omitempty"`
WikiEnabled bool `url:"wiki_enabled,omitempty"`
SnippetsEnabled bool `url:"snippets_enabled,omitempty"`
Public bool `url:"public,omitempty"`
VisibilityLevel VisibilityLevel `url:"visibility_level,omitempty"`
ImportURL string `url:"import_url,omitempty"`
}
// CreateProject creates a new project owned by the authenticated user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#create-project
func (s *ProjectsService) CreateProject(
opt *CreateProjectOptions) (*Project, *Response, error) {
req, err := s.client.NewRequest("POST", "projects", opt)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// CreateProjectForUserOptions represents the available CreateProjectForUser()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#create-project-for-user
type CreateProjectForUserOptions struct {
Name string `url:"name,omitempty"`
Description string `url:"description,omitempty"`
DefaultBranch string `url:"default_branch,omitempty"`
IssuesEnabled bool `url:"issues_enabled,omitempty"`
MergeRequestsEnabled bool `url:"merge_requests_enabled,omitempty"`
WikiEnabled bool `url:"wiki_enabled,omitempty"`
SnippetsEnabled bool `url:"snippets_enabled,omitempty"`
Public bool `url:"public,omitempty"`
VisibilityLevel VisibilityLevel `url:"visibility_level,omitempty"`
ImportURL string `url:"import_url,omitempty"`
}
// CreateProjectForUser creates a new project owned by the specified user.
// Available only for admins.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#create-project-for-user
func (s *ProjectsService) CreateProjectForUser(
user int,
opt *CreateProjectForUserOptions) (*Project, *Response, error) {
u := fmt.Sprintf("projects/user/%d", user)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// EditProjectOptions represents the available EditProject() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#edit-project
type EditProjectOptions struct {
Name string `url:"name,omitempty"`
Path string `url:"path,omitempty"`
Description string `url:"description,omitempty"`
DefaultBranch string `url:"default_branch,omitempty"`
IssuesEnabled bool `url:"issues_enabled,omitempty"`
MergeRequestsEnabled bool `url:"merge_requests_enabled,omitempty"`
WikiEnabled bool `url:"wiki_enabled,omitempty"`
SnippetsEnabled bool `url:"snippets_enabled,omitempty"`
Public bool `url:"public,omitempty"`
VisibilityLevel VisibilityLevel `url:"visibility_level,omitempty"`
}
// EditProject updates an existing project.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#edit-project
func (s *ProjectsService) EditProject(
pid interface{},
opt *EditProjectOptions) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s", url.QueryEscape(project))
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// ForkProject forks a project into the user namespace of the authenticated
// user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#fork-project
func (s *ProjectsService) ForkProject(pid interface{}) (*Project, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/fork/%s", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
p := new(Project)
resp, err := s.client.Do(req, p)
if err != nil {
return nil, resp, err
}
return p, resp, err
}
// DeleteProject removes a project including all associated resources
// (issues, merge requests etc.)
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#remove-project
func (s *ProjectsService) DeleteProject(pid interface{}) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s", url.QueryEscape(project))
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// ProjectMember represents a project member.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-project-team-members
type ProjectMember struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
AccessLevel int `json:"access_level"`
}
// ListProjectMembersOptions represents the available ListProjectMembers()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-project-team-members
type ListProjectMembersOptions struct {
Query string `url:"query,omitempty"`
}
// ListProjectMembers gets a list of a project's team members.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-project-team-members
func (s *ProjectsService) ListProjectMembers(
pid interface{},
opt *ListProjectMembersOptions) ([]*ProjectMember, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/members", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var pm []*ProjectMember
resp, err := s.client.Do(req, &pm)
if err != nil {
return nil, resp, err
}
return pm, resp, err
}
// GetProjectMember gets a project team member.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-project-team-member
func (s *ProjectsService) GetProjectMember(
pid interface{},
user int) (*ProjectMember, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/members/%d", url.QueryEscape(project), user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
pm := new(ProjectMember)
resp, err := s.client.Do(req, pm)
if err != nil {
return nil, resp, err
}
return pm, resp, err
}
// AddProjectMemberOptions represents the available AddProjectMember() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#add-project-team-member
type AddProjectMemberOptions struct {
UserID int `url:"user_id,omitempty"`
AccessLevel AccessLevel `url:"access_level,omitempty"`
}
// AddProjectMember adds a user to a project team. This is an idempotent
// method and can be called multiple times with the same parameters. Adding
// team membership to a user that is already a member does not affect the
// existing membership.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#add-project-team-member
func (s *ProjectsService) AddProjectMember(
pid interface{},
opt *AddProjectMemberOptions) (*ProjectMember, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/members", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
pm := new(ProjectMember)
resp, err := s.client.Do(req, pm)
if err != nil {
return nil, resp, err
}
return pm, resp, err
}
// EditProjectMemberOptions represents the available EditProjectMember() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#edit-project-team-member
type EditProjectMemberOptions struct {
AccessLevel AccessLevel `url:"access_level,omitempty"`
}
// EditProjectMember updates a project team member to a specified access level..
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#edit-project-team-member
func (s *ProjectsService) EditProjectMember(
pid interface{},
user int,
opt *EditProjectMemberOptions) (*ProjectMember, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/members/%d", url.QueryEscape(project), user)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
pm := new(ProjectMember)
resp, err := s.client.Do(req, pm)
if err != nil {
return nil, resp, err
}
return pm, resp, err
}
// DeleteProjectMember removes a user from a project team.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#remove-project-team-member
func (s *ProjectsService) DeleteProjectMember(pid interface{}, user int) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/members/%d", url.QueryEscape(project), user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// ProjectHook represents a project hook.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-project-hooks
type ProjectHook struct {
ID int `json:"id"`
URL string `json:"url"`
ProjectID int `json:"project_id"`
PushEvents bool `json:"push_events"`
IssuesEvents bool `json:"issues_events"`
MergeRequestsEvents bool `json:"merge_requests_events"`
CreatedAt time.Time `json:"created_at"`
}
// ListProjectHooks gets a list of project hooks.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#list-project-hooks
func (s *ProjectsService) ListProjectHooks(pid interface{}) ([]*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var ph []*ProjectHook
resp, err := s.client.Do(req, &ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// GetProjectHook gets a specific hook for a project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#get-project-hook
func (s *ProjectsService) GetProjectHook(
pid interface{},
hook int) (*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks/%d", url.QueryEscape(project), hook)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
ph := new(ProjectHook)
resp, err := s.client.Do(req, ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// AddProjectHookOptions represents the available AddProjectHook() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#add-project-hook
type AddProjectHookOptions struct {
URL string `url:"url,omitempty"`
PushEvents bool `url:"push_events,omitempty"`
IssuesEvents bool `url:"issues_events,omitempty"`
MergeRequestsEvents bool `url:"merge_requests_events,omitempty"`
TagPushEvents bool `url:"tag_push_events,omitempty"`
}
// AddProjectHook adds a hook to a specified project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#add-project-hook
func (s *ProjectsService) AddProjectHook(
pid interface{},
opt *AddProjectHookOptions) (*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
ph := new(ProjectHook)
resp, err := s.client.Do(req, ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// EditProjectHookOptions represents the available EditProjectHook() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#edit-project-hook
type EditProjectHookOptions struct {
URL string `url:"url,omitempty"`
PushEvents bool `url:"push_events,omitempty"`
IssuesEvents bool `url:"issues_events,omitempty"`
MergeRequestsEvents bool `url:"merge_requests_events,omitempty"`
TagPushEvents bool `url:"tag_push_events,omitempty"`
}
// EditProjectHook edits a hook for a specified project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#edit-project-hook
func (s *ProjectsService) EditProjectHook(
pid interface{},
hook int,
opt *EditProjectHookOptions) (*ProjectHook, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/hooks/%d", url.QueryEscape(project), hook)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
ph := new(ProjectHook)
resp, err := s.client.Do(req, ph)
if err != nil {
return nil, resp, err
}
return ph, resp, err
}
// DeleteProjectHook removes a hook from a project. This is an idempotent
// method and can be called multiple times. Either the hook is available or not.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#delete-project-hook
func (s *ProjectsService) DeleteProjectHook(pid interface{}, hook int) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/hooks/%d", url.QueryEscape(project), hook)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// ProjectForkRelation represents a project fork relationship.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#admin-fork-relation
type ProjectForkRelation struct {
ID int `json:"id"`
ForkedToProjectID int `json:"forked_to_project_id"`
ForkedFromProjectID int `json:"forked_from_project_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// CreateProjectForkRelation creates a forked from/to relation between
// existing projects.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#create-a-forked-fromto-relation-between-existing-projects.
func (s *ProjectsService) CreateProjectForkRelation(
pid int,
fork int) (*ProjectForkRelation, *Response, error) {
u := fmt.Sprintf("projects/%d/fork/%d", pid, fork)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
pfr := new(ProjectForkRelation)
resp, err := s.client.Do(req, pfr)
if err != nil {
return nil, resp, err
}
return pfr, resp, err
}
// DeleteProjectForkRelation deletes an existing forked from relationship.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/projects.html#delete-an-existing-forked-from-relationship
func (s *ProjectsService) DeleteProjectForkRelation(pid int) (*Response, error) {
u := fmt.Sprintf("projects/%d/fork", pid)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
//
// 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"
"fmt"
"net/url"
)
// RepositoriesService handles communication with the repositories related
// methods of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/repositories.html
type RepositoriesService struct {
client *Client
}
// Tag represents a GitLab repository tag.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#list-project-repository-tags
type Tag struct {
Commit *Commit `json:"commit"`
Name string `json:"name"`
Message string `json:"message"`
}
func (r Tag) String() string {
return Stringify(r)
}
// ListTags gets a list of repository tags from a project, sorted by name in
// reverse alphabetical order.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#list-project-repository-tags
func (s *RepositoriesService) ListTags(pid interface{}) ([]*Tag, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/tags", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var t []*Tag
resp, err := s.client.Do(req, &t)
if err != nil {
return nil, resp, err
}
return t, resp, err
}
// CreateTagOptions represents the available CreateTag() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#create-a-new-tag
type CreateTagOptions struct {
TagName string `url:"tag_name,omitempty"`
Ref string `url:"ref,omitempty"`
Message string `url:"message,omitempty"`
}
// CreateTag creates a new tag in the repository that points to the supplied ref.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#create-a-new-tag
func (s *RepositoriesService) CreateTag(
pid interface{},
opt *CreateTagOptions) (*Tag, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/tags", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
t := new(Tag)
resp, err := s.client.Do(req, t)
if err != nil {
return nil, resp, err
}
return t, resp, err
}
// TreeNode represents a GitLab repository file or directory.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#list-repository-tree
type TreeNode struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Mode string `json:"mode"`
}
func (t TreeNode) String() string {
return Stringify(t)
}
// ListTreeOptions represents the available ListTree() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#list-repository-tree
type ListTreeOptions struct {
Path string `url:"path,omitempty"`
RefName string `url:"ref_name,omitempty"`
}
// ListTree gets a list of repository files and directories in a project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#list-repository-tree
func (s *RepositoriesService) ListTree(
pid interface{},
opt *ListTreeOptions) ([]*TreeNode, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/tree", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var t []*TreeNode
resp, err := s.client.Do(req, &t)
if err != nil {
return nil, resp, err
}
return t, resp, err
}
// RawFileContentOptions represents the available RawFileContent() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#raw-file-content
type RawFileContentOptions struct {
FilePath string `url:"filepath,omitempty"`
}
// RawFileContent gets the raw file contents for a file by commit SHA and path
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#raw-file-content
func (s *RepositoriesService) RawFileContent(
pid interface{},
sha string,
opt *RawFileContentOptions) ([]byte, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/blobs/%s", url.QueryEscape(project), sha)
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var b bytes.Buffer
resp, err := s.client.Do(req, &b)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// RawBlobContent gets the raw file contents for a blob by blob SHA.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#raw-blob-content
func (s *RepositoriesService) RawBlobContent(
pid interface{},
sha string) ([]byte, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/raw_blobs/%s", url.QueryEscape(project), sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var b bytes.Buffer
resp, err := s.client.Do(req, &b)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// ArchiveOptions represents the available Archive() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#get-file-archive
type ArchiveOptions struct {
SHA string `url:"sha,omitempty"`
}
// Archive gets an archive of the repository.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#get-file-archive
func (s *RepositoriesService) Archive(
pid interface{},
opt *ArchiveOptions) ([]byte, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/archive", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
var b bytes.Buffer
resp, err := s.client.Do(req, &b)
if err != nil {
return nil, resp, err
}
return b.Bytes(), resp, err
}
// Compare represents the result of a comparison of branches, tags or commits.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits
type Compare struct {
Commit *Commit `json:"commit"`
Commits []*Commit `json:"commits"`
Diffs []*Diff `json:"diffs"`
CompareTimeout bool `json:"compare_timeout"`
CompareSameRef bool `json:"compare_same_ref"`
}
func (c Compare) String() string {
return Stringify(c)
}
// CompareOptions represents the available Compare() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits
type CompareOptions struct {
From string `url:"from,omitempty"`
To string `url:"to,omitempty"`
}
// Compare compares branches, tags or commits.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits
func (s *RepositoriesService) Compare(
pid interface{},
opt *CompareOptions) (*Compare, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/compare", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
c := new(Compare)
resp, err := s.client.Do(req, c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
// Contributor represents a GitLap contributor.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/repositories.html#contributer
type Contributor struct {
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Commits int `json:"commits,omitempty"`
Additions int `json:"additions,omitempty"`
Deletions int `json:"deletions,omitempty"`
}
func (c Contributor) String() string {
return Stringify(c)
}
// Contributors gets the repository contributors list.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/repositories.html#contributer
func (s *RepositoriesService) Contributors(pid interface{}) ([]*Contributor, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/contributors", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var c []*Contributor
resp, err := s.client.Do(req, &c)
if err != nil {
return nil, resp, err
}
return c, resp, err
}
//
// 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 (
"fmt"
"net/url"
)
// RepositoryFilesService handles communication with the repository files
// related methods of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/repository_files.html
type RepositoryFilesService struct {
client *Client
}
// File represents a GitLab repository file.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/repository_files.html
type File struct {
FileName string `json:"file_name"`
FilePath string `json:"file_path"`
Size int `json:"size"`
Encoding string `json:"encoding"`
Content string `json:"content"`
Ref string `json:"ref"`
BlobID string `json:"blob_id"`
CommitID string `json:"commit_id"`
}
func (r File) String() string {
return Stringify(r)
}
// GetFileOptions represents the available GetFile() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#get-file-from-respository
type GetFileOptions struct {
FilePath string `url:"file_path,omitempty"`
Ref string `url:"ref,omitempty"`
}
// GetFile allows you to receive information about a file in repository like
// name, size, content. Note that file content is Base64 encoded.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#get-file-from-respository
func (s *RepositoryFilesService) GetFile(
pid interface{},
opt *GetFileOptions) (*File, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/files", url.QueryEscape(project))
req, err := s.client.NewRequest("GET", u, opt)
if err != nil {
return nil, nil, err
}
f := new(File)
resp, err := s.client.Do(req, f)
if err != nil {
return nil, resp, err
}
return f, resp, err
}
// FileInfo represents file details of a GitLab repository file.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/repository_files.html
type FileInfo struct {
FilePath string `json:"file_path"`
BranchName string `json:"branch_name"`
}
func (r FileInfo) String() string {
return Stringify(r)
}
// CreateFileOptions represents the available CreateFile() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#create-new-file-in-repository
type CreateFileOptions struct {
FilePath string `url:"file_path,omitempty"`
BranchName string `url:"branch_name,omitempty"`
Encoding string `url:"encoding,omitempty"`
Content string `url:"content,omitempty"`
CommitMessage string `url:"commit_message,omitempty"`
}
// CreateFile creates a new file in a repository.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#create-new-file-in-repository
func (s *RepositoryFilesService) CreateFile(
pid interface{},
opt *CreateFileOptions) (*FileInfo, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/files", url.QueryEscape(project))
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
f := new(FileInfo)
resp, err := s.client.Do(req, f)
if err != nil {
return nil, resp, err
}
return f, resp, err
}
// UpdateFileOptions represents the available UpdateFile() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#update-existing-file-in-repository
type UpdateFileOptions struct {
FilePath string `url:"file_path,omitempty"`
BranchName string `url:"branch_name,omitempty"`
Encoding string `url:"encoding,omitempty"`
Content string `url:"content,omitempty"`
CommitMessage string `url:"commit_message,omitempty"`
}
// UpdateFile updates an existing file in a repository
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#update-existing-file-in-repository
func (s *RepositoryFilesService) UpdateFile(
pid interface{},
opt *UpdateFileOptions) (*FileInfo, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/files", url.QueryEscape(project))
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
f := new(FileInfo)
resp, err := s.client.Do(req, f)
if err != nil {
return nil, resp, err
}
return f, resp, err
}
// DeleteFileOptions represents the available DeleteFile() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#delete-existing-file-in-repository
type DeleteFileOptions struct {
FilePath string `url:"file_path,omitempty"`
BranchName string `url:"branch_name,omitempty"`
CommitMessage string `url:"commit_message,omitempty"`
}
// DeleteFile deletes an existing file in a repository
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/repository_files.html#delete-existing-file-in-repository
func (s *RepositoryFilesService) DeleteFile(
pid interface{},
opt *DeleteFileOptions) (*FileInfo, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%s/repository/files", url.QueryEscape(project))
req, err := s.client.NewRequest("DELETE", u, opt)
if err != nil {
return nil, nil, err
}
f := new(FileInfo)
resp, err := s.client.Do(req, f)
if err != nil {
return nil, resp, err
}
return f, resp, err
}
//
// 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 (
"fmt"
"net/url"
)
// ServicesService handles communication with the services related methods of
// the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/services.html
type ServicesService struct {
client *Client
}
// SetGitLabCIServiceOptions represents the available SetGitLabCIService()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/services.html#edit-gitlab-ci-service
type SetGitLabCIServiceOptions struct {
Token string `url:"token,omitempty"`
ProjectURL string `url:"project_url,omitempty"`
}
// SetGitLabCIService sets GitLab CI service for a project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/services.html#edit-gitlab-ci-service
func (s *ServicesService) SetGitLabCIService(
pid interface{},
opt *SetGitLabCIServiceOptions) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/gitlab-ci", url.QueryEscape(project))
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// DeleteGitLabCIService deletes GitLab CI service settings for a project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/services.html#delete-gitlab-ci-service
func (s *ServicesService) DeleteGitLabCIService(pid interface{}) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/gitlab-ci", url.QueryEscape(project))
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// SetHipChatServiceOptions represents the available SetHipChatService()
// options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/services.html#edit-hipchat-service
type SetHipChatServiceOptions struct {
Token string `url:"token,omitempty"`
Room string `url:"room,omitempty"`
}
// SetHipChatService sets HipChat service for a project
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/services.html#edit-hipchat-service
func (s *ServicesService) SetHipChatService(
pid interface{},
opt *SetHipChatServiceOptions) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/hipchat", url.QueryEscape(project))
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// DeleteHipChatService deletes HipChat service for project.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/services.html#delete-hipchat-service
func (s *ServicesService) DeleteHipChatService(pid interface{}) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}
u := fmt.Sprintf("projects/%s/services/hipchat", url.QueryEscape(project))
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
//
// 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 "time"
// SessionService handles communication with the session related methods of
// the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/session.html
type SessionService struct {
client *Client
}
// Session represents a GitLab session.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/session.html#session
type Session struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
PrivateToken string `json:"private_token"`
Blocked bool `json:"blocked"`
CreatedAt time.Time `json:"created_at"`
Bio interface{} `json:"bio"`
Skype string `json:"skype"`
Linkedin string `json:"linkedin"`
Twitter string `json:"twitter"`
WebsiteURL string `json:"website_url"`
DarkScheme bool `json:"dark_scheme"`
ThemeID int `json:"theme_id"`
IsAdmin bool `json:"is_admin"`
CanCreateGroup bool `json:"can_create_group"`
CanCreateTeam bool `json:"can_create_team"`
CanCreateProject bool `json:"can_create_project"`
}
// GetSessionOptions represents the available Session() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/session.html#session
type GetSessionOptions struct {
Login string `url:"login,omitempty"`
Email string `url:"email,omitempty"`
Password string `url:"password,omitempty"`
}
// GetSession logs in to get private token.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/session.html#session
func (s *SessionService) GetSession(opt *GetSessionOptions) (*Session, *Response, error) {
req, err := s.client.NewRequest("POST", "session", opt)
if err != nil {
return nil, nil, err
}
session := new(Session)
resp, err := s.client.Do(req, session)
if err != nil {
return nil, resp, err
}
return session, resp, err
}
//
// 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 "time"
// SettingsService handles communication with the application SettingsService
// related methods of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/settings.html
type SettingsService struct {
client *Client
}
// Settings represents the GitLab application settings.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/settings.html
type Settings struct {
ID int `json:"id"`
DefaultProjectsLimit int `json:"default_projects_limit"`
SignupEnabled bool `json:"signup_enabled"`
SigninEnabled bool `json:"signin_enabled"`
GravatarEnabled bool `json:"gravatar_enabled"`
SignInText string `json:"sign_in_text"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
HomePageURL string `json:"home_page_url"`
DefaultBranchProtection int `json:"default_branch_protection"`
TwitterSharingEnabled bool `json:"twitter_sharing_enabled"`
RestrictedVisibilityLevels []VisibilityLevel `json:"restricted_visibility_levels"`
MaxAttachmentSize int `json:"max_attachment_size"`
SessionExpireDelay int `json:"session_expire_delay"`
DefaultProjectVisibility int `json:"default_project_visibility"`
DefaultSnippetVisibility int `json:"default_snippet_visibility"`
RestrictedSignupDomains []string `json:"restricted_signup_domains"`
UserOauthApplications bool `json:"user_oauth_applications"`
AfterSignOutPath string `json:"after_sign_out_path"`
}
func (s Settings) String() string {
return Stringify(s)
}
// GetSettings gets the current application settings.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/settings.html#get-current-application.settings
func (s *SettingsService) GetSettings() (*Settings, *Response, error) {
req, err := s.client.NewRequest("GET", "application/settings", nil)
if err != nil {
return nil, nil, err
}
as := new(Settings)
resp, err := s.client.Do(req, as)
if err != nil {
return nil, resp, err
}
return as, resp, err
}
// UpdateSettingsOptions represents the available UpdateSettings() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/settings.html#change-application.settings
type UpdateSettingsOptions struct {
DefaultProjectsLimit int `url:"default_projects_limit,omitempty"`
SignupEnabled bool `url:"signup_enabled,omitempty"`
SigninEnabled bool `url:"signin_enabled,omitempty"`
GravatarEnabled bool `url:"gravatar_enabled,omitempty"`
SignInText string `url:"sign_in_text,omitempty"`
HomePageURL string `url:"home_page_url,omitempty"`
DefaultBranchProtection int `url:"default_branch_protection,omitempty"`
TwitterSharingEnabled bool `url:"twitter_sharing_enabled,omitempty"`
RestrictedVisibilityLevels []VisibilityLevel `url:"restricted_visibility_levels,omitempty"`
MaxAttachmentSize int `url:"max_attachment_size,omitempty"`
SessionExpireDelay int `url:"session_expire_delay,omitempty"`
DefaultProjectVisibility int `url:"default_project_visibility,omitempty"`
DefaultSnippetVisibility int `url:"default_snippet_visibility,omitempty"`
RestrictedSignupDomains []string `url:"restricted_signup_domains,omitempty"`
UserOauthApplications bool `url:"user_oauth_applications,omitempty"`
AfterSignOutPath string `url:"after_sign_out_path,omitempty"`
}
// UpdateSettings updates the application settings.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/settings.html#change-application.settings
func (s *SettingsService) UpdateSettings(opt *UpdateSettingsOptions) (*Settings, *Response, error) {
req, err := s.client.NewRequest("PUT", "application/settings", opt)
if err != nil {
return nil, nil, err
}
as := new(Settings)
resp, err := s.client.Do(req, as)
if err != nil {
return nil, resp, err
}
return as, resp, err
}
//
// 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"
"fmt"
"io"
"reflect"
)
// Stringify attempts to create a reasonable string representation of types in
// the GitHub library. It does things like resolve pointers to their values
// and omits struct fields with nil values.
func Stringify(message interface{}) string {
var buf bytes.Buffer
v := reflect.ValueOf(message)
stringifyValue(&buf, v)
return buf.String()
}
// stringifyValue was heavily inspired by the goprotobuf library.
func stringifyValue(w io.Writer, val reflect.Value) {
if val.Kind() == reflect.Ptr && val.IsNil() {
w.Write([]byte("<nil>"))
return
}
v := reflect.Indirect(val)
switch v.Kind() {
case reflect.String:
fmt.Fprintf(w, `"%s"`, v)
case reflect.Slice:
w.Write([]byte{'['})
for i := 0; i < v.Len(); i++ {
if i > 0 {
w.Write([]byte{' '})
}
stringifyValue(w, v.Index(i))
}
w.Write([]byte{']'})
return
case reflect.Struct:
if v.Type().Name() != "" {
w.Write([]byte(v.Type().String()))
}
w.Write([]byte{'{'})
var sep bool
for i := 0; i < v.NumField(); i++ {
fv := v.Field(i)
if fv.Kind() == reflect.Ptr && fv.IsNil() {
continue
}
if fv.Kind() == reflect.Slice && fv.IsNil() {
continue
}
if sep {
w.Write([]byte(", "))
} else {
sep = true
}
w.Write([]byte(v.Type().Field(i).Name))
w.Write([]byte{':'})
stringifyValue(w, fv)
}
w.Write([]byte{'}'})
default:
if v.CanInterface() {
fmt.Fprint(w, v.Interface())
}
}
}
//
// 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 (
"fmt"
"time"
)
// SystemHooksService handles communication with the system hooks related
// methods of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/system_hooks.html
type SystemHooksService struct {
client *Client
}
// Hook represents a GitLap system hook.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/system_hooks.html
type Hook struct {
ID int `json:"id"`
URL string `json:"url"`
CreatedAt time.Time `json:"created_at"`
}
func (h Hook) String() string {
return Stringify(h)
}
// ListHooks gets a list of system hooks.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/system_hooks.html#list-system-hooks
func (s *SystemHooksService) ListHooks() ([]*Hook, *Response, error) {
req, err := s.client.NewRequest("GET", "hooks", nil)
if err != nil {
return nil, nil, err
}
var h []*Hook
resp, err := s.client.Do(req, &h)
if err != nil {
return nil, resp, err
}
return h, resp, err
}
// AddHookOptions represents the available AddHook() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/system_hooks.html#add-new-system-hook-hook
type AddHookOptions struct {
URL string `url:"url,omitempty"`
}
// AddHook adds a new system hook hook.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/system_hooks.html#add-new-system-hook-hook
func (s *SystemHooksService) AddHook(opt *AddHookOptions) (*Hook, *Response, error) {
req, err := s.client.NewRequest("POST", "hooks", opt)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := s.client.Do(req, h)
if err != nil {
return nil, resp, err
}
return h, resp, err
}
// HookEvent represents an event triggert by a GitLab system hook.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/system_hooks.html
type HookEvent struct {
EventName string `json:"event_name"`
Name string `json:"name"`
Path string `json:"path"`
ProjectID int `json:"project_id"`
OwnerName string `json:"owner_name"`
OwnerEmail string `json:"owner_email"`
}
func (h HookEvent) String() string {
return Stringify(h)
}
// TestHook tests a system hook.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/system_hooks.html#test-system-hook
func (s *SystemHooksService) TestHook(hook int) (*HookEvent, *Response, error) {
u := fmt.Sprintf("hooks/%d", hook)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
h := new(HookEvent)
resp, err := s.client.Do(req, h)
if err != nil {
return nil, resp, err
}
return h, resp, err
}
// DeleteHook deletes a system hook. This is an idempotent API function and
// returns 200 OK even if the hook is not available. If the hook is deleted it
// is also returned as JSON.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/system_hooks.html#delete-system-hook
func (s *SystemHooksService) DeleteHook(hook int) (*Response, error) {
u := fmt.Sprintf("hooks/%d", hook)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
//
// 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 (
"fmt"
"time"
)
// UsersService handles communication with the user related methods of
// the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html
type UsersService struct {
client *Client
}
// User represents a GitLab user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
State string `json:"state"`
CreatedAt time.Time `json:"created_at"`
Bio string `json:"bio"`
Skype string `json:"skype"`
Linkedin string `json:"linkedin"`
Twitter string `json:"twitter"`
WebsiteURL string `json:"website_url"`
ExternUID string `json:"extern_uid"`
Provider string `json:"provider"`
ThemeID int `json:"theme_id"`
ColorSchemeID int `json:"color_scheme_id"`
IsAdmin bool `json:"is_admin"`
AvatarURL string `json:"avatar_url"`
CanCreateGroup bool `json:"can_create_group"`
CanCreateProject bool `json:"can_create_project"`
ProjectsLimit int `json:"projects_limit"`
CurrentSignInAt time.Time `json:"current_sign_in_at"`
TwoFactorEnabled bool `json:"two_factor_enabled"`
}
// ListUsers gets a list of users.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#list-users
func (s *UsersService) ListUsers() ([]*User, *Response, error) {
req, err := s.client.NewRequest("GET", "users", nil)
if err != nil {
return nil, nil, err
}
var usr []*User
resp, err := s.client.Do(req, &usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
// GetUser gets a single user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#single-user
func (s *UsersService) GetUser(user int) (*User, *Response, error) {
u := fmt.Sprintf("users/%d", user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
usr := new(User)
resp, err := s.client.Do(req, usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
// CreateUserOptions represents the available CreateUser() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#user-creation
type CreateUserOptions struct {
Email string `url:"email,omitempty"`
Password string `url:"password,omitempty"`
Username string `url:"username,omitempty"`
Name string `url:"name,omitempty"`
Skype string `url:"skype,omitempty"`
Linkedin string `url:"linkedin,omitempty"`
Twitter string `url:"twitter,omitempty"`
WebsiteURL string `url:"website_url,omitempty"`
ProjectsLimit int `url:"projects_limit,omitempty"`
ExternUID string `url:"extern_uid,omitempty"`
Provider string `url:"provider,omitempty"`
Bio string `url:"bio,omitempty"`
Admin bool `url:"admin,omitempty"`
CanCreateGroup bool `url:"can_create_group,omitempty"`
Confirm bool `url:"confirm,omitempty"`
}
// CreateUser creates a new user. Note only administrators can create new users.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#user-creation
func (s *UsersService) CreateUser(opt *CreateUserOptions) (*User, *Response, error) {
req, err := s.client.NewRequest("POST", "users", opt)
if err != nil {
return nil, nil, err
}
usr := new(User)
resp, err := s.client.Do(req, usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
// ModifyUserOptions represents the available ModifyUser() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#user-modification
type ModifyUserOptions struct {
Email string `url:"email,omitempty"`
Password string `url:"password,omitempty"`
Username string `url:"username,omitempty"`
Name string `url:"name,omitempty"`
Skype string `url:"skype,omitempty"`
Linkedin string `url:"linkedin,omitempty"`
Twitter string `url:"twitter,omitempty"`
WebsiteURL string `url:"website_url,omitempty"`
ProjectsLimit int `url:"projects_limit,omitempty"`
ExternUID string `url:"extern_uid,omitempty"`
Provider string `url:"provider,omitempty"`
Bio string `url:"bio,omitempty"`
Admin bool `url:"admin,omitempty"`
CanCreateGroup bool `url:"can_create_group,omitempty"`
}
// ModifyUser modifies an existing user. Only administrators can change attributes
// of a user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#user-modification
func (s *UsersService) ModifyUser(user int, opt *ModifyUserOptions) (*User, *Response, error) {
u := fmt.Sprintf("users/%d", user)
req, err := s.client.NewRequest("PUT", u, opt)
if err != nil {
return nil, nil, err
}
usr := new(User)
resp, err := s.client.Do(req, usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
// DeleteUser deletes a user. Available only for administrators. This is an
// idempotent function, calling this function for a non-existent user id still
// returns a status code 200 OK. The JSON response differs if the user was
// actually deleted or not. In the former the user is returned and in the
// latter not.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#user-deletion
func (s *UsersService) DeleteUser(user int) (*Response, error) {
u := fmt.Sprintf("users/%d", user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// CurrentUser gets currently authenticated user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#current-user
func (s *UsersService) CurrentUser() (*User, *Response, error) {
req, err := s.client.NewRequest("GET", "user", nil)
if err != nil {
return nil, nil, err
}
usr := new(User)
resp, err := s.client.Do(req, usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
// SSHKey represents a SSH key.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#list-ssh-keys
type SSHKey struct {
ID int `json:"id"`
Title string `json:"title"`
Key string `json:"key"`
CreatedAt time.Time `json:"created_at"`
}
// ListSSHKeys gets a list of currently authenticated user's SSH keys.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#list-ssh-keys
func (s *UsersService) ListSSHKeys() ([]*SSHKey, *Response, error) {
req, err := s.client.NewRequest("GET", "user/keys", nil)
if err != nil {
return nil, nil, err
}
var k []*SSHKey
resp, err := s.client.Do(req, &k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// ListSSHKeysForUser gets a list of a specified user's SSH keys. Available
// only for admin
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/users.html#list-ssh-keys-for-user
func (s *UsersService) ListSSHKeysForUser(user int) ([]*SSHKey, *Response, error) {
u := fmt.Sprintf("users/%d/keys", user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var k []*SSHKey
resp, err := s.client.Do(req, &k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// GetSSHKey gets a single key.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#single-ssh-key
func (s *UsersService) GetSSHKey(kid int) (*SSHKey, *Response, error) {
u := fmt.Sprintf("user/keys/%d", kid)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
k := new(SSHKey)
resp, err := s.client.Do(req, k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// AddSSHKeyOptions represents the available AddSSHKey() options.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/projects.html#add-ssh-key
type AddSSHKeyOptions struct {
Title string `url:"title,omitempty"`
Key string `url:"key,omitempty"`
}
// AddSSHKey creates a new key owned by the currently authenticated user.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#add-ssh-key
func (s *UsersService) AddSSHKey(opt *AddSSHKeyOptions) (*SSHKey, *Response, error) {
req, err := s.client.NewRequest("POST", "user/keys", opt)
if err != nil {
return nil, nil, err
}
k := new(SSHKey)
resp, err := s.client.Do(req, k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// AddSSHKeyForUser creates new key owned by specified user. Available only for
// admin.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#add-ssh-key-for-user
func (s *UsersService) AddSSHKeyForUser(
user int,
opt *AddSSHKeyOptions) (*SSHKey, *Response, error) {
u := fmt.Sprintf("users/%d/keys", user)
req, err := s.client.NewRequest("POST", u, opt)
if err != nil {
return nil, nil, err
}
k := new(SSHKey)
resp, err := s.client.Do(req, k)
if err != nil {
return nil, resp, err
}
return k, resp, err
}
// DeleteSSHKey deletes key owned by currently authenticated user. This is an
// idempotent function and calling it on a key that is already deleted or not
// available results in 200 OK.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/users.html#delete-ssh-key-for-current-owner
func (s *UsersService) DeleteSSHKey(kid int) (*Response, error) {
u := fmt.Sprintf("user/keys/%d", kid)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// DeleteSSHKeyForUser deletes key owned by a specified user. Available only
// for admin.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/users.html#delete-ssh-key-for-given-user
func (s *UsersService) DeleteSSHKeyForUser(user int, kid int) (*Response, error) {
u := fmt.Sprintf("users/%d/keys/%d", user, kid)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(req, nil)
if err != nil {
return resp, err
}
return resp, err
}
// BlockUser blocks the specified user. Available only for admin.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#block-user
func (s *UsersService) BlockUser(user int) (*User, *Response, error) {
u := fmt.Sprintf("users/%d/block", user)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, nil, err
}
usr := new(User)
resp, err := s.client.Do(req, usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
// UnblockUser unblocks the specified user. Available only for admin.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/users.html#unblock-user
func (s *UsersService) UnblockUser(user int) (*User, *Response, error) {
u := fmt.Sprintf("users/%d/unblock", user)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, nil, err
}
usr := new(User)
resp, err := s.client.Do(req, usr)
if err != nil {
return nil, resp, err
}
return usr, resp, err
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment