Skip to content

Commit

Permalink
implement repos_commits API
Browse files Browse the repository at this point in the history
  • Loading branch information
ktoso authored and willnorris committed Sep 4, 2013
1 parent 838a7ac commit 1eaf383
Show file tree
Hide file tree
Showing 5 changed files with 358 additions and 0 deletions.
1 change: 1 addition & 0 deletions github/git_commits.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Commit struct {
Message *string `json:"message,omitempty"`
Tree *Tree `json:"tree,omitempty"`
Parents []Commit `json:"parents,omitempty"`
Stats *CommitStats `json:"stats,omitempty"`
}

func (c Commit) String() string {
Expand Down
1 change: 1 addition & 0 deletions github/repos_collaborators.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func (s *RepositoriesService) IsCollaborator(owner, repo, user string) (bool, *R
if err != nil {
return false, nil, err
}

resp, err := s.client.Do(req, nil)
isCollab, err := parseBoolResponse(err)
return isCollab, resp, err
Expand Down
161 changes: 161 additions & 0 deletions github/repos_commits.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
"fmt"
"net/url"
"time"
)

// RepositoryCommit represents a commit in a repo.
// Note that it's wrapping a Commit, so author/committer information is in two places,
// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details".
type RepositoryCommit struct {
SHA *string `json:"sha,omitempty"`
Commit *Commit `json:"commit,omitempty"`
Author *User `json:"author,omitempty"`
Committer *User `json:"committer,omitempty"`
Parents []Commit `json:"parents,omitempty"`
Message *string `json:"message,omitempty"`

// Details about how many changes were made in this commit. Only filled in during GetCommit!
Stats *CommitStats `json:"stats,omitempty"`
// Details about which files, and how this commit touched. Only filled in during GetCommit!
Files []CommitFile `json:"files,omitempty"`
}

func (r RepositoryCommit) String() string {
return Stringify(r)
}

// CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit.
type CommitStats struct {
Additions *int `json:"additions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
Total *int `json:"total,omitempty"`
}

func (c CommitStats) String() string {
return Stringify(c)
}

// CommitFile represents a file modified in a commit.
type CommitFile struct {
SHA *string `json:"sha,omitempty"`
Filename *string `json:"filename,omitempty"`
Additions *int `json:"additions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
Changes *int `json:"changes,omitempty"`
Status *string `json:"status,omitempty"`
Patch *string `json:"patch,omitempty"`
}

func (c CommitFile) String() string {
return Stringify(c)
}

// CommitsComparison is the result of comparing two commits.
// See CompareCommits() for details.
type CommitsComparison struct {
BaseCommit *RepositoryCommit `json:"base_commit,omitempty"`

// Head can be 'behind' or 'ahead'
Status *string `json:"status,omitempty"`
AheadBy *int `json:"ahead_by,omitempty"`
BehindBy *int `json:"behind_by,omitempty"`
TotalCommits *int `json:"total_commits,omitempty"`

Commits []RepositoryCommit `json:"commits,omitempty"`

Files []CommitFile `json:"files,omitempty"`
}

func (c CommitsComparison) String() string {
return Stringify(c)
}

// CommitsListOptions specifies the optional parameters to the
// RepositoriesService.ListCommits method.
type CommitsListOptions struct {
// SHA or branch to start listing Commits from.
SHA string
// Path that should be touched by the returned Commits.
Path string
// Author of by which to filter Commits.
Author string
// Since when should Commits be included in the response.
Since time.Time
// Until when should Commits be included in the response.
Until time.Time
}

// ListCommits lists the commits of a repository.
//
// GitHub API docs: http://developer.github.com/v3/repos/commits/#list
func (s *RepositoriesService) ListCommits(owner, repo string, opts *CommitsListOptions) ([]RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits", owner, repo)

if opts != nil {
params := url.Values{
"sha": {opts.SHA},
"path": {opts.Path},
"author": {opts.Author},
}
if !opts.Since.IsZero() {
params.Add("since", opts.Since.Format(time.RFC3339))
}
if !opts.Until.IsZero() {
params.Add("until", opts.Until.Format(time.RFC3339))
}

u += "?" + params.Encode()
}

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

commits := new([]RepositoryCommit)
resp, err := s.client.Do(req, commits)
return *commits, resp, err
}

// GetCommit fetches the specified commit, including all details about it.
// todo: support media formats - https://github.com/google/go-github/issues/6
//
// GitHub API docs: http://developer.github.com/v3/repos/commits/#get-a-single-commit
// See also: http://developer.github.com//v3/git/commits/#get-a-single-commit provides the same functionality
func (s *RepositoriesService) GetCommit(owner, repo, sha string) (*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

commit := new(RepositoryCommit)
resp, err := s.client.Do(req, commit)
return commit, resp, err
}

// CompareCommits compares a range of commits with each other.
// todo: support media formats - https://github.com/google/go-github/issues/6
//
// GitHub API docs: http://developer.github.com/v3/repos/commits/index.html#compare-two-commits
func (s *RepositoriesService) CompareCommits(owner, repo string, base, head string) (*CommitsComparison, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, base, head)

req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}

comp := new(CommitsComparison)
resp, err := s.client.Do(req, comp)
return comp, resp, err
}
191 changes: 191 additions & 0 deletions github/repos_commits_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
"fmt"
"net/http"
"reflect"
"testing"
"time"
)

