github.com/google/go-github/v66@v66.0.0/github/repos_commits.go (about) 1 // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "bytes" 10 "context" 11 "fmt" 12 "net/url" 13 "time" 14 ) 15 16 // RepositoryCommit represents a commit in a repo. 17 // Note that it's wrapping a Commit, so author/committer information is in two places, 18 // but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". 19 type RepositoryCommit struct { 20 NodeID *string `json:"node_id,omitempty"` 21 SHA *string `json:"sha,omitempty"` 22 Commit *Commit `json:"commit,omitempty"` 23 Author *User `json:"author,omitempty"` 24 Committer *User `json:"committer,omitempty"` 25 Parents []*Commit `json:"parents,omitempty"` 26 HTMLURL *string `json:"html_url,omitempty"` 27 URL *string `json:"url,omitempty"` 28 CommentsURL *string `json:"comments_url,omitempty"` 29 30 // Details about how many changes were made in this commit. Only filled in during GetCommit! 31 Stats *CommitStats `json:"stats,omitempty"` 32 // Details about which files, and how this commit touched. Only filled in during GetCommit! 33 Files []*CommitFile `json:"files,omitempty"` 34 } 35 36 func (r RepositoryCommit) String() string { 37 return Stringify(r) 38 } 39 40 // CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit. 41 type CommitStats struct { 42 Additions *int `json:"additions,omitempty"` 43 Deletions *int `json:"deletions,omitempty"` 44 Total *int `json:"total,omitempty"` 45 } 46 47 func (c CommitStats) String() string { 48 return Stringify(c) 49 } 50 51 // CommitFile represents a file modified in a commit. 52 type CommitFile struct { 53 SHA *string `json:"sha,omitempty"` 54 Filename *string `json:"filename,omitempty"` 55 Additions *int `json:"additions,omitempty"` 56 Deletions *int `json:"deletions,omitempty"` 57 Changes *int `json:"changes,omitempty"` 58 Status *string `json:"status,omitempty"` 59 Patch *string `json:"patch,omitempty"` 60 BlobURL *string `json:"blob_url,omitempty"` 61 RawURL *string `json:"raw_url,omitempty"` 62 ContentsURL *string `json:"contents_url,omitempty"` 63 PreviousFilename *string `json:"previous_filename,omitempty"` 64 } 65 66 func (c CommitFile) String() string { 67 return Stringify(c) 68 } 69 70 // CommitsComparison is the result of comparing two commits. 71 // See CompareCommits() for details. 72 type CommitsComparison struct { 73 BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` 74 MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"` 75 76 // Head can be 'behind' or 'ahead' 77 Status *string `json:"status,omitempty"` 78 AheadBy *int `json:"ahead_by,omitempty"` 79 BehindBy *int `json:"behind_by,omitempty"` 80 TotalCommits *int `json:"total_commits,omitempty"` 81 82 Commits []*RepositoryCommit `json:"commits,omitempty"` 83 84 Files []*CommitFile `json:"files,omitempty"` 85 86 HTMLURL *string `json:"html_url,omitempty"` 87 PermalinkURL *string `json:"permalink_url,omitempty"` 88 DiffURL *string `json:"diff_url,omitempty"` 89 PatchURL *string `json:"patch_url,omitempty"` 90 URL *string `json:"url,omitempty"` // API URL. 91 } 92 93 func (c CommitsComparison) String() string { 94 return Stringify(c) 95 } 96 97 // CommitsListOptions specifies the optional parameters to the 98 // RepositoriesService.ListCommits method. 99 type CommitsListOptions struct { 100 // SHA or branch to start listing Commits from. 101 SHA string `url:"sha,omitempty"` 102 103 // Path that should be touched by the returned Commits. 104 Path string `url:"path,omitempty"` 105 106 // Author of by which to filter Commits. 107 Author string `url:"author,omitempty"` 108 109 // Since when should Commits be included in the response. 110 Since time.Time `url:"since,omitempty"` 111 112 // Until when should Commits be included in the response. 113 Until time.Time `url:"until,omitempty"` 114 115 ListOptions 116 } 117 118 // BranchCommit is the result of listing branches with commit SHA. 119 type BranchCommit struct { 120 Name *string `json:"name,omitempty"` 121 Commit *Commit `json:"commit,omitempty"` 122 Protected *bool `json:"protected,omitempty"` 123 } 124 125 // ListCommits lists the commits of a repository. 126 // 127 // GitHub API docs: https://docs.github.com/rest/commits/commits#list-commits 128 // 129 //meta:operation GET /repos/{owner}/{repo}/commits 130 func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opts *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { 131 u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) 132 u, err := addOptions(u, opts) 133 if err != nil { 134 return nil, nil, err 135 } 136 137 req, err := s.client.NewRequest("GET", u, nil) 138 if err != nil { 139 return nil, nil, err 140 } 141 142 var commits []*RepositoryCommit 143 resp, err := s.client.Do(ctx, req, &commits) 144 if err != nil { 145 return nil, resp, err 146 } 147 148 return commits, resp, nil 149 } 150 151 // GetCommit fetches the specified commit, including all details about it. 152 // 153 // GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit 154 // 155 //meta:operation GET /repos/{owner}/{repo}/commits/{ref} 156 func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string, opts *ListOptions) (*RepositoryCommit, *Response, error) { 157 u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) 158 u, err := addOptions(u, opts) 159 if err != nil { 160 return nil, nil, err 161 } 162 163 req, err := s.client.NewRequest("GET", u, nil) 164 if err != nil { 165 return nil, nil, err 166 } 167 168 commit := new(RepositoryCommit) 169 resp, err := s.client.Do(ctx, req, commit) 170 if err != nil { 171 return nil, resp, err 172 } 173 174 return commit, resp, nil 175 } 176 177 // GetCommitRaw fetches the specified commit in raw (diff or patch) format. 178 // 179 // GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit 180 // 181 //meta:operation GET /repos/{owner}/{repo}/commits/{ref} 182 func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opts RawOptions) (string, *Response, error) { 183 u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) 184 req, err := s.client.NewRequest("GET", u, nil) 185 if err != nil { 186 return "", nil, err 187 } 188 189 switch opts.Type { 190 case Diff: 191 req.Header.Set("Accept", mediaTypeV3Diff) 192 case Patch: 193 req.Header.Set("Accept", mediaTypeV3Patch) 194 default: 195 return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) 196 } 197 198 var buf bytes.Buffer 199 resp, err := s.client.Do(ctx, req, &buf) 200 if err != nil { 201 return "", resp, err 202 } 203 204 return buf.String(), resp, nil 205 } 206 207 // GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is 208 // supplied and no new commits have occurred, a 304 Unmodified response is returned. 209 // 210 // GitHub API docs: https://docs.github.com/rest/commits/commits#get-a-commit 211 // 212 //meta:operation GET /repos/{owner}/{repo}/commits/{ref} 213 func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { 214 u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, refURLEscape(ref)) 215 216 req, err := s.client.NewRequest("GET", u, nil) 217 if err != nil { 218 return "", nil, err 219 } 220 if lastSHA != "" { 221 req.Header.Set("If-None-Match", `"`+lastSHA+`"`) 222 } 223 224 req.Header.Set("Accept", mediaTypeV3SHA) 225 226 var buf bytes.Buffer 227 resp, err := s.client.Do(ctx, req, &buf) 228 if err != nil { 229 return "", resp, err 230 } 231 232 return buf.String(), resp, nil 233 } 234 235 // CompareCommits compares a range of commits with each other. 236 // 237 // GitHub API docs: https://docs.github.com/rest/commits/commits#compare-two-commits 238 // 239 //meta:operation GET /repos/{owner}/{repo}/compare/{basehead} 240 func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string, opts *ListOptions) (*CommitsComparison, *Response, error) { 241 escapedBase := url.QueryEscape(base) 242 escapedHead := url.QueryEscape(head) 243 244 u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) 245 u, err := addOptions(u, opts) 246 if err != nil { 247 return nil, nil, err 248 } 249 250 req, err := s.client.NewRequest("GET", u, nil) 251 if err != nil { 252 return nil, nil, err 253 } 254 255 comp := new(CommitsComparison) 256 resp, err := s.client.Do(ctx, req, comp) 257 if err != nil { 258 return nil, resp, err 259 } 260 261 return comp, resp, nil 262 } 263 264 // CompareCommitsRaw compares a range of commits with each other in raw (diff or patch) format. 265 // 266 // Both "base" and "head" must be branch names in "repo". 267 // To compare branches across other repositories in the same network as "repo", 268 // use the format "<USERNAME>:branch". 269 // 270 // GitHub API docs: https://docs.github.com/rest/commits/commits#compare-two-commits 271 // 272 //meta:operation GET /repos/{owner}/{repo}/compare/{basehead} 273 func (s *RepositoriesService) CompareCommitsRaw(ctx context.Context, owner, repo, base, head string, opts RawOptions) (string, *Response, error) { 274 escapedBase := url.QueryEscape(base) 275 escapedHead := url.QueryEscape(head) 276 277 u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) 278 279 req, err := s.client.NewRequest("GET", u, nil) 280 if err != nil { 281 return "", nil, err 282 } 283 284 switch opts.Type { 285 case Diff: 286 req.Header.Set("Accept", mediaTypeV3Diff) 287 case Patch: 288 req.Header.Set("Accept", mediaTypeV3Patch) 289 default: 290 return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) 291 } 292 293 var buf bytes.Buffer 294 resp, err := s.client.Do(ctx, req, &buf) 295 if err != nil { 296 return "", resp, err 297 } 298 299 return buf.String(), resp, nil 300 } 301 302 // ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD, 303 // or latest commit for the branch. 304 // 305 // GitHub API docs: https://docs.github.com/rest/commits/commits#list-branches-for-head-commit 306 // 307 //meta:operation GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head 308 func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) { 309 u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha) 310 311 req, err := s.client.NewRequest("GET", u, nil) 312 if err != nil { 313 return nil, nil, err 314 } 315 316 // TODO: remove custom Accept header when this API fully launches. 317 req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) 318 var branchCommits []*BranchCommit 319 resp, err := s.client.Do(ctx, req, &branchCommits) 320 if err != nil { 321 return nil, resp, err 322 } 323 324 return branchCommits, resp, nil 325 }