From 2cbe6d9d3e86c6b386fc18f8601d657e2d1f65ae Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Wed, 5 Jun 2013 12:23:29 +0200 Subject: [PATCH] Implementation and tests for Trees API --- github/github.go | 2 + github/trees.go | 77 +++++++++++++++++++++++ github/trees_test.go | 141 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 github/trees.go create mode 100644 github/trees_test.go diff --git a/github/github.go b/github/github.go index a6b994d..2125ba3 100644 --- a/github/github.go +++ b/github/github.go @@ -91,6 +91,7 @@ type Client struct { Organizations *OrganizationsService PullRequests *PullRequestsService Repositories *RepositoriesService + Trees *TreesService Users *UsersService Gists *GistsService } @@ -117,6 +118,7 @@ func NewClient(httpClient *http.Client) *Client { c.Organizations = &OrganizationsService{client: c} c.PullRequests = &PullRequestsService{client: c} c.Repositories = &RepositoriesService{client: c} + c.Trees = &TreesService{client: c} c.Users = &UsersService{client: c} c.Gists = &GistsService{client: c} return c diff --git a/github/trees.go b/github/trees.go new file mode 100644 index 0000000..e9ac58e --- /dev/null +++ b/github/trees.go @@ -0,0 +1,77 @@ +// Copyright 2013 Google. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +package github + +import "fmt" + +// TreesService handles communication with the tree related +// methods of the GitHub API. +// +// GitHub API docs: http://developer.github.com/v3/trees/ +type TreesService struct { + client *Client +} + +type Tree struct { + SHA string `json:"sha,omitempty"` + Trees []GitTree `json:"tree,omitempty"` +} + +// Tree represents a Git tree. +type GitTree struct { + SHA string `json:"sha,omitempty"` + Path string `json:"path,omitempty"` + Mode string `json:"mode,omitempty"` + Type string `json:"type,omitempty"` + Size int `json:"size,omitempty"` +} + +type createTree struct { + baseTree string `json:base_tree` + trees []GitTree `json:tree` +} + +// Get the Tree object for a given sha hash from a users repository. +// +// GitHub API docs: http://developer.github.com/v3/git/trees/#get-a-tree +func (s *TreesService) Get(user string, repo string, sha string, recursive bool) (*Tree, error) { + url_ := fmt.Sprintf("repos/%v/%v/git/trees/%v", user, repo, sha) + + if recursive { + url_ += "?recursive=1" + } + + req, err := s.client.NewRequest("GET", url_, nil) + if err != nil { + return nil, err + } + + var response Tree + _, err = s.client.Do(req, &response) + return &response, err +} + +// The tree creation API will take nested entries as well. +// If both a tree and a nested path modifying that tree are specified, +// it will overwrite the contents of that tree with the new path contents and write a new tree out. +// +// GitHub API docs: http://developer.github.com/v3/git/trees/#create-a-tree +func (s *TreesService) Create(owner string, repo string, sha string, baseTreeSha string, trees []GitTree) (*Tree, error) { + url_ := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) + + req, err := s.client.NewRequest("POST", url_, createTree{ + baseTree: baseTreeSha, + trees: trees, + }) + if err != nil { + return nil, err + } + + r := new(Tree) + _, err = s.client.Do(req, r) + return r, err +} diff --git a/github/trees_test.go b/github/trees_test.go new file mode 100644 index 0000000..533ff1d --- /dev/null +++ b/github/trees_test.go @@ -0,0 +1,141 @@ +// Copyright 2013 Google. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +package github + +import ( + "encoding/json" + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestTreesService_Get_authenticatedUser(t *testing.T) { + setup() + defer teardown() + + url_ := fmt.Sprintf("/repos/%v/%v/git/trees/%v", "user", "repo", "coffebabecoffebabecoffebabe") + + mux.HandleFunc(url_, func(w http.ResponseWriter, r *http.Request) { + if m := "GET"; m != r.Method { + t.Errorf("Request method = %v, want %v", r.Method, m) + } + fmt.Fprint(w, `{ + "sha": "9fb037999f264ba9a7fc6274d15fa3ae2ab98312", + "url": "https://api.github.com/repos/octocat/Hello-World/trees/9fb037999f264ba9a7fc6274d15fa3ae2ab98312", + "tree": [ + { + "path": "file.rb", + "mode": "100644", + "type": "blob", + "size": 30, + "sha": "44b4fc6d56897b048c772eb4087f854f46256132", + "url": "https://api.github.com/repos/octocat/Hello-World/git/blobs/44b4fc6d56897b048c772eb4087f854f46256132" + }, + { + "path": "subdir", + "mode": "040000", + "type": "tree", + "sha": "f484d249c660418515fb01c2b9662073663c242e", + "url": "https://api.github.com/repos/octocat/Hello-World/git/blobs/f484d249c660418515fb01c2b9662073663c242e" + } + ] + }`) + }) + + trees, err := client.Trees.Get("user", "repo", "coffebabecoffebabecoffebabe", true) + if err != nil { + t.Errorf("Trees.List returned error: %v", err) + } + + want := Tree{ + SHA: `9fb037999f264ba9a7fc6274d15fa3ae2ab98312`, + Trees: []GitTree{ + GitTree{ + Path: "file.rb", + Mode: "100644", + Type: "blob", + Size: 30, + SHA: "44b4fc6d56897b048c772eb4087f854f46256132", + }, + GitTree{ + Path: "subdir", + Mode: "040000", + Type: "tree", + SHA: "f484d249c660418515fb01c2b9662073663c242e", + }, + }, + } + if !reflect.DeepEqual(*trees, want) { + t.Errorf("Tree.List returned %+v, want %+v", *trees, want) + } +} + +func TestTreesService_Create_authenticatedUser(t *testing.T) { + setup() + defer teardown() + + url_ := fmt.Sprintf("/repos/%v/%v/git/trees/%v", "user", "repo", "coffebabecoffebabecoffebabe") + + treesToCreate := + []GitTree{ + GitTree{ + Path: "file.rb", + Mode: "100644", + Type: "blob", + SHA: "7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b", + }, + } + + mux.HandleFunc(url_, func(w http.ResponseWriter, r *http.Request) { + v := new(struct { + BaseTree string `json:base_tree` + Tree []GitTree `json:tree` + }) + + json.NewDecoder(r.Body).Decode(v) + + if m := "POST"; m != r.Method { + t.Errorf("Request method = %v, want %v", r.Method, m) + } + + fmt.Fprint(w, `{ + "sha": "cd8274d15fa3ae2ab983129fb037999f264ba9a7", + "tree": [ + { + "path": "file.rb", + "mode": "100644", + "type": "blob", + "size": 132, + "sha": "7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b" + } + ] + }`) + }) + + tree, err := client.Trees.Create("user", "repo", "coffebabecoffebabecoffebabe", "basebasebase", treesToCreate) + if err != nil { + t.Errorf("Trees.Create returned error: %v", err) + } + + want := Tree{ + "cd8274d15fa3ae2ab983129fb037999f264ba9a7", + []GitTree{ + GitTree{ + Path: "file.rb", + Mode: "100644", + Type: "blob", + Size: 132, + SHA: "7c258a9869f33c1e1e1f74fbb32f07c86cb5a75b", + }, + }, + } + + if !reflect.DeepEqual(*tree, want) { + t.Errorf("Tree.Create returned %+v, want %+v", *tree, want) + } +}