diff --git a/github/git.go b/github/git.go index 31890bc..3ada1cd 100644 --- a/github/git.go +++ b/github/git.go @@ -5,7 +5,11 @@ package github -import "fmt" +import ( + "time" + + "fmt" +) // GitService handles communication with the git data related // methods of the GitHub API. @@ -15,6 +19,24 @@ type GitService struct { client *Client } +// Commit represents a GitHub commit. +type Commit struct { + SHA string `json:"sha,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message string `json:"message,omitempty"` + Tree *Tree `json:"tree,omitempty"` + Parents []Commit `json:"parents,omitempty"` +} + +// CommitAuthor represents the author or committer of a commit. The commit +// author may not correspond to a GitHub User. +type CommitAuthor struct { + Date *time.Time `json:"date,omitempty"` + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` +} + // Tree represents a GitHub tree. type Tree struct { SHA string `json:"sha,omitempty"` @@ -32,6 +54,40 @@ type TreeEntry struct { Size int `json:"size,omitempty"` } +// GetCommit fetchs the Commit object for a given SHA. +// +// GitHub API docs: http://developer.github.com/v3/git/commits/#get-a-commit +func (s *GitService) GetCommit(owner string, repo string, sha string) (*Commit, error) { + u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + + c := new(Commit) + _, err = s.client.Do(req, c) + return c, err +} + +// CreateCommit creates a new commit in a repository. +// +// The commit.Committer is optional and will be filled with the commit.Author +// data if omitted. If the commit.Author is omitted, it will be filled in with +// the authenticated user’s information and the current date. +// +// GitHub API docs: http://developer.github.com/v3/git/commits/#create-a-commit +func (s *GitService) CreateCommit(owner string, repo string, commit *Commit) (*Commit, error) { + u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) + req, err := s.client.NewRequest("POST", u, commit) + if err != nil { + return nil, err + } + + c := new(Commit) + _, err = s.client.Do(req, c) + return c, err +} + // GetTree fetches the Tree object for a given sha hash from a repository. // // GitHub API docs: http://developer.github.com/v3/git/trees/#get-a-tree diff --git a/github/git_test.go b/github/git_test.go index 167e4a6..ccd814f 100644 --- a/github/git_test.go +++ b/github/git_test.go @@ -13,6 +13,54 @@ import ( "testing" ) +func TestGitService_GetCommit(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/repos/o/r/git/commits/s", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{"sha":"s","message":"m","author":{"name":"n"}}`) + }) + + commit, err := client.Git.GetCommit("o", "r", "s") + if err != nil { + t.Errorf("Git.GetCommit returned error: %v", err) + } + + want := &Commit{SHA: "s", Message: "m", Author: &CommitAuthor{Name: "n"}} + if !reflect.DeepEqual(commit, want) { + t.Errorf("Git.GetCommit returned %+v, want %+v", commit, want) + } +} + +func TestGitService_CreateCommit(t *testing.T) { + setup() + defer teardown() + + input := &Commit{Message: "m", Tree: &Tree{SHA: "t"}} + + mux.HandleFunc("/repos/o/r/git/commits", func(w http.ResponseWriter, r *http.Request) { + v := new(Commit) + json.NewDecoder(r.Body).Decode(v) + + testMethod(t, r, "POST") + if !reflect.DeepEqual(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + fmt.Fprint(w, `{"sha":"s"}`) + }) + + commit, err := client.Git.CreateCommit("o", "r", input) + if err != nil { + t.Errorf("Git.CreateCommit returned error: %v", err) + } + + want := &Commit{SHA: "s"} + if !reflect.DeepEqual(commit, want) { + t.Errorf("Git.CreateCommit returned %+v, want %+v", commit, want) + } +} + func TestGitService_GetTree(t *testing.T) { setup() defer teardown()