diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 9e5bdd3c2..827cac72f 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2,7 +2,7 @@ "ImportPath": "github.com/drone/drone", "GoVersion": "go1.4.2", "Packages": [ - "github.com/drone/drone/..." + "github.com/drone/drone..." ], "Deps": [ { @@ -10,6 +10,10 @@ "Comment": "null-236", "Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e" }, + { + "ImportPath": "github.com/Bugagazavr/go-gitlab-client", + "Rev": "912567bb7e65212c910733b3bfa178b11049a70e" + }, { "ImportPath": "github.com/BurntSushi/migration", "Rev": "c45b897f13350786ccaf2b7403b92b1c7ad85844" diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/.gitignore b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/.gitignore new file mode 100644 index 000000000..c444d00ec --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +.idea +examples/config.json \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/.travis.yml b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/.travis.yml new file mode 100644 index 000000000..a8de6ec6e --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/.travis.yml @@ -0,0 +1,6 @@ +language: go +go: + - 1.4 + +script: + - make deps test \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/Makefile b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/Makefile new file mode 100644 index 000000000..b1ee855db --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/Makefile @@ -0,0 +1,8 @@ +all:deps test + +deps: + go get github.com/stretchr/testify + go get ./... + +test: + go test -cover -short ./... diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/README.md b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/README.md new file mode 100644 index 000000000..4e716ee32 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/README.md @@ -0,0 +1,78 @@ +go-gitlab-client +================ + +This is a fork of project https://github.com/plouc/go-gitlab-client + +go-gitlab-client is a simple client written in golang to consume gitlab API. + +[![Build Status](https://travis-ci.org/Bugagazavr/go-gitlab-client.svg?branch=master)](https://travis-ci.org/Bugagazavr/go-gitlab-client) + + +##features + +* + ###Session [gitlab api doc](http://doc.gitlab.com/ce/api/session.html) + * get session + +* + ###Projects [gitlab api doc](http://doc.gitlab.com/ce/api/projects.html) + * list projects + * get single project + +* + ###Repositories [gitlab api doc](http://doc.gitlab.com/ce/api/repositories.html) + * list repository branches + * get single repository branch + * list project repository tags + * list repository commits + * list project hooks + * add/get/edit/rm project hook + +* + ###Users [gitlab api doc](http://doc.gitlab.com/ce/api/users.html) + * get single user + * manage user keys + +* + ###Deploy Keys [gitlab api doc](http://doc.gitlab.com/ce/api/deploy_keys.html) + * list project deploy keys + * add/get/rm project deploy key + + + + +##Installation + +To install go-gitlab-client, use `go get`: + + go get github.com/bugagazavr/go-gitlab-client + +Import the `go-gitlab-client` package into your code: + +```go +package whatever + +import ( + "github.com/bugagazavr/go-gitlab-client" +) +``` + + +##Update + +To update `go-gitlab-client`, use `go get -u`: + + go get -u github.com/bugagazavr/go-gitlab-client + + +##Documentation + +Visit the docs at http://godoc.org/github.com/Bugagazavr/go-gitlab-client + + +## Examples + +You can play with the examples located in the `examples` directory + +* [projects](https://github.com/Bugagazavr/go-gitlab-client/tree/master/examples/projects) +* [repositories](https://github.com/Bugagazavr/go-gitlab-client/tree/master/examples/repositories) diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/deploy_keys.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/deploy_keys.go new file mode 100644 index 000000000..38fe671c3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/deploy_keys.go @@ -0,0 +1,118 @@ +package gogitlab + +import ( + "encoding/json" + "net/url" +) + +const ( + // ID + project_url_deploy_keys = "/projects/:id/keys" // Get list of project deploy keys + // PROJECT ID AND KEY ID + project_url_deploy_key = "/projects/:id/keys/:key_id" // Get single project deploy key +) + +/* +Get list of project deploy keys. + + GET /projects/:id/keys + +Parameters: + + id The ID of a project + +*/ +func (g *Gitlab) ProjectDeployKeys(id string) ([]*PublicKey, error) { + + url, opaque := g.ResourceUrlRaw(project_url_deploy_keys, map[string]string{":id": id}) + + var deployKeys []*PublicKey + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &deployKeys) + } + + return deployKeys, err +} + +/* +Get single project deploy key. + + GET /projects/:id/keys/:key_id + +Parameters: + + id The ID of a project + key_id The ID of a key + +*/ +func (g *Gitlab) ProjectDeployKey(id, key_id string) (*PublicKey, error) { + + url, opaque := g.ResourceUrlRaw(project_url_deploy_key, map[string]string{ + ":id": id, + ":key_id": key_id, + }) + + var deployKey *PublicKey + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &deployKey) + } + + return deployKey, err +} + +/* +Add deploy key to project. + + POST /projects/:id/keys + +Parameters: + + id The ID of a project + title The key title + key The key value + +*/ +func (g *Gitlab) AddProjectDeployKey(id, title, key string) error { + var err error + + path, opaque := g.ResourceUrlRaw(project_url_deploy_keys, map[string]string{":id": id}) + + v := url.Values{} + v.Set("title", title) + v.Set("key", key) + + body := v.Encode() + + _, err = g.buildAndExecRequestRaw("POST", path, opaque, []byte(body)) + + return err +} + +/* +Remove deploy key from project + + DELETE /projects/:id/keys/:key_id + +Parameters: + + id The ID of a project + key_id The ID of a key + +*/ +func (g *Gitlab) RemoveProjectDeployKey(id, key_id string) error { + + url, opaque := g.ResourceUrlRaw(project_url_deploy_key, map[string]string{ + ":id": id, + ":key_id": key_id, + }) + + var err error + + _, err = g.buildAndExecRequestRaw("DELETE", url, opaque, nil) + + return err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/events.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/events.go new file mode 100644 index 000000000..82ac9c78f --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/events.go @@ -0,0 +1,72 @@ +package gogitlab + +import ( + "encoding/xml" + "fmt" + "time" +) + +type Person struct { + Name string `xml:"name"json:"name"` + Email string `xml:"email"json:"email"` +} + +type Link struct { + Rel string `xml:"rel,attr,omitempty"json:"rel"` + Href string `xml:"href,attr"json:"href"` +} + +type ActivityFeed struct { + Title string `xml:"title"json:"title"` + Id string `xml:"id"json:"id"` + Link []Link `xml:"link"json:"link"` + Updated time.Time `xml:"updated,attr"json:"updated"` + Entries []*FeedCommit `xml:"entry"json:"entries"` +} + +type FeedCommit struct { + Id string `xml:"id"json:"id"` + Title string `xml:"title"json:"title"` + Link []Link `xml:"link"json:"link"` + Updated time.Time `xml:"updated"json:"updated"` + Author Person `xml:"author"json:"author"` + Summary string `xml:"summary"json:"summary"` + // +} + +func (g *Gitlab) Activity() (ActivityFeed, error) { + + url := g.BaseUrl + dasboard_feed_path + "?private_token=" + g.Token + fmt.Println(url) + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err != nil { + fmt.Println("%s", err) + } + + var activity ActivityFeed + err = xml.Unmarshal(contents, &activity) + if err != nil { + fmt.Println("%s", err) + } + + return activity, err +} + +func (g *Gitlab) RepoActivityFeed(feedPath string) ActivityFeed { + + url := g.BaseUrl + g.RepoFeedPath + "?private_token=" + g.Token + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err != nil { + fmt.Println("%s", err) + } + + var activity ActivityFeed + err = xml.Unmarshal(contents, &activity) + if err != nil { + fmt.Println("%s", err) + } + + return activity +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/config.json.sample b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/config.json.sample new file mode 100644 index 000000000..b7285af65 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/config.json.sample @@ -0,0 +1,5 @@ +{ + "host": "https://gitlab.domain.com", + "api_path": "/api/v3", + "token": "TOKEN" +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/projects/main.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/projects/main.go new file mode 100644 index 000000000..26325c19d --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/projects/main.go @@ -0,0 +1,195 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "github.com/bugagazavr/go-gitlab-client" + "io/ioutil" + "os" + "strconv" + "time" +) + +type Config struct { + Host string `json:"host"` + ApiPath string `json:"api_path"` + Token string `json:"token"` +} + +func main() { + help := flag.Bool("help", false, "Show usage") + + file, e := ioutil.ReadFile("../config.json") + if e != nil { + fmt.Printf("Config file error: %v\n", e) + os.Exit(1) + } + + var config Config + json.Unmarshal(file, &config) + fmt.Printf("Results: %+v\n", config) + + var gitlab *gogitlab.Gitlab + + gitlab = gogitlab.NewGitlab(config.Host, config.ApiPath, config.Token) + + var method string + flag.StringVar(&method, "m", "", "Specify method to retrieve projects infos, available methods:\n"+ + " > -m projects\n"+ + " > -m project -id PROJECT_ID\n"+ + " > -m hooks -id PROJECT_ID\n"+ + " > -m branches -id PROJECT_ID\n"+ + " > -m merge_requests -id PROJECT_ID\n"+ + " > -m team -id PROJECT_ID") + + var id string + flag.StringVar(&id, "id", "", "Specify repository id") + + flag.Usage = func() { + fmt.Printf("Usage:\n") + flag.PrintDefaults() + } + flag.Parse() + + if *help == true || method == "" { + flag.Usage() + return + } + + startedAt := time.Now() + defer func() { + fmt.Printf("processed in %v\n", time.Now().Sub(startedAt)) + }() + + switch method { + case "projects": + fmt.Println("Fetching projects…") + + projects, err := gitlab.Projects(1, 100) + if err != nil { + fmt.Println(err.Error()) + return + } + + for _, project := range projects { + fmt.Printf("> %6d | %s\n", project.Id, project.Name) + } + + case "project": + fmt.Println("Fetching project…") + + if id == "" { + flag.Usage() + return + } + + project, err := gitlab.Project(id) + if err != nil { + fmt.Println(err.Error()) + return + } + + format := "> %-23s: %s\n" + + fmt.Printf("%s\n", project.Name) + fmt.Printf(format, "id", strconv.Itoa(project.Id)) + fmt.Printf(format, "name", project.Name) + fmt.Printf(format, "description", project.Description) + fmt.Printf(format, "default branch", project.DefaultBranch) + if project.Owner != nil { + fmt.Printf(format, "owner.name", project.Owner.Username) + } + fmt.Printf(format, "public", strconv.FormatBool(project.Public)) + fmt.Printf(format, "path", project.Path) + fmt.Printf(format, "path with namespace", project.PathWithNamespace) + fmt.Printf(format, "issues enabled", strconv.FormatBool(project.IssuesEnabled)) + fmt.Printf(format, "merge requests enabled", strconv.FormatBool(project.MergeRequestsEnabled)) + fmt.Printf(format, "wall enabled", strconv.FormatBool(project.WallEnabled)) + fmt.Printf(format, "wiki enabled", strconv.FormatBool(project.WikiEnabled)) + fmt.Printf(format, "created at", project.CreatedAtRaw) + //fmt.Printf(format, "namespace", project.Namespace) + + case "branches": + fmt.Println("Fetching project branches…") + + if id == "" { + flag.Usage() + return + } + + branches, err := gitlab.ProjectBranches(id) + if err != nil { + fmt.Println(err.Error()) + return + } + + for _, branch := range branches { + fmt.Printf("> %s\n", branch.Name) + } + + case "merge_requests": + fmt.Println("Fetching project merge_requests…") + + if id == "" { + flag.Usage() + return + } + + mrs, err := gitlab.ProjectMergeRequests(id, 0, 30, "opened") + if err != nil { + fmt.Println(err.Error()) + return + } + + for _, mr := range mrs { + author := "" + if mr.Author != nil { + author = mr.Author.Username + } + assignee := "" + if mr.Assignee != nil { + assignee = mr.Assignee.Username + } + fmt.Printf(" %s -> %s [%s] author[%s] assignee[%s]\n", + mr.SourceBranch, mr.TargetBranch, mr.State, + author, assignee) + } + + case "hooks": + fmt.Println("Fetching project hooks…") + + if id == "" { + flag.Usage() + return + } + + hooks, err := gitlab.ProjectHooks(id) + if err != nil { + fmt.Println(err.Error()) + return + } + + for _, hook := range hooks { + fmt.Printf("> [%d] %s, created on %s\n", hook.Id, hook.Url, hook.CreatedAtRaw) + } + + case "team": + fmt.Println("Fetching project team members…") + + if id == "" { + flag.Usage() + return + } + + members, err := gitlab.ProjectMembers(id) + if err != nil { + fmt.Println(err.Error()) + return + } + + for _, member := range members { + fmt.Printf("> [%d] %s (%s) since %s\n", member.Id, member.Username, member.Name, member.CreatedAt) + } + } +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/repositories/main.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/repositories/main.go new file mode 100644 index 000000000..e6591bb91 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/examples/repositories/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "github.com/bugagazavr/go-gitlab-client" + "io/ioutil" + "os" + "time" +) + +type Config struct { + Host string `json:"host"` + ApiPath string `json:"api_path"` + Token string `json:"token"` +} + +func main() { + help := flag.Bool("help", false, "Show usage") + + file, e := ioutil.ReadFile("../config.json") + if e != nil { + fmt.Printf("Config file error: %v\n", e) + os.Exit(1) + } + + var config Config + json.Unmarshal(file, &config) + fmt.Printf("Results: %+v\n", config) + + gitlab := gogitlab.NewGitlab(config.Host, config.ApiPath, config.Token) + + var method string + flag.StringVar(&method, "m", "", "Specify method to retrieve repositories, available methods:\n"+ + " > branches\n"+ + " > branch\n"+ + " > tags\n"+ + " > commits") + + var id string + flag.StringVar(&id, "id", "", "Specify repository id") + + flag.Usage = func() { + fmt.Printf("Usage:\n") + flag.PrintDefaults() + } + flag.Parse() + + if *help == true || method == "" || id == "" { + flag.Usage() + return + } + + startedAt := time.Now() + defer func() { + fmt.Printf("processed in %v\n", time.Now().Sub(startedAt)) + }() + + switch method { + case "branches": + fmt.Println("Fetching repository branches…") + + branches, err := gitlab.RepoBranches(id) + if err != nil { + fmt.Println(err.Error()) + } + + for _, branch := range branches { + fmt.Printf("> %s\n", branch.Name) + } + case "branch": + case "tags": + fmt.Println("Fetching repository tags…") + + tags, err := gitlab.RepoTags(id) + if err != nil { + fmt.Println(err.Error()) + } + + for _, tag := range tags { + fmt.Printf("> %s\n", tag.Name) + } + case "commits": + fmt.Println("Fetching repository commits…") + + commits, err := gitlab.RepoCommits(id) + if err != nil { + fmt.Println(err.Error()) + } + + for _, commit := range commits { + fmt.Printf("%s > [%s] %s\n", commit.CreatedAt.Format("Mon 02 Jan 15:04"), commit.Author_Name, commit.Title) + } + } +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/gitlab.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/gitlab.go new file mode 100644 index 000000000..415dc5ed6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/gitlab.go @@ -0,0 +1,191 @@ +// Package github implements a simple client to consume gitlab API. +package gogitlab + +import ( + "bytes" + "crypto/tls" + "flag" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + +const ( + dasboard_feed_path = "/dashboard.atom" +) + +type Gitlab struct { + BaseUrl string + ApiPath string + RepoFeedPath string + Token string + Bearer bool + Client *http.Client +} + +const ( + dateLayout = "2006-01-02T15:04:05-07:00" +) + +var ( + skipCertVerify = flag.Bool("gitlab.skip-cert-check", false, + `If set to true, gitlab client will skip certificate checking for https, possibly exposing your system to MITM attack.`) +) + +func NewGitlab(baseUrl, apiPath, token string) *Gitlab { + return NewGitlabCert(baseUrl, apiPath, token, *skipCertVerify) +} + +func NewGitlabCert(baseUrl, apiPath, token string, skipVerify bool) *Gitlab { + config := &tls.Config{InsecureSkipVerify: skipVerify} + tr := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: config, + } + client := &http.Client{Transport: tr} + + return &Gitlab{ + BaseUrl: baseUrl, + ApiPath: apiPath, + Token: token, + Client: client, + } +} + +func (g *Gitlab) ResourceUrl(url string, params map[string]string) string { + + if params != nil { + for key, val := range params { + url = strings.Replace(url, key, encodeParameter(val), -1) + } + } + + url = g.BaseUrl + g.ApiPath + url + if !g.Bearer { + url = url + "?private_token=" + g.Token + } + return url +} + +func (g *Gitlab) buildAndExecRequest(method, url string, body []byte) ([]byte, error) { + + var req *http.Request + var err error + + if body != nil { + reader := bytes.NewReader(body) + req, err = http.NewRequest(method, url, reader) + } else { + req, err = http.NewRequest(method, url, nil) + } + if err != nil { + panic("Error while building gitlab request") + } + + if g.Bearer { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", g.Token)) + } + + resp, err := g.Client.Do(req) + if err != nil { + return nil, fmt.Errorf("Client.Do error: %q", err) + } + defer resp.Body.Close() + contents, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Printf("%s", err) + } + + if resp.StatusCode >= 400 { + err = fmt.Errorf("*Gitlab.buildAndExecRequest failed: <%d> %s", resp.StatusCode, req.URL) + } + + return contents, err +} + +func (g *Gitlab) ResourceUrlQuery(u string, params, query map[string]string) string { + if params != nil { + for key, val := range params { + u = strings.Replace(u, key, encodeParameter(val), -1) + } + } + + query_params := url.Values{} + if !g.Bearer { + query_params.Add("private_token", g.Token) + } + + if query != nil { + for key, val := range query { + query_params.Set(key, val) + } + } + + u = g.BaseUrl + g.ApiPath + u + "?" + query_params.Encode() + return u + +} + +func (g *Gitlab) ResourceUrlRaw(u string, params map[string]string) (string, string) { + + if params != nil { + for key, val := range params { + u = strings.Replace(u, key, encodeParameter(val), -1) + } + } + + path := u + u = g.BaseUrl + g.ApiPath + path + if !g.Bearer { + u = u + "?private_token=" + g.Token + } + + p, err := url.Parse(u) + if err != nil { + return u, "" + } + opaque := "//" + p.Host + p.Path + return u, opaque +} + +func (g *Gitlab) buildAndExecRequestRaw(method, url, opaque string, body []byte) ([]byte, error) { + + var req *http.Request + var err error + + if body != nil { + reader := bytes.NewReader(body) + req, err = http.NewRequest(method, url, reader) + } else { + req, err = http.NewRequest(method, url, nil) + } + if err != nil { + panic("Error while building gitlab request") + } + + if g.Bearer { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", g.Token)) + } + + if len(opaque) > 0 { + req.URL.Opaque = opaque + } + + resp, err := g.Client.Do(req) + if err != nil { + return nil, fmt.Errorf("Client.Do error: %q", err) + } + defer resp.Body.Close() + contents, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Printf("%s", err) + } + + if resp.StatusCode >= 400 { + err = fmt.Errorf("*Gitlab.buildAndExecRequestRaw failed: <%d> %s", resp.StatusCode, req.URL) + } + + return contents, err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/gitlab_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/gitlab_test.go new file mode 100644 index 000000000..f4088e457 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/gitlab_test.go @@ -0,0 +1,13 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestResourceUrl(t *testing.T) { + gitlab := NewGitlab("http://base_url/", "api_path", "token") + + assert.Equal(t, gitlab.ResourceUrl(projects_url, nil), "http://base_url/api_path/projects?private_token=token") + assert.Equal(t, gitlab.ResourceUrl(project_url, map[string]string{":id": "123"}), "http://base_url/api_path/projects/123?private_token=token") +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/helper_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/helper_test.go new file mode 100644 index 000000000..2bac5df5e --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/helper_test.go @@ -0,0 +1,16 @@ +package gogitlab + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" +) + +func Stub(filename string) (*httptest.Server, *Gitlab) { + stub, _ := ioutil.ReadFile(filename) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(stub)) + })) + gitlab := NewGitlab(ts.URL, "", "") + return ts, gitlab +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hook_payload.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hook_payload.go new file mode 100644 index 000000000..8bb7e9add --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hook_payload.go @@ -0,0 +1,154 @@ +package gogitlab + +import ( + "encoding/json" + "fmt" + "strings" +) + +type HookObjAttr struct { + Id int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + AssigneeId int `json:"assignee_id,omitempty"` + AuthorId int `json:"author_id,omitempty"` + ProjectId int `json:"project_id,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + Position int `json:"position,omitempty"` + BranchName string `json:"branch_name,omitempty"` + Description string `json:"description,omitempty"` + MilestoneId int `json:"milestone_id,omitempty"` + State string `json:"state,omitempty"` + IId int `json:"iid,omitempty"` + TargetBranch string `json:"target_branch,omitempty"` + SourceBranch string `json:"source_branch,omitempty"` + SourceProjectId int `json:"source_project_id,omitempty"` + StCommits string `json:"st_commits,omitempty"` + StDiffs string `json:"st_diffs,omitempty"` + MergeStatus string `json:"merge_status,omitempty"` + TargetProjectId int `json:"target_project_id,omitempty"` + Source *hProject `json:"source,omitempty"` + Target *hProject `json:"target,omitempty"` + LastCommit *hCommit `json:"last_commit,omitempty"` +} + +type hProject struct { + Name string `json:"name"` + SshUrl string `json:"ssh_url"` + HttpUrl string `json:"http_url"` + VisibilityLevel int `json:"visibility_level"` + Namespace string `json:"namespace"` +} + +type hRepository struct { + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` + Description string `json:"description,omitempty"` + Homepage string `json:"homepage,omitempty"` + GitHttpUrl string `json:"git_http_url,omitempty"` + GitSshUrl string `json:"git_ssh_url,omitempty"` + VisibilityLevel int `json:"visibility_level,omitempty"` +} + +type hCommit struct { + Id string `json:"id,omitempty"` + Message string `json:"message,omitempty"` + Timestamp string `json:"timestamp,omitempty"` + URL string `json:"url,omitempty"` + Author *Person `json:"author,omitempty"` +} + +type HookPayload struct { + Before string `json:"before,omitempty"` + After string `json:"after,omitempty"` + Ref string `json:"ref,omitempty"` + UserId int `json:"user_id,omitempty"` + UserName string `json:"user_name,omitempty"` + ProjectId int `json:"project_id,omitempty"` + Repository *hRepository `json:"repository,omitempty"` + Commits []hCommit `json:"commits,omitempty"` + TotalCommitsCount int `json:"total_commits_count,omitempty"` + ObjectKind string `json:"object_kind,omitempty"` + ObjectAttributes *HookObjAttr `json:"object_attributes,omitempty"` +} + +// ParseHook parses hook payload from GitLab +func ParseHook(payload []byte) (*HookPayload, error) { + hp := HookPayload{} + if err := json.Unmarshal(payload, &hp); err != nil { + return nil, err + } + + // Basic sanity check + switch { + case len(hp.ObjectKind) == 0: + // Assume this is a post-receive within repository + if len(hp.After) == 0 { + return nil, fmt.Errorf("Invalid hook received, commit hash not found.") + } + case hp.ObjectKind == "push": + if hp.Repository == nil { + return nil, fmt.Errorf("Invalid push hook received, attributes not found") + } + case hp.ObjectKind == "tag_push": + if hp.Repository == nil { + return nil, fmt.Errorf("Invalid tag push hook received, attributes not found") + } + case hp.ObjectKind == "issue": + fallthrough + case hp.ObjectKind == "merge_request": + if hp.ObjectAttributes == nil { + return nil, fmt.Errorf("Invalid hook received, attributes not found.") + } + default: + return nil, fmt.Errorf("Invalid hook received, payload format not recognized.") + } + + return &hp, nil +} + +// Type return current event type +// This function returns "unknown" type if event not supported +func (h *HookPayload) Type() string { + switch { + case strings.HasPrefix(h.Ref, "refs/heads/") && len(h.After) == 0: + return "branch_deleted" + case strings.HasPrefix(h.Ref, "refs/heads/") && len(h.Before) == 0: + return "branch" + case strings.HasPrefix(h.Ref, "refs/heads/"): + return "commit" + case strings.HasPrefix(h.Ref, "refs/tags/") && len(h.After) == 0: + return "tag_deleted" + case strings.HasPrefix(h.Ref, "refs/tags/"): + return "tag" + case h.ObjectKind == "issue": + return "issue" + case h.ObjectKind == "merge_request": + return "merge_request" + default: + return "unknown" + } +} + +// Tag returns current tag for push event hook payload +// This function returns empty string for any other events +func (h *HookPayload) Tag() string { + return strings.TrimPrefix(h.Ref, "refs/tags/") +} + +// Branch returns current branch for push event hook payload +// This function returns empty string for any other events +func (h *HookPayload) Branch() string { + return strings.TrimPrefix(h.Ref, "refs/heads/") +} + +// Head returns the latest changeset for push event hook payload +func (h *HookPayload) Head() hCommit { + c := hCommit{} + for _, cm := range h.Commits { + if h.After == cm.Id { + return cm + } + } + return c +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hook_payload_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hook_payload_test.go new file mode 100644 index 000000000..483d1bbae --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hook_payload_test.go @@ -0,0 +1,45 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "io/ioutil" + "testing" +) + +func TestParsePushHook(t *testing.T) { + stub, _ := ioutil.ReadFile("stubs/hook_payloads/push.json") + p, err := ParseHook([]byte(stub)) + + assert.Equal(t, err, nil) + assert.Equal(t, p.ObjectKind, "push") + assert.IsType(t, new(HookPayload), p) + assert.Equal(t, p.After, "da1560886d4f094c3e6c9ef40349f7d38b5d27d7") + assert.Equal(t, p.Repository.URL, "git@example.com:mike/diasporadiaspora.git") + assert.Equal(t, p.Repository.GitHttpUrl, "http://example.com/mike/diaspora.git") + assert.Equal(t, p.Repository.GitSshUrl, "git@example.com:mike/diaspora.git") + assert.Equal(t, p.Repository.VisibilityLevel, 0) + assert.Equal(t, len(p.Commits), 2) + assert.Equal(t, p.Commits[0].Author.Email, "jordi@softcatala.org") + assert.Equal(t, p.Commits[1].Id, "da1560886d4f094c3e6c9ef40349f7d38b5d27d7") + assert.Equal(t, p.Branch(), "master") + assert.Equal(t, p.Head().Message, "fixed readme") +} + +func TestParseIssueHook(t *testing.T) { + stub, _ := ioutil.ReadFile("stubs/hook_payloads/issue.json") + p, err := ParseHook([]byte(stub)) + + assert.Equal(t, err, nil) + assert.Equal(t, p.ObjectKind, "issue") + assert.Equal(t, p.ObjectAttributes.Id, 301) +} + +func TestParseMergeRequestHook(t *testing.T) { + stub, _ := ioutil.ReadFile("stubs/hook_payloads/merge_request.json") + p, err := ParseHook([]byte(stub)) + + assert.Equal(t, err, nil) + assert.Equal(t, p.ObjectKind, "merge_request") + assert.Equal(t, p.ObjectAttributes.TargetBranch, "master") + assert.Equal(t, p.ObjectAttributes.SourceProjectId, p.ObjectAttributes.TargetProjectId) +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hooks.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hooks.go new file mode 100644 index 000000000..9dd0fe4bb --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hooks.go @@ -0,0 +1,183 @@ +package gogitlab + +import ( + "encoding/json" + "net/url" +) + +const ( + project_url_hooks = "/projects/:id/hooks" // Get list of project hooks + project_url_hook = "/projects/:id/hooks/:hook_id" // Get single project hook +) + +type Hook struct { + Id int `json:"id,omitempty"` + Url string `json:"url,omitempty"` + CreatedAtRaw string `json:"created_at,omitempty"` +} + +/* +Get list of project hooks. + + GET /projects/:id/hooks + +Parameters: + + id The ID of a project + +*/ +func (g *Gitlab) ProjectHooks(id string) ([]*Hook, error) { + + url, opaque := g.ResourceUrlRaw(project_url_hooks, map[string]string{":id": id}) + + var err error + var hooks []*Hook + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err != nil { + return hooks, err + } + + err = json.Unmarshal(contents, &hooks) + + return hooks, err +} + +/* +Get single project hook. + + GET /projects/:id/hooks/:hook_id + +Parameters: + + id The ID of a project + hook_id The ID of a hook + +*/ +func (g *Gitlab) ProjectHook(id, hook_id string) (*Hook, error) { + + url, opaque := g.ResourceUrlRaw(project_url_hook, map[string]string{ + ":id": id, + ":hook_id": hook_id, + }) + + var err error + hook := new(Hook) + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err != nil { + return hook, err + } + + err = json.Unmarshal(contents, &hook) + + return hook, err +} + +/* +Add new project hook. + + POST /projects/:id/hooks + +Parameters: + + id The ID or NAMESPACE/PROJECT_NAME of a project + hook_url The hook URL + push_events Trigger hook on push events + issues_events Trigger hook on issues events + merge_requests_events Trigger hook on merge_requests events + +*/ +func (g *Gitlab) AddProjectHook(id, hook_url string, push_events, issues_events, merge_requests_events bool) error { + + url, opaque := g.ResourceUrlRaw(project_url_hooks, map[string]string{":id": id}) + + var err error + + body := buildHookQuery(hook_url, push_events, issues_events, merge_requests_events) + _, err = g.buildAndExecRequestRaw("POST", url, opaque, []byte(body)) + + return err +} + +/* +Edit existing project hook. + + PUT /projects/:id/hooks/:hook_id + +Parameters: + + id The ID or NAMESPACE/PROJECT_NAME of a project + hook_id The ID of a project hook + hook_url The hook URL + push_events Trigger hook on push events + issues_events Trigger hook on issues events + merge_requests_events Trigger hook on merge_requests events + +*/ +func (g *Gitlab) EditProjectHook(id, hook_id, hook_url string, push_events, issues_events, merge_requests_events bool) error { + + url, opaque := g.ResourceUrlRaw(project_url_hook, map[string]string{ + ":id": id, + ":hook_id": hook_id, + }) + + var err error + + body := buildHookQuery(hook_url, push_events, issues_events, merge_requests_events) + _, err = g.buildAndExecRequestRaw("PUT", url, opaque, []byte(body)) + + return err +} + +/* +Remove hook from project. + + DELETE /projects/:id/hooks/:hook_id + +Parameters: + + id The ID or NAMESPACE/PROJECT_NAME of a project + hook_id The ID of hook to delete + +*/ +func (g *Gitlab) RemoveProjectHook(id, hook_id string) error { + + url, opaque := g.ResourceUrlRaw(project_url_hook, map[string]string{ + ":id": id, + ":hook_id": hook_id, + }) + + var err error + + _, err = g.buildAndExecRequestRaw("DELETE", url, opaque, nil) + + return err +} + +/* +Build HTTP query to add or edit hook +*/ +func buildHookQuery(hook_url string, push_events, issues_events, merge_requests_events bool) string { + + v := url.Values{} + v.Set("url", hook_url) + + if push_events { + v.Set("push_events", "true") + } else { + v.Set("push_events", "false") + } + if issues_events { + v.Set("issues_events", "true") + } else { + v.Set("issues_events", "false") + } + if merge_requests_events { + v.Set("merge_requests_events", "true") + } else { + v.Set("merge_requests_events", "false") + } + + return v.Encode() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hooks_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hooks_test.go new file mode 100644 index 000000000..18ae7fc1f --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/hooks_test.go @@ -0,0 +1,16 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestHook(t *testing.T) { + ts, gitlab := Stub("stubs/hooks/show.json") + hook, err := gitlab.ProjectHook("1", "2") + + assert.Equal(t, err, nil) + assert.IsType(t, new(Hook), hook) + assert.Equal(t, hook.Url, "http://example.com/hook") + defer ts.Close() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/projects.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/projects.go new file mode 100644 index 000000000..9de030ec0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/projects.go @@ -0,0 +1,245 @@ +package gogitlab + +import ( + "encoding/json" + "strconv" + "strings" +) + +const ( + projects_url = "/projects" // Get a list of projects owned by the authenticated user + projects_search_url = "/projects/search/:query" // Search for projects by name + project_url = "/projects/:id" // Get a specific project, identified by project ID or NAME + project_url_events = "/projects/:id/events" // Get project events + project_url_branches = "/projects/:id/repository/branches" // Lists all branches of a project + project_url_members = "/projects/:id/members" // List project team members + project_url_member = "/projects/:id/members/:user_id" // Get project team member + project_url_merge_requests = "/projects/:id/merge_requests" // List all merge requests of a project +) + +type Member struct { + Id int + Username string + Email string + Name string + State string + CreatedAt string `json:"created_at,omitempty"` + // AccessLevel int +} + +type Namespace struct { + Id int + Name string + Path string + Description string + Owner_Id int + Created_At string + Updated_At string +} + +type ProjectAccess struct { + AccessLevel int `json:"access_level,omitempty"` + NotificationLevel int `json:"notification_level,omitempty"` +} + +type GroupAccess struct { + AccessLevel int `json:"access_level,omitempty"` + NotificationLevel int `json:"notification_level,omitempty"` +} + +type Permissions struct { + ProjectAccess *ProjectAccess `json:"project_access,omitempty"` + GroupAccess *GroupAccess `json:"group_access,omitempty"` +} + +// A gitlab project +type Project struct { + Id int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + DefaultBranch string `json:"default_branch,omitempty"` + Owner *Member `json:"owner,omitempty"` + Public bool `json:"public,omitempty"` + Path string `json:"path,omitempty"` + PathWithNamespace string `json:"path_with_namespace,omitempty"` + IssuesEnabled bool `json:"issues_enabled,omitempty"` + MergeRequestsEnabled bool `json:"merge_requests_enabled,omitempty"` + WallEnabled bool `json:"wall_enabled,omitempty"` + WikiEnabled bool `json:"wiki_enabled,omitempty"` + CreatedAtRaw string `json:"created_at,omitempty"` + Namespace *Namespace `json:"namespace,omitempty"` + SshRepoUrl string `json:"ssh_url_to_repo"` + HttpRepoUrl string `json:"http_url_to_repo"` + Url string `json:"web_url"` + Permissions *Permissions `json:"permissions,omitempty"` +} + +type MergeRequest struct { + Id int `json:"id,omitempty"` + // IId + TargetBranch string `json:"target_branch,omitempty"` + SourceBranch string `json:"source_branch,omitempty"` + ProjectId int `json:"project_id,omitempty"` + Title string `json:"title,omitempty"` + State string `json:"state,omitempty"` + Upvotes int `json:"upvotes,omitempty"` + Downvotes int `json:"downvotes,omitempty"` + Author *Member `json:"author,omitempty"` + Assignee *Member `json:"assignee,omitempty"` + Description string `json:"description,omitempty"` +} + +/* +Get a list of all projects owned by the authenticated user. +*/ +func (g *Gitlab) AllProjects() ([]*Project, error) { + var per_page = 100 + var projects []*Project + + for i := 1; true; i++ { + contents, err := g.Projects(i, per_page) + if err != nil { + return projects, err + } + + for _, value := range contents { + projects = append(projects, value) + } + + if len(projects) == 0 { + break + } + + if len(projects)/i < per_page { + break + } + } + + return projects, nil +} + +/* +Get a list of projects owned by the authenticated user. +*/ +func (g *Gitlab) Projects(page int, per_page int) ([]*Project, error) { + + url := g.ResourceUrlQuery(projects_url, nil, map[string]string{"page": strconv.Itoa(page), "per_page": strconv.Itoa(per_page)}) + + var projects []*Project + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &projects) + } + + return projects, err +} + +/* +Get a specific project, identified by project ID or NAME, +which is owned by the authentication user. +Namespaced project may be retrieved by specifying the namespace +and its project name like this: + + `namespace%2Fproject-name` + +*/ +func (g *Gitlab) Project(id string) (*Project, error) { + + url, opaque := g.ResourceUrlRaw(project_url, map[string]string{":id": id}) + + var project *Project + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &project) + } + + return project, err +} + +/* +Lists all branches of a project. +*/ +func (g *Gitlab) ProjectBranches(id string) ([]*Branch, error) { + + url, opaque := g.ResourceUrlRaw(project_url_branches, map[string]string{":id": id}) + + var branches []*Branch + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &branches) + } + + return branches, err +} + +func (g *Gitlab) ProjectMembers(id string) ([]*Member, error) { + url, opaque := g.ResourceUrlRaw(project_url_members, map[string]string{":id": id}) + + var members []*Member + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &members) + } + + return members, err +} + +/* +Lists all merge requests of a project. +*/ +func (g *Gitlab) ProjectMergeRequests(id string, page int, per_page int, state string) ([]*MergeRequest, error) { + par := map[string]string{":id": id} + qry := map[string]string{ + "state": state, + "page": strconv.Itoa(page), + "per_page": strconv.Itoa(per_page)} + url := g.ResourceUrlQuery(project_url_merge_requests, par, qry) + + var mr []*MergeRequest + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &mr) + } + + return mr, err +} + +/* +Get single project id. + + GET /projects/search/:query + +Parameters: + + namespace The namespace of a project + name The id of a project + +*/ +func (g *Gitlab) SearchProjectId(namespace string, name string) (id int, err error) { + + url, opaque := g.ResourceUrlRaw(projects_search_url, map[string]string{ + ":query": strings.ToLower(name), + }) + + var projects []*Project + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &projects) + } else { + return id, err + } + + for _, project := range projects { + if project.Namespace.Name == namespace { + id = project.Id + } + } + + return id, err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/projects_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/projects_test.go new file mode 100644 index 000000000..56511ce5e --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/projects_test.go @@ -0,0 +1,70 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestALlProjects(t *testing.T) { + ts, gitlab := Stub("stubs/projects/index.json") + projects, err := gitlab.AllProjects() + + assert.Equal(t, err, nil) + assert.Equal(t, len(projects), 2) + defer ts.Close() +} + +func TestProjects(t *testing.T) { + ts, gitlab := Stub("stubs/projects/index.json") + projects, err := gitlab.Projects(1, 100) + + assert.Equal(t, err, nil) + assert.Equal(t, len(projects), 2) + defer ts.Close() +} + +func TestProject(t *testing.T) { + ts, gitlab := Stub("stubs/projects/show.json") + project, err := gitlab.Project("1") + + assert.Equal(t, err, nil) + assert.IsType(t, new(Project), project) + assert.Equal(t, project.SshRepoUrl, "git@example.com:diaspora/diaspora-project-site.git") + assert.Equal(t, project.HttpRepoUrl, "http://example.com/diaspora/diaspora-project-site.git") + defer ts.Close() +} + +func TestProjectBranches(t *testing.T) { + ts, gitlab := Stub("stubs/projects/branches/index.json") + branches, err := gitlab.ProjectBranches("1") + + assert.Equal(t, err, nil) + assert.Equal(t, len(branches), 2) + defer ts.Close() +} + +func TestProjectMergeRequests(t *testing.T) { + ts, gitlab := Stub("stubs/projects/merge_requests/index.json") + defer ts.Close() + mr, err := gitlab.ProjectMergeRequests("1", 0, 30, "all") + + assert.Equal(t, err, nil) + assert.Equal(t, len(mr), 1) + + if len(mr) > 0 { + assert.Equal(t, mr[0].TargetBranch, "master") + assert.Equal(t, mr[0].SourceBranch, "test1") + } +} + +func TestSearchProjectId(t *testing.T) { + ts, gitlab := Stub("stubs/projects/index.json") + + namespace := "Brightbox" + name := "Puppet" + id, err := gitlab.SearchProjectId(namespace, name) + + assert.Equal(t, err, nil) + assert.Equal(t, id, 6) + defer ts.Close() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/public_keys.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/public_keys.go new file mode 100644 index 000000000..e3b7156b8 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/public_keys.go @@ -0,0 +1,69 @@ +package gogitlab + +import ( + "encoding/json" + "net/url" +) + +const ( + // ID + user_keys = "/user/keys" // Get current user keys + user_key = "/user/keys/:id" // Get user key by id + custom_user_keys = "/user/:id/keys" // Create key for user with :id +) + +type PublicKey struct { + Id int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + Key string `json:"key,omitempty"` + CreatedAtRaw string `json:"created_at,omitempty"` +} + +func (g *Gitlab) UserKeys() ([]*PublicKey, error) { + url := g.ResourceUrl(user_keys, nil) + var keys []*PublicKey + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &keys) + } + return keys, err +} + +func (g *Gitlab) UserKey(id string) (*PublicKey, error) { + url := g.ResourceUrl(user_key, map[string]string{":id": id}) + var key *PublicKey + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &key) + } + return key, err +} + +func (g *Gitlab) AddKey(title, key string) error { + path := g.ResourceUrl(user_keys, nil) + var err error + v := url.Values{} + v.Set("title", title) + v.Set("key", key) + body := v.Encode() + _, err = g.buildAndExecRequest("POST", path, []byte(body)) + return err +} + +func (g *Gitlab) AddUserKey(id, title, key string) error { + path := g.ResourceUrl(user_keys, map[string]string{":id": id}) + var err error + v := url.Values{} + v.Set("title", title) + v.Set("key", key) + body := v.Encode() + _, err = g.buildAndExecRequest("POST", path, []byte(body)) + return err +} + +func (g *Gitlab) DeleteKey(id string) error { + url := g.ResourceUrl(user_key, map[string]string{":id": id}) + var err error + _, err = g.buildAndExecRequest("DELETE", url, nil) + return err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/public_keys_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/public_keys_test.go new file mode 100644 index 000000000..d3be64a1f --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/public_keys_test.go @@ -0,0 +1,50 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetUserKeys(t *testing.T) { + ts, gitlab := Stub("stubs/public_keys/index.json") + keys, err := gitlab.UserKeys() + + assert.Equal(t, err, nil) + assert.Equal(t, len(keys), 2) + defer ts.Close() +} + +func TestGetUserKey(t *testing.T) { + ts, gitlab := Stub("stubs/public_keys/show.json") + key, err := gitlab.UserKey("1") + + assert.Equal(t, err, nil) + assert.IsType(t, new(PublicKey), key) + assert.Equal(t, key.Title, "Public key") + assert.Equal(t, key.Key, "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=") + defer ts.Close() +} + +func TestAddKey(t *testing.T) { + ts, gitlab := Stub("") + err := gitlab.AddKey("Public key", "stubbed key") + + assert.Equal(t, err, nil) + defer ts.Close() +} + +func TestAddUserKey(t *testing.T) { + ts, gitlab := Stub("") + err := gitlab.AddUserKey("1", "Public key", "stubbed key") + + assert.Equal(t, err, nil) + defer ts.Close() +} + +func TestDeleteKey(t *testing.T) { + ts, gitlab := Stub("") + err := gitlab.DeleteKey("1") + + assert.Equal(t, err, nil) + defer ts.Close() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/repositories.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/repositories.go new file mode 100644 index 000000000..694100e0e --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/repositories.go @@ -0,0 +1,246 @@ +package gogitlab + +import ( + "encoding/json" + "net/url" + "time" +) + +const ( + repo_url_branches = "/projects/:id/repository/branches" // List repository branches + repo_url_branch = "/projects/:id/repository/branches/:branch" // Get a specific branch of a project. + repo_url_tags = "/projects/:id/repository/tags" // List project repository tags + repo_url_commits = "/projects/:id/repository/commits" // List repository commits + repo_url_tree = "/projects/:id/repository/tree" // List repository tree + repo_url_raw_file = "/projects/:id/repository/blobs/:sha" // Get raw file content for specific commit/branch +) + +type BranchCommit struct { + Id string `json:"id,omitempty"` + Tree string `json:"tree,omitempty"` + AuthoredDateRaw string `json:"authored_date,omitempty"` + CommittedDateRaw string `json:"committed_date,omitempty"` + Message string `json:"message,omitempty"` + Author *Person `json:"author,omitempty"` + Committer *Person `json:"committer,omitempty"` + /* + "parents": [ + {"id": "9b0c4b08e7890337fc8111e66f809c8bbec467a9"}, + {"id": "3ac634dca850cab70ab14b43ad6073d1e0a7827f"} + ] + */ +} + +type Branch struct { + Name string `json:"name,omitempty"` + Protected bool `json:"protected,omitempty"` + Commit *BranchCommit `json:"commit,omitempty"` +} + +type Tag struct { + Name string `json:"name,omitempty"` + Protected bool `json:"protected,omitempty"` + Commit *BranchCommit `json:"commit,omitempty"` +} + +type Commit struct { + Id string + Short_Id string + Title string + Author_Name string + Author_Email string + Created_At string + CreatedAt time.Time +} + +type File struct { + Id string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Mode string `json:"mode,omitempty"` + + Children []*File +} + +/* +Get a list of repository branches from a project, sorted by name alphabetically. + + GET /projects/:id/repository/branches + +Parameters: + + id The ID of a project + +Usage: + + branches, err := gitlab.RepoBranches("your_projet_id") + if err != nil { + fmt.Println(err.Error()) + } + for _, branch := range branches { + fmt.Printf("%+v\n", branch) + } +*/ +func (g *Gitlab) RepoBranches(id string) ([]*Branch, error) { + + url, opaque := g.ResourceUrlRaw(repo_url_branches, map[string]string{":id": id}) + + var branches []*Branch + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &branches) + } + + return branches, err +} + +/* +Get a single project repository branch. + + GET /projects/:id/repository/branches/:branch + +Parameters: + + id The ID of a project + branch The name of the branch + +*/ +func (g *Gitlab) RepoBranch(id, refName string) (*Branch, error) { + + url, opaque := g.ResourceUrlRaw(repo_url_branch, map[string]string{ + ":id": id, + ":branch": refName, + }) + + branch := new(Branch) + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &branch) + } + return branch, err +} + +/* +Get a list of repository tags from a project, sorted by name in reverse alphabetical order. + + GET /projects/:id/repository/tags + +Parameters: + + id The ID of a project + +Usage: + + tags, err := gitlab.RepoTags("your_projet_id") + if err != nil { + fmt.Println(err.Error()) + } + for _, tag := range tags { + fmt.Printf("%+v\n", tag) + } +*/ +func (g *Gitlab) RepoTags(id string) ([]*Tag, error) { + + url, opaque := g.ResourceUrlRaw(repo_url_tags, map[string]string{":id": id}) + + var tags []*Tag + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &tags) + } + + return tags, err +} + +/* +Get a list of repository commits in a project. + + GET /projects/:id/repository/commits + +Parameters: + + id The ID of a project + refName The name of a repository branch or tag or if not given the default branch + +Usage: + + commits, err := gitlab.RepoCommits("your_projet_id") + if err != nil { + fmt.Println(err.Error()) + } + for _, commit := range commits { + fmt.Printf("%+v\n", commit) + } +*/ +func (g *Gitlab) RepoCommits(id string) ([]*Commit, error) { + + url, opaque := g.ResourceUrlRaw(repo_url_commits, map[string]string{":id": id}) + + var commits []*Commit + + contents, err := g.buildAndExecRequestRaw("GET", url, opaque, nil) + if err == nil { + err = json.Unmarshal(contents, &commits) + if err == nil { + for _, commit := range commits { + t, _ := time.Parse(dateLayout, commit.Created_At) + commit.CreatedAt = t + } + } + } + + return commits, err +} + +/* +Get Raw file content +*/ +func (g *Gitlab) RepoRawFile(id, sha, filepath string) ([]byte, error) { + url_ := g.ResourceUrlQuery(repo_url_raw_file, map[string]string{ + ":id": id, + ":sha": sha, + }, map[string]string{ + "filepath": filepath, + }) + + p, err := url.Parse(url_) + if err != nil { + return nil, err + } + + opaque := "//" + p.Host + p.Path + contents, err := g.buildAndExecRequestRaw("GET", url_, opaque, nil) + + return contents, err +} + +/* +Get Raw file content +*/ +func (g *Gitlab) RepoTree(id, ref, path string) ([]*File, error) { + + url := g.ResourceUrlQuery(repo_url_tree, map[string]string{ + ":id": id, + }, map[string]string{ + "ref": ref, + "path": path, + }) + + var files []*File + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &files) + } + + for _, f := range files { + if f.Type == "tree" { + f.Children, err = g.RepoTree(id, ref, path+"/"+f.Name) + } + } + + return files, err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/repositories_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/repositories_test.go new file mode 100644 index 000000000..f009fb23f --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/repositories_test.go @@ -0,0 +1,43 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRepoBranches(t *testing.T) { + ts, gitlab := Stub("stubs/branches/index.json") + branches, err := gitlab.RepoBranches("1") + + assert.Equal(t, err, nil) + assert.Equal(t, len(branches), 1) + defer ts.Close() +} + +func TestRepoBranch(t *testing.T) { + ts, gitlab := Stub("stubs/branches/show.json") + branch, err := gitlab.RepoBranch("1", "master") + + assert.Equal(t, err, nil) + assert.IsType(t, new(Branch), branch) + assert.Equal(t, branch.Name, "master") + defer ts.Close() +} + +func TestRepoTags(t *testing.T) { + ts, gitlab := Stub("stubs/tags/index.json") + tags, err := gitlab.RepoTags("1") + + assert.Equal(t, err, nil) + assert.Equal(t, len(tags), 1) + defer ts.Close() +} + +func TestRepoCommits(t *testing.T) { + ts, gitlab := Stub("stubs/commits/index.json") + commits, err := gitlab.RepoCommits("1") + + assert.Equal(t, err, nil) + assert.Equal(t, len(commits), 2) + defer ts.Close() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/session.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/session.go new file mode 100644 index 000000000..5626ade26 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/session.go @@ -0,0 +1,54 @@ +package gogitlab + +import ( + "encoding/json" + "net/url" +) + +const ( + session_path = "/session" +) + +type Session struct { + Id int `json:"id"` + UserName string `json:"username"` + Name string `json:"name"` + Blocked bool `json:"blocked"` + State string `json:"state"` + AvatarURL string `json:"avatar_url",omitempty` + IsAdmin bool `json:"is_admin"` + Bio string `json:"bio",omitempty` + Email string `json:"email"` + ThemeId int `json:"theme_id",omitempty` + ColorSchemeId int `json:"color_scheme_id",omitempty` + ExternUid string `json:"extern_uid",omitempty` + Provider string `json:"provider",omitempty` + CanCreateGroup bool `json:"can_create_group"` + CanCreateProject bool `json:"can_create_project"` + Skype string `json:"skype",omitempty` + Twitter string `json:"twitter",omitempty` + LinkedIn string `json:"linkedin",omitempty` + WebsiteURL string `json:"website_url",omitempty` + PrivateToken string `json:"private_token"` +} + +func (g *Gitlab) GetSession(email string, password string) (*Session, error) { + session_url := g.ResourceUrl(session_path, map[string]string{}) + + var session *Session + + v := url.Values{} + v.Set("email", email) + v.Set("password", password) + + body := v.Encode() + + contents, err := g.buildAndExecRequest("POST", session_url, []byte(body)) + if err != nil { + return session, err + } + + err = json.Unmarshal(contents, &session) + + return session, err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/session_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/session_test.go new file mode 100644 index 000000000..28665563b --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/session_test.go @@ -0,0 +1,33 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetSesison(t *testing.T) { + ts, gitlab := Stub("stubs/session/index.json") + session, err := gitlab.GetSession("john@example.com", "samplepassword") + + assert.Equal(t, err, nil) + assert.Equal(t, session.Id, 1) + assert.Equal(t, session.UserName, "john_smith") + assert.Equal(t, session.Name, "John Smith") + assert.Equal(t, session.State, "active") + assert.Equal(t, session.AvatarURL, "http://someurl.com/avatar.png") + assert.Equal(t, session.IsAdmin, false) + assert.Equal(t, session.Bio, "somebio") + assert.Equal(t, session.Skype, "someskype") + assert.Equal(t, session.LinkedIn, "somelinkedin") + assert.Equal(t, session.Twitter, "sometwitter") + assert.Equal(t, session.WebsiteURL, "http://example.com") + assert.Equal(t, session.Email, "john@example.com") + assert.Equal(t, session.ThemeId, 1) + assert.Equal(t, session.ColorSchemeId, 1) + assert.Equal(t, session.ExternUid, "someuid") + assert.Equal(t, session.Provider, "github.com") + assert.Equal(t, session.CanCreateGroup, true) + assert.Equal(t, session.CanCreateProject, true) + assert.Equal(t, session.PrivateToken, "dd34asd13as") + defer ts.Close() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/branches/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/branches/index.json new file mode 100644 index 000000000..c3f72112b --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/branches/index.json @@ -0,0 +1,26 @@ +[ + { + "name": "master", + "commit": { + "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", + "parents": [ + { + "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8" + } + ], + "tree": "46e82de44b1061621357f24c05515327f2795a95", + "message": "add projects API", + "author": { + "name": "John Smith", + "email": "john@example.com" + }, + "committer": { + "name": "John Smith", + "email": "john@example.com" + }, + "authored_date": "2012-06-27T05:51:39-07:00", + "committed_date": "2012-06-28T03:44:20-07:00" + }, + "protected": true + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/branches/show.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/branches/show.json new file mode 100644 index 000000000..4bf5b39ef --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/branches/show.json @@ -0,0 +1,24 @@ +{ + "name": "master", + "commit": { + "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", + "parents": [ + { + "id": "4ad91d3c1144c406e50c7b33bae684bd6837faf8" + } + ], + "tree": "46e82de44b1061621357f24c05515327f2795a95", + "message": "add projects API", + "author": { + "name": "John Smith", + "email": "john@example.com" + }, + "committer": { + "name": "John Smith", + "email": "john@example.com" + }, + "authored_date": "2012-06-27T05:51:39-07:00", + "committed_date": "2012-06-28T03:44:20-07:00" + }, + "protected": true +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/commits/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/commits/index.json new file mode 100644 index 000000000..53eb0c558 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/commits/index.json @@ -0,0 +1,18 @@ +[ + { + "id": "ed899a2f4b50b4370feeea94676502b42383c746", + "short_id": "ed899a2f4b5", + "title": "Replace sanitize with escape once", + "author_name": "Dmitriy Zaporozhets", + "author_email": "dzaporozhets@sphereconsultinginc.com", + "created_at": "2012-09-20T11:50:22+03:00" + }, + { + "id": "6104942438c14ec7bd21c6cd5bd995272b3faff6", + "short_id": "6104942438c", + "title": "Sanitize for network graph", + "author_name": "randx", + "author_email": "dmitriy.zaporozhets@gmail.com", + "created_at": "2012-09-20T09:06:12+03:00" + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/issue.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/issue.json new file mode 100644 index 000000000..e0842c1c9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/issue.json @@ -0,0 +1,18 @@ +{ + "object_kind": "issue", + "object_attributes": { + "id": 301, + "title": "New API: create/update/delete file", + "assignee_id": 51, + "author_id": 51, + "project_id": 14, + "created_at": "2013-12-03T17:15:43Z", + "updated_at": "2013-12-03T17:15:43Z", + "position": 0, + "branch_name": null, + "description": "Create new API for manipulations with repository", + "milestone_id": null, + "state": "opened", + "iid": 23 + } +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/merge_request.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/merge_request.json new file mode 100644 index 000000000..490719e63 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/merge_request.json @@ -0,0 +1,22 @@ +{ + "object_kind": "merge_request", + "object_attributes": { + "id": 99, + "target_branch": "master", + "source_branch": "ms-viewport", + "source_project_id": 14, + "author_id": 51, + "assignee_id": 6, + "title": "MS-Viewport", + "created_at": "2013-12-03T17:23:34Z", + "updated_at": "2013-12-03T17:23:34Z", + "st_commits": null, + "st_diffs": null, + "milestone_id": null, + "state": "opened", + "merge_status": "unchecked", + "target_project_id": 14, + "iid": 1, + "description": "" + } +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/push.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/push.json new file mode 100644 index 000000000..02e7f6485 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hook_payloads/push.json @@ -0,0 +1,42 @@ +{ + "object_kind": "push", + "before": "95790bf891e76fee5e1747ab589903a6a1f80f22", + "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", + "ref": "refs/heads/master", + "user_id": 4, + "user_name": "John Smith", + "user_email": "john@example.com", + "project_id": 15, + "repository": { + "name": "Diaspora", + "url": "git@example.com:mike/diasporadiaspora.git", + "description": "", + "homepage": "http://example.com/mike/diaspora", + "git_http_url":"http://example.com/mike/diaspora.git", + "git_ssh_url":"git@example.com:mike/diaspora.git", + "visibility_level":0 + }, + "commits": [ + { + "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", + "message": "Update Catalan translation to e38cb41.", + "timestamp": "2011-12-12T14:27:31+02:00", + "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", + "author": { + "name": "Jordi Mallach", + "email": "jordi@softcatala.org" + } + }, + { + "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", + "message": "fixed readme", + "timestamp": "2012-01-03T23:36:29+02:00", + "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7", + "author": { + "name": "GitLab dev user", + "email": "gitlabdev@dv6700.(none)" + } + } + ], + "total_commits_count": 4 +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hooks/show.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hooks/show.json new file mode 100644 index 000000000..ce7f3aca2 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/hooks/show.json @@ -0,0 +1,9 @@ +{ + "id": 1, + "url": "http://example.com/hook", + "project_id": 3, + "push_events": "true", + "issues_events": "true", + "merge_requests_events": "true", + "created_at": "2012-10-12T17:04:47Z" +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/branches/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/branches/index.json new file mode 100644 index 000000000..0e62917a0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/branches/index.json @@ -0,0 +1,50 @@ +[ + { + "name": "async", + "commit": { + "id": "a2b702edecdf41f07b42653eb1abe30ce98b9fca", + "parents": [ + { + "id": "3f94fc7c85061973edc9906ae170cc269b07ca55" + } + ], + "tree": "c68537c6534a02cc2b176ca1549f4ffa190b58ee", + "message": "give caolan credit where it's due (up top)", + "author": { + "name": "Jeremy Ashkenas", + "email": "jashkenas@example.com" + }, + "committer": { + "name": "Jeremy Ashkenas", + "email": "jashkenas@example.com" + }, + "authored_date": "2010-12-08T21:28:50+00:00", + "committed_date": "2010-12-08T21:28:50+00:00" + }, + "protected": false + }, + { + "name": "gh-pages", + "commit": { + "id": "101c10a60019fe870d21868835f65c25d64968fc", + "parents": [ + { + "id": "9c15d2e26945a665131af5d7b6d30a06ba338aaa" + } + ], + "tree": "fb5cc9d45da3014b17a876ad539976a0fb9b352a", + "message": "Underscore.js 1.5.2", + "author": { + "name": "Jeremy Ashkenas", + "email": "jashkenas@example.com" + }, + "committer": { + "name": "Jeremy Ashkenas", + "email": "jashkenas@example.com" + }, + "authored_date": "2013-09-07T12: 58: 21+00: 00", + "committed_date": "2013-09-07T12: 58: 21+00: 00" + }, + "protected": false + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/index.json new file mode 100644 index 000000000..6528d6cc4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/index.json @@ -0,0 +1,72 @@ +[ + { + "id": 4, + "description": null, + "default_branch": "master", + "public": false, + "visibility_level": 0, + "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git", + "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", + "web_url": "http://example.com/diaspora/diaspora-client", + "owner": { + "id": 3, + "name": "Diaspora", + "created_at": "2013-09-30T13: 46: 02Z" + }, + "name": "Diaspora Client", + "name_with_namespace": "Diaspora / Diaspora Client", + "path": "diaspora-client", + "path_with_namespace": "diaspora/diaspora-client", + "issues_enabled": true, + "merge_requests_enabled": true, + "wall_enabled": false, + "wiki_enabled": true, + "snippets_enabled": false, + "created_at": "2013-09-30T13: 46: 02Z", + "last_activity_at": "2013-09-30T13: 46: 02Z", + "namespace": { + "created_at": "2013-09-30T13: 46: 02Z", + "description": "", + "id": 3, + "name": "Diaspora", + "owner_id": 1, + "path": "diaspora", + "updated_at": "2013-09-30T13: 46: 02Z" + } + }, + { + "id": 6, + "description": null, + "default_branch": "master", + "public": false, + "visibility_level": 0, + "ssh_url_to_repo": "git@example.com:brightbox/puppet.git", + "http_url_to_repo": "http://example.com/brightbox/puppet.git", + "web_url": "http://example.com/brightbox/puppet", + "owner": { + "id": 4, + "name": "Brightbox", + "created_at": "2013-09-30T13:46:02Z" + }, + "name": "Puppet", + "name_with_namespace": "Brightbox / Puppet", + "path": "puppet", + "path_with_namespace": "brightbox/puppet", + "issues_enabled": true, + "merge_requests_enabled": true, + "wall_enabled": false, + "wiki_enabled": true, + "snippets_enabled": false, + "created_at": "2013-09-30T13:46:02Z", + "last_activity_at": "2013-09-30T13:46:02Z", + "namespace": { + "created_at": "2013-09-30T13:46:02Z", + "description": "", + "id": 4, + "name": "Brightbox", + "owner_id": 1, + "path": "brightbox", + "updated_at": "2013-09-30T13:46:02Z" + } + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/merge_requests/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/merge_requests/index.json new file mode 100644 index 000000000..b9cbbe5a5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/merge_requests/index.json @@ -0,0 +1,30 @@ +[ + { + "id": 1, + "iid": 1, + "target_branch": "master", + "source_branch": "test1", + "project_id": 3, + "title": "test1", + "state": "opened", + "upvotes": 0, + "downvotes": 0, + "author": { + "id": 1, + "username": "admin", + "email": "admin@example.com", + "name": "Administrator", + "state": "active", + "created_at": "2012-04-29T08:46:00Z" + }, + "assignee": { + "id": 1, + "username": "admin", + "email": "admin@example.com", + "name": "Administrator", + "state": "active", + "created_at": "2012-04-29T08:46:00Z" + }, + "description":"fixed login page css paddings" + } +] diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/show.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/show.json new file mode 100644 index 000000000..cabb359ec --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/projects/show.json @@ -0,0 +1,45 @@ +{ + "id": 3, + "description": null, + "default_branch": "master", + "public": false, + "visibility_level": 0, + "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", + "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", + "web_url": "http://example.com/diaspora/diaspora-project-site", + "owner": { + "id": 3, + "name": "Diaspora", + "created_at": "2013-09-30T13: 46: 02Z" + }, + "name": "Diaspora Project Site", + "name_with_namespace": "Diaspora / Diaspora Project Site", + "path": "diaspora-project-site", + "path_with_namespace": "diaspora/diaspora-project-site", + "issues_enabled": true, + "merge_requests_enabled": true, + "wall_enabled": false, + "wiki_enabled": true, + "snippets_enabled": false, + "created_at": "2013-09-30T13: 46: 02Z", + "last_activity_at": "2013-09-30T13: 46: 02Z", + "namespace": { + "created_at": "2013-09-30T13: 46: 02Z", + "description": "", + "id": 3, + "name": "Diaspora", + "owner_id": 1, + "path": "diaspora", + "updated_at": "2013-09-30T13: 46: 02Z" + }, + "permissions": { + "project_access": { + "access_level": 10, + "notification_level": 3 + }, + "group_access": { + "access_level": 50, + "notification_level": 3 + } + } +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/public_keys/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/public_keys/index.json new file mode 100644 index 000000000..67a9f4795 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/public_keys/index.json @@ -0,0 +1,12 @@ +[ + { + "id": 1, + "title": "Public key", + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" + }, + { + "id": 3, + "title": "Another Public key", + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/public_keys/show.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/public_keys/show.json new file mode 100644 index 000000000..ef2868b36 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/public_keys/show.json @@ -0,0 +1,5 @@ +{ + "id": 1, + "title": "Public key", + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/session/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/session/index.json new file mode 100644 index 000000000..bf55d8bd0 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/session/index.json @@ -0,0 +1,23 @@ +{ + "id": 1, + "username": "john_smith", + "email": "john@example.com", + "name": "John Smith", + "avatar_url": "http://someurl.com/avatar.png", + "state": "active", + "created_at": "2012-05-23T08:00:58Z", + "bio": "somebio", + "skype": "someskype", + "linkedin": "somelinkedin", + "twitter": "sometwitter", + "website_url": "http://example.com", + "theme_id": 1, + "color_scheme_id": 1, + "extern_uid": "someuid", + "provider": "github.com", + "is_admin": false, + "can_create_group": true, + "can_create_team": true, + "can_create_project": true, + "private_token": "dd34asd13as" +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/tags/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/tags/index.json new file mode 100644 index 000000000..0e7474cbf --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/tags/index.json @@ -0,0 +1,22 @@ +[ + { + "name": "v1.0.0", + "commit": { + "id": "2695effb5807a22ff3d138d593fd856244e155e7", + "parents": [], + "tree": "38017f2f189336fe4497e9d230c5bb1bf873f08d", + "message": "Initial commit", + "author": { + "name": "John Smith", + "email": "john@example.com" + }, + "committer": { + "name": "Jack Smith", + "email": "jack@example.com" + }, + "authored_date": "2012-05-28T04:42:42-07:00", + "committed_date": "2012-05-28T04:42:42-07:00" + }, + "protected": null + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/current.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/current.json new file mode 100644 index 000000000..e39d69667 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/current.json @@ -0,0 +1,19 @@ +{ + "id": 1, + "username": "john_smith", + "email": "john@example.com", + "name": "John Smith", + "private_token": "dd34asd13as", + "state": "active", + "created_at": "2012-05-23T08:00:58Z", + "bio": null, + "skype": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "theme_id": 1, + "color_scheme_id": 2, + "is_admin": false, + "can_create_group": true, + "can_create_project": true +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/index.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/index.json new file mode 100644 index 000000000..5a14aa5d5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/index.json @@ -0,0 +1,41 @@ +[ + { + "id": 1, + "username": "john_smith", + "email": "john@example.com", + "name": "John Smith", + "state": "active", + "created_at": "2012-05-23T08:00:58Z", + "bio": null, + "skype": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "extern_uid": "john.smith", + "provider": "provider_name", + "theme_id": 1, + "color_scheme_id": 2, + "is_admin": false, + "can_create_group": true + }, + { + "id": 2, + "username": "jack_smith", + "email": "jack@example.com", + "name": "Jack Smith", + "state": "blocked", + "created_at": "2012-05-23T08:01:01Z", + "bio": null, + "skype": "", + "linkedin": "", + "twitter": "", + "website_url": "", + "extern_uid": "jack.smith", + "provider": "provider_name", + "theme_id": 1, + "color_scheme_id": 3, + "is_admin": false, + "can_create_group": true, + "can_create_project": true + } +] \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/show.json b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/show.json new file mode 100644 index 000000000..af1d2d1bb --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/stubs/users/show.json @@ -0,0 +1,15 @@ +{ + "id": 6, + "username": "plouc", + "email": "plouc@plouc.com", + "name": "Raphaël Benitte", + "bio": null, + "skype": "", + "linkedin": "", + "twitter": "", + "theme_id": 2, + "state": "active", + "created_at": "2001-01-01T00:00:00Z", + "extern_uid": "uid=plouc", + "provider": "ldap" +} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/users.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/users.go new file mode 100644 index 000000000..6c2c9460f --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/users.go @@ -0,0 +1,97 @@ +package gogitlab + +import ( + "encoding/json" + "strconv" +) + +const ( + users_url = "/users" // Get users list + user_url = "/users/:id" // Get a single user. + current_user_url = "/user" // Get current user +) + +type User struct { + Id int `json:"id,omitempty"` + Username string `json:"username,omitempty"` + Email string `json:"email,omitempty"` + AvatarUrl string `json:"avatar_url,omitempty"` + Name string `json:"name,omitempty"` + State string `json:"state,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + Bio string `json:"bio,omitempty"` + Skype string `json:"skype,omitempty"` + LinkedIn string `json:"linkedin,omitempty"` + Twitter string `json:"twitter,omitempty"` + ExternUid string `json:"extern_uid,omitempty"` + Provider string `json:"provider,omitempty"` + ThemeId int `json:"theme_id,omitempty"` + ColorSchemeId int `json:"color_scheme_id,color_scheme_id"` +} + +func (g *Gitlab) Users(page int, per_page int) ([]*User, error) { + + qry := map[string]string{ + "page": strconv.Itoa(page), + "per_page": strconv.Itoa(per_page)} + url := g.ResourceUrlQuery(users_url, nil, qry) + + var users []*User + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &users) + } + + return users, err +} + +/* +Get a single user. + + GET /users/:id + +Parameters: + + id The ID of a user + +Usage: + + user, err := gitlab.User("your_user_id") + if err != nil { + fmt.Println(err.Error()) + } + fmt.Printf("%+v\n", user) +*/ +func (g *Gitlab) User(id string) (*User, error) { + + url := g.ResourceUrl(user_url, map[string]string{":id": id}) + + user := new(User) + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &user) + } + + return user, err +} + +func (g *Gitlab) DeleteUser(id string) error { + url := g.ResourceUrl(user_url, map[string]string{":id": id}) + var err error + _, err = g.buildAndExecRequest("DELETE", url, nil) + return err +} + +func (g *Gitlab) CurrentUser() (User, error) { + url := g.ResourceUrl(current_user_url, nil) + var user User + + contents, err := g.buildAndExecRequest("GET", url, nil) + if err == nil { + err = json.Unmarshal(contents, &user) + } + + return user, err +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/users_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/users_test.go new file mode 100644 index 000000000..0102697a5 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/users_test.go @@ -0,0 +1,53 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestUsers(t *testing.T) { + ts, gitlab := Stub("stubs/users/index.json") + users, err := gitlab.Users(0, 100) + + assert.Equal(t, err, nil) + assert.Equal(t, len(users), 2) + defer ts.Close() +} + +func TestUser(t *testing.T) { + ts, gitlab := Stub("stubs/users/show.json") + user, err := gitlab.User("plouc") + + assert.Equal(t, err, nil) + assert.IsType(t, new(User), user) + assert.Equal(t, user.Id, 6) + assert.Equal(t, user.Username, "plouc") + assert.Equal(t, user.Name, "Raphaël Benitte") + assert.Equal(t, user.Bio, "") + assert.Equal(t, user.Skype, "") + assert.Equal(t, user.LinkedIn, "") + assert.Equal(t, user.Twitter, "") + assert.Equal(t, user.ThemeId, 2) + assert.Equal(t, user.State, "active") + assert.Equal(t, user.CreatedAt, "2001-01-01T00:00:00Z") + assert.Equal(t, user.ExternUid, "uid=plouc") + assert.Equal(t, user.Provider, "ldap") + defer ts.Close() +} + +func TestDeleteUser(t *testing.T) { + ts, gitlab := Stub("") + err := gitlab.DeleteUser("1") + + assert.Equal(t, err, nil) + defer ts.Close() +} + +func TestCurrentUser(t *testing.T) { + ts, gitlab := Stub("stubs/users/current.json") + user, err := gitlab.CurrentUser() + + assert.Equal(t, err, nil) + assert.Equal(t, user.Username, "john_smith") + defer ts.Close() +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/util.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/util.go new file mode 100644 index 000000000..8e47c681f --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/util.go @@ -0,0 +1,10 @@ +package gogitlab + +import ( + "net/url" + "strings" +) + +func encodeParameter(value string) string { + return strings.Replace(url.QueryEscape(value), "/", "%2F", 0) +} diff --git a/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/util_test.go b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/util_test.go new file mode 100644 index 000000000..fdaed9cd3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client/util_test.go @@ -0,0 +1,11 @@ +package gogitlab + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestParameterEncoding(t *testing.T) { + assert.Equal(t, encodeParameter("namespace/project"), "namespace%2Fproject") + assert.Equal(t, encodeParameter("14"), "14") +} diff --git a/Makefile b/Makefile index 713be80d6..f54edc7ad 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,6 @@ all: concat bindata build deps: go get github.com/jteeuwen/go-bindata/... - go get github.com/Bugagazavr/go-gitlab-client... test: go vet github.com/drone/drone/pkg/... diff --git a/pkg/remote/builtin/gitlab/gitlab.go b/pkg/remote/builtin/gitlab/gitlab.go index 4e5e4c5af..29920914f 100644 --- a/pkg/remote/builtin/gitlab/gitlab.go +++ b/pkg/remote/builtin/gitlab/gitlab.go @@ -8,7 +8,7 @@ import ( "strconv" "strings" - "github.com/Bugagazavr/go-gitlab-client" + "github.com/drone/drone/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client" "github.com/drone/drone/Godeps/_workspace/src/github.com/hashicorp/golang-lru" "github.com/drone/drone/pkg/config" "github.com/drone/drone/pkg/oauth2" diff --git a/pkg/remote/builtin/gitlab/helper.go b/pkg/remote/builtin/gitlab/helper.go index 39339196e..ac7f49f5d 100644 --- a/pkg/remote/builtin/gitlab/helper.go +++ b/pkg/remote/builtin/gitlab/helper.go @@ -4,7 +4,7 @@ import ( "fmt" "net/url" - "github.com/Bugagazavr/go-gitlab-client" + "github.com/drone/drone/Godeps/_workspace/src/github.com/Bugagazavr/go-gitlab-client" ) // NewClient is a helper function that returns a new GitHub