func TestRepositoriesService_ListCommits(t *testing.T) {
setup()
defer teardown()

// given
mux.HandleFunc("/repos/o/r/commits", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testFormValues(t, r,
values{
"sha": "s",
"path": "p",
"author": "a",
"since": "2013-08-01T00:00:00Z",
"until": "2013-09-03T00:00:00Z",
})
fmt.Fprintf(w, `[{"sha": "s"}]`)
})

opt := &CommitsListOptions{
SHA: "s",
Path: "p",
Author: "a",
Since: time.Date(2013, time.August, 1, 0, 0, 0, 0, time.UTC),
Until: time.Date(2013, time.September, 3, 0, 0, 0, 0, time.UTC),
}
commits, _, err := client.Repositories.ListCommits("o", "r", opt)
if err != nil {
t.Errorf("Repositories.ListCommits returned error: %v", err)
}

want := []RepositoryCommit{{SHA: String("s")}}
if !reflect.DeepEqual(commits, want) {
t.Errorf("Repositories.ListCommits returned %+v, want %+v", commits, want)
}
}

func TestRepositoriesService_GetCommit(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/repos/o/r/commits/s", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprintf(w, `{
"sha": "s",
"commit": { "message": "m" },
"author": { "login": "l" },
"committer": { "login": "l" },
"parents": [ { "sha": "s" } ],
"stats": { "additions": 104, "deletions": 4, "total": 108 },
"files": [
{
"filename": "f",
"additions": 10,
"deletions": 2,
"changes": 12,
"status": "s",
"raw_url": "r",
"blob_url": "b",
"patch": "p"
}
]
}`)
})

commit, _, err := client.Repositories.GetCommit("o", "r", "s")
if err != nil {
t.Errorf("Repositories.GetCommit returned error: %v", err)
}

want := &RepositoryCommit{
SHA: String("s"),
Commit: &Commit{
Message: String("m"),
},
Author: &User{
Login: String("l"),
},
Committer: &User{
Login: String("l"),
},
Parents: []Commit{
{
SHA: String("s"),
},
},
Stats: &CommitStats{
Additions: Int(104),
Deletions: Int(4),
Total: Int(108),
},
Files: []CommitFile{
{
Filename: String("f"),
Additions: Int(10),
Deletions: Int(2),
Changes: Int(12),
Status: String("s"),
Patch: String("p"),
},
},
}
if !reflect.DeepEqual(commit, want) {
t.Errorf("Repositories.GetCommit returned \n%+v, want \n%+v", commit, want)
}
}

func TestRepositoriesService_CompareCommits(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/repos/o/r/compare/b...h", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
fmt.Fprintf(w, `{
"base_commit": {
"sha": "s",
"commit": {
"author": { "name": "n" },
"committer": { "name": "n" },
"message": "m",
"tree": { "sha": "t" }
},
"author": { "login": "n" },
"committer": { "login": "l" },
"parents": [ { "sha": "s" } ]
},
"status": "s",
"ahead_by": 1,
"behind_by": 2,
"total_commits": 1,
"commits": [
{
"sha": "s",
"commit": { "author": { "name": "n" } },
"author": { "login": "l" },
"committer": { "login": "l" },
"parents": [ { "sha": "s" } ]
}
],
"files": [ { "filename": "f" } ]
}`)
})

got, _, err := client.Repositories.CompareCommits("o", "r", "b", "h")
if err != nil {
t.Errorf("Repositories.CompareCommits returned error: %v", err)
}

want := &CommitsComparison{
Status: String("s"),
AheadBy: Int(1),
BehindBy: Int(2),
TotalCommits: Int(1),
BaseCommit: &RepositoryCommit{
Commit: &Commit{
Author: &CommitAuthor{Name: String("n")},
},
Author: &User{Login: String("l")},
Committer: &User{Login: String("l")},
Message: String("m"),
},
Commits: []RepositoryCommit{
{
SHA: String("s"),
},
},
Files: []CommitFile{
{
Filename: String("f"),
},
},
}

if reflect.DeepEqual(got, want) {
t.Errorf("Repositories.CompareCommits returned \n%+v, want \n%+v", got, want)
}
}
4 changes: 4 additions & 0 deletions github/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ func TestString(t *testing.T) {
{PullRequestComment{ID: Int(1)}, `github.PullRequestComment{ID:1}`},
{Repository{ID: Int(1)}, `github.Repository{ID:1}`},
{RepositoryComment{ID: Int(1)}, `github.RepositoryComment{ID:1}`},
{RepositoryCommit{SHA: String("s")}, `github.RepositoryCommit{SHA:"s"}`},
{CommitStats{Total: Int(1)}, `github.CommitStats{Total:1}`},
{CommitFile{SHA: String("s")}, `github.CommitFile{SHA:"s"}`},
{CommitsComparison{TotalCommits: Int(1)}, `github.CommitsComparison{TotalCommits:1}`},

This comment has been minimized.

Copy link
@ktoso

ktoso Sep 5, 2013

Author Contributor

Oh :-) I'll remember to test the String()s too next time then! Thanks 👍

This comment has been minimized.

Copy link
@willnorris

willnorris Sep 5, 2013

Collaborator

you might also be interested in #55

{WebHookPayload{Ref: String("r")}, `github.WebHookPayload{Ref:"r"}`},
{WebHookCommit{ID: String("1")}, `github.WebHookCommit{ID:"1"}`},
{WebHookAuthor{Name: String("n")}, `github.WebHookAuthor{Name:"n"}`},
Expand Down

0 comments on commit 1eaf383

Please sign in to comment.