Repositories

Modified repository/git.go

@@ -19,6 +19,7 @@ package repository
import (
"crypto/sha1"
"encoding/json"
"fmt"
"log"
"os"
@@ -173,6 +174,38 @@ func (repo *GitRepo) GetLastParent(ref string) (string, error) {
return repo.runGitCommand("rev-list", "--skip", "1", "-n", "1", ref)
}
// GetCommitDetails returns the details of a commit's metadata.
func (repo GitRepo) GetCommitDetails(ref string) (*CommitDetails, error) {
var err error
show := func(formatString string) (result string) {
if err != nil {
return ""
}
result, err = repo.runGitCommand("show", "-s", ref, fmt.Sprintf("--format=tformat:%s", formatString))
return result
}
jsonFormatString := "{\"tree\":\"%T\", \"time\": \"%at\"}"
detailsJSON := show(jsonFormatString)
if err != nil {
return nil, err
}
var details CommitDetails
err = json.Unmarshal([]byte(detailsJSON), &details)
if err != nil {
return nil, err
}
details.Author = show("%an")
details.AuthorEmail = show("%ae")
details.Summary = show("%s")
parentsString := show("%P")
details.Parents = strings.Split(parentsString, " ")
if err != nil {
return nil, err
}
return &details, nil
}
// MergeBase determines if the first commit that is an ancestor of the two arguments.
func (repo *GitRepo) MergeBase(a, b string) string {
return repo.runGitCommandOrDie("merge-base", a, b)

Modified repository/mock_repo.go

@@ -256,6 +256,21 @@ func (r mockRepoForTest) GetLastParent(ref string) (string, error) {
return "", err
}
// GetCommitDetails returns the details of a commit's metadata.
func (r mockRepoForTest) GetCommitDetails(ref string) (*CommitDetails, error) {
commit, err := r.getCommit(ref)
if err != nil {
return nil, err
}
var details CommitDetails
details.Author = "Test Author"
details.AuthorEmail = "[email protected]"
details.Summary = commit.Message
details.Time = commit.Time
details.Parents = commit.Parents
return &details, nil
}
// ancestors returns the breadth-first traversal of a commit's ancestors
func (r mockRepoForTest) ancestors(commit string) []string {
queue := []string{commit}
@@ -335,10 +350,22 @@ func (r mockRepoForTest) GetNotes(notesRef, revision string) []Note {
}
// AppendNote appends a note to a revision under the given ref.
func (r mockRepoForTest) AppendNote(ref, revision string, note Note) {}
func (r mockRepoForTest) AppendNote(ref, revision string, note Note) {
existingNotes := r.Notes[ref][revision]
newNotes := existingNotes + "\n" + string(note)
r.Notes[ref][revision] = newNotes
}
// ListNotedRevisions returns the collection of revisions that are annotated by notes in the given ref.
func (r mockRepoForTest) ListNotedRevisions(notesRef string) []string { return nil }
func (r mockRepoForTest) ListNotedRevisions(notesRef string) []string {
var revisions []string
for revision := range r.Notes[notesRef] {
if _, ok := r.Commits[revision]; ok {
revisions = append(revisions, revision)
}
}
return revisions
}
// PushNotes pushes git notes to a remote repo.
func (r mockRepoForTest) PushNotes(remote, notesRefPattern string) error { return nil }

Modified repository/repo.go

@@ -20,6 +20,15 @@ package repository
// Note represents the contents of a git-note
type Note []byte
type CommitDetails struct {
Author string `json:"author,omitempty"`
AuthorEmail string `json:"authorEmail,omitempty"`
Tree string `json:"tree,omitempty"`
Time string `json:"time,omitempty"`
Parents []string `json:"parents,omitempty"`
Summary string `json:"summary,omitempty"`
}
// Repo represents a source code repository.
type Repo interface {
// GetPath returns the path to the repo.
@@ -66,6 +75,9 @@ type Repo interface {
// GetLastParent returns the last parent of the given commit (as ordered by git).
GetLastParent(ref string) (string, error)
// GetCommitDetails returns the details of a commit's metadata.
GetCommitDetails(ref string) (*CommitDetails, error)
// MergeBase determines if the first commit that is an ancestor of the two arguments.
MergeBase(a, b string) string