dmitri.shuralyov.com/service/change/...

Start ability to view individual commits.
dmitshur committed 2 years ago commit d072b8bd33fb7cf5828e26c4bc6578c5ea6a4ab0
changes.go
@@ -17,13 +17,13 @@ type Service interface {
 	Count(ctx context.Context, repo string, opt ListOptions) (uint64, error)
 
 	// Get a change.
 	Get(ctx context.Context, repo string, id uint64) (Change, error)
 	// ListCommits lists change commits.
-	ListCommits(ctx context.Context, repo string, id uint64) ([]Commit, error)
+	ListCommits(ctx context.Context, repo string, id uint64, opt *ListCommitsOptions) ([]Commit, error)
 	// Get a change diff.
-	GetDiff(ctx context.Context, repo string, id uint64) ([]byte, error)
+	GetDiff(ctx context.Context, repo string, id uint64, opt *ListCommitsOptions) ([]byte, error)
 
 	// ListComments lists comments for specified change id.
 	ListComments(ctx context.Context, repo string, id uint64, opt *ListCommentsOptions) ([]issues.Comment, error)
 	// ListEvents lists events for specified change id.
 	ListEvents(ctx context.Context, repo string, id uint64, opt *ListCommentsOptions) ([]issues.Event, error)
@@ -42,11 +42,11 @@ type Change struct {
 	Commits int // Number of commits (not populated during list operation).
 }
 
 type Commit struct {
 	SHA        string
-	Message    string
+	Message    string // TODO: Consider splitting into Subject, Body.
 	Author     users.User
 	AuthorTime time.Time
 }
 
 // State represents the change state.
@@ -72,10 +72,15 @@ type StateFilter State
 const (
 	// AllStates is a state filter that includes all issues.
 	AllStates StateFilter = "all"
 )
 
+type ListCommitsOptions struct {
+	// Commit is the commit ID of the commit to fetch.
+	Commit string
+}
+
 // ListCommentsOptions controls pagination.
 type ListCommentsOptions struct {
 	// Start is the index of first result to retrieve, zero-indexed.
 	Start int
 
gerritapi/gerritapi.go
@@ -123,15 +123,15 @@ func state(status string) changes.State {
 	default:
 		panic("unreachable")
 	}
 }
 
-func (s service) ListCommits(ctx context.Context, _ string, id uint64) ([]changes.Commit, error) {
+func (s service) ListCommits(ctx context.Context, _ string, id uint64, opt *changes.ListCommitsOptions) ([]changes.Commit, error) {
 	return nil, fmt.Errorf("ListCommits: not implemented")
 }
 
-func (s service) GetDiff(ctx context.Context, _ string, id uint64) ([]byte, error) {
+func (s service) GetDiff(ctx context.Context, _ string, id uint64, opt *changes.ListCommitsOptions) ([]byte, error) {
 	diff, _, err := s.cl.Changes.GetPatch(fmt.Sprint(id), "current", &gerrit.PatchOptions{
 		Path: "src", // TODO.
 	})
 	if err != nil {
 		return nil, err
githubapi/githubapi.go
@@ -206,43 +206,66 @@ func (s service) Get(ctx context.Context, rs string, id uint64) (changes.Change,
 		CreatedAt: pr.CreatedAt.Time,
 		Commits:   pr.Commits.TotalCount,
 	}, nil
 }
 
-func (s service) ListCommits(ctx context.Context, rs string, id uint64) ([]changes.Commit, error) {
+func (s service) ListCommits(ctx context.Context, rs string, id uint64, opt *changes.ListCommitsOptions) ([]changes.Commit, error) {
 	repo, err := ghRepoSpec(rs)
 	if err != nil {
 		// TODO: Map to 400 Bad Request HTTP error.
 		return nil, err
 	}
-	cs, _, err := s.clV3.PullRequests.ListCommits(ctx, repo.Owner, repo.Repo, int(id), nil)
-	if err != nil {
-		return nil, err
-	}
-	var commits []changes.Commit
-	for _, c := range cs {
-		commits = append(commits, changes.Commit{
+	switch opt {
+	case nil:
+		cs, _, err := s.clV3.PullRequests.ListCommits(ctx, repo.Owner, repo.Repo, int(id), nil)
+		if err != nil {
+			return nil, err
+		}
+		var commits []changes.Commit
+		for _, c := range cs {
+			commits = append(commits, changes.Commit{
+				SHA:        *c.SHA,
+				Message:    *c.Commit.Message,
+				Author:     ghUser(c.Author),
+				AuthorTime: *c.Commit.Author.Date,
+			})
+		}
+		return commits, nil
+	default:
+		c, _, err := s.clV3.Repositories.GetCommit(ctx, repo.Owner, repo.Repo, opt.Commit)
+		if err != nil {
+			return nil, err
+		}
+		return []changes.Commit{{
 			SHA:        *c.SHA,
 			Message:    *c.Commit.Message,
 			Author:     ghUser(c.Author),
 			AuthorTime: *c.Commit.Author.Date,
-		})
+		}}, nil
 	}
-	return commits, nil
 }
 
-func (s service) GetDiff(ctx context.Context, rs string, id uint64) ([]byte, error) {
+func (s service) GetDiff(ctx context.Context, rs string, id uint64, opt *changes.ListCommitsOptions) ([]byte, error) {
 	repo, err := ghRepoSpec(rs)
 	if err != nil {
 		// TODO: Map to 400 Bad Request HTTP error.
 		return nil, err
 	}
-	diff, _, err := s.clV3.PullRequests.GetRaw(ctx, repo.Owner, repo.Repo, int(id), github.RawOptions{Type: github.Diff})
-	if err != nil {
-		return nil, err
+	switch opt {
+	case nil:
+		diff, _, err := s.clV3.PullRequests.GetRaw(ctx, repo.Owner, repo.Repo, int(id), github.RawOptions{Type: github.Diff})
+		if err != nil {
+			return nil, err
+		}
+		return []byte(diff), nil
+	default:
+		diff, _, err := s.clV3.Repositories.GetCommitRaw(ctx, repo.Owner, repo.Repo, opt.Commit, github.RawOptions{Type: github.Diff})
+		if err != nil {
+			return nil, err
+		}
+		return []byte(diff), nil
 	}
-	return []byte(diff), nil
 }
 
 func (s service) ListComments(ctx context.Context, rs string, id uint64, opt *changes.ListCommentsOptions) ([]issues.Comment, error) {
 	// TODO: Respect opt.Start and opt.Length, if given.
 
maintner/maintner.go
@@ -104,15 +104,15 @@ func (s service) Count(_ context.Context, repo string, opt changes.ListOptions)
 func (s service) Get(ctx context.Context, _ string, id uint64) (changes.Change, error) {
 	// TODO.
 	return changes.Change{}, fmt.Errorf("Get: not implemented")
 }
 
-func (s service) ListCommits(ctx context.Context, _ string, id uint64) ([]changes.Commit, error) {
+func (s service) ListCommits(ctx context.Context, _ string, id uint64, opt *changes.ListCommitsOptions) ([]changes.Commit, error) {
 	return nil, fmt.Errorf("ListCommits: not implemented")
 }
 
-func (s service) GetDiff(ctx context.Context, _ string, id uint64) ([]byte, error) {
+func (s service) GetDiff(ctx context.Context, _ string, id uint64, opt *changes.ListCommitsOptions) ([]byte, error) {
 	// TODO.
 	return nil, fmt.Errorf("GetDiff: not implemented")
 }
 
 func state(status string) changes.State {