1 // Copyright 2014 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 "context" 10 "fmt" 11 "time" 12 ) 13 14 // ContributorStats represents a contributor to a repository and their 15 // weekly contributions to a given repo. 16 type ContributorStats struct { 17 Author *Contributor `json:"author,omitempty"` 18 Total *int `json:"total,omitempty"` 19 Weeks []*WeeklyStats `json:"weeks,omitempty"` 20 } 21 22 func (c ContributorStats) String() string { 23 return Stringify(c) 24 } 25 26 // WeeklyStats represents the number of additions, deletions and commits 27 // a Contributor made in a given week. 28 type WeeklyStats struct { 29 Week *Timestamp `json:"w,omitempty"` 30 Additions *int `json:"a,omitempty"` 31 Deletions *int `json:"d,omitempty"` 32 Commits *int `json:"c,omitempty"` 33 } 34 35 func (w WeeklyStats) String() string { 36 return Stringify(w) 37 } 38 39 // ListContributorsStats gets a repo's contributor list with additions, 40 // deletions and commit counts. 41 // 42 // If this is the first time these statistics are requested for the given 43 // repository, this method will return an *AcceptedError and a status code of 44 // 202. This is because this is the status that GitHub returns to signify that 45 // it is now computing the requested statistics. A follow up request, after a 46 // delay of a second or so, should result in a successful request. 47 // 48 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-all-contributor-commit-activity 49 func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { 50 u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) 51 req, err := s.client.NewRequest("GET", u, nil) 52 if err != nil { 53 return nil, nil, err 54 } 55 56 var contributorStats []*ContributorStats 57 resp, err := s.client.Do(ctx, req, &contributorStats) 58 if err != nil { 59 return nil, resp, err 60 } 61 62 return contributorStats, resp, nil 63 } 64 65 // WeeklyCommitActivity represents the weekly commit activity for a repository. 66 // The days array is a group of commits per day, starting on Sunday. 67 type WeeklyCommitActivity struct { 68 Days []int `json:"days,omitempty"` 69 Total *int `json:"total,omitempty"` 70 Week *Timestamp `json:"week,omitempty"` 71 } 72 73 func (w WeeklyCommitActivity) String() string { 74 return Stringify(w) 75 } 76 77 // ListCommitActivity returns the last year of commit activity 78 // grouped by week. The days array is a group of commits per day, 79 // starting on Sunday. 80 // 81 // If this is the first time these statistics are requested for the given 82 // repository, this method will return an *AcceptedError and a status code of 83 // 202. This is because this is the status that GitHub returns to signify that 84 // it is now computing the requested statistics. A follow up request, after a 85 // delay of a second or so, should result in a successful request. 86 // 87 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-the-last-year-of-commit-activity 88 func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { 89 u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) 90 req, err := s.client.NewRequest("GET", u, nil) 91 if err != nil { 92 return nil, nil, err 93 } 94 95 var weeklyCommitActivity []*WeeklyCommitActivity 96 resp, err := s.client.Do(ctx, req, &weeklyCommitActivity) 97 if err != nil { 98 return nil, resp, err 99 } 100 101 return weeklyCommitActivity, resp, nil 102 } 103 104 // ListCodeFrequency returns a weekly aggregate of the number of additions and 105 // deletions pushed to a repository. Returned WeeklyStats will contain 106 // additions and deletions, but not total commits. 107 // 108 // If this is the first time these statistics are requested for the given 109 // repository, this method will return an *AcceptedError and a status code of 110 // 202. This is because this is the status that GitHub returns to signify that 111 // it is now computing the requested statistics. A follow up request, after a 112 // delay of a second or so, should result in a successful request. 113 // 114 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-the-weekly-commit-activity 115 func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { 116 u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) 117 req, err := s.client.NewRequest("GET", u, nil) 118 if err != nil { 119 return nil, nil, err 120 } 121 122 var weeks [][]int 123 resp, err := s.client.Do(ctx, req, &weeks) 124 125 // convert int slices into WeeklyStats 126 var stats []*WeeklyStats 127 for _, week := range weeks { 128 if len(week) != 3 { 129 continue 130 } 131 stat := &WeeklyStats{ 132 Week: &Timestamp{time.Unix(int64(week[0]), 0)}, 133 Additions: Int(week[1]), 134 Deletions: Int(week[2]), 135 } 136 stats = append(stats, stat) 137 } 138 139 return stats, resp, err 140 } 141 142 // RepositoryParticipation is the number of commits by everyone 143 // who has contributed to the repository (including the owner) 144 // as well as the number of commits by the owner themself. 145 type RepositoryParticipation struct { 146 All []int `json:"all,omitempty"` 147 Owner []int `json:"owner,omitempty"` 148 } 149 150 func (r RepositoryParticipation) String() string { 151 return Stringify(r) 152 } 153 154 // ListParticipation returns the total commit counts for the 'owner' 155 // and total commit counts in 'all'. 'all' is everyone combined, 156 // including the 'owner' in the last 52 weeks. If you’d like to get 157 // the commit counts for non-owners, you can subtract 'all' from 'owner'. 158 // 159 // The array order is oldest week (index 0) to most recent week. 160 // 161 // If this is the first time these statistics are requested for the given 162 // repository, this method will return an *AcceptedError and a status code of 163 // 202. This is because this is the status that GitHub returns to signify that 164 // it is now computing the requested statistics. A follow up request, after a 165 // delay of a second or so, should result in a successful request. 166 // 167 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-the-weekly-commit-count 168 func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { 169 u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) 170 req, err := s.client.NewRequest("GET", u, nil) 171 if err != nil { 172 return nil, nil, err 173 } 174 175 participation := new(RepositoryParticipation) 176 resp, err := s.client.Do(ctx, req, participation) 177 if err != nil { 178 return nil, resp, err 179 } 180 181 return participation, resp, nil 182 } 183 184 // PunchCard represents the number of commits made during a given hour of a 185 // day of the week. 186 type PunchCard struct { 187 Day *int // Day of the week (0-6: =Sunday - Saturday). 188 Hour *int // Hour of day (0-23). 189 Commits *int // Number of commits. 190 } 191 192 // ListPunchCard returns the number of commits per hour in each day. 193 // 194 // If this is the first time these statistics are requested for the given 195 // repository, this method will return an *AcceptedError and a status code of 196 // 202. This is because this is the status that GitHub returns to signify that 197 // it is now computing the requested statistics. A follow up request, after a 198 // delay of a second or so, should result in a successful request. 199 // 200 // GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-the-hourly-commit-count-for-each-day 201 func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { 202 u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) 203 req, err := s.client.NewRequest("GET", u, nil) 204 if err != nil { 205 return nil, nil, err 206 } 207 208 var results [][]int 209 resp, err := s.client.Do(ctx, req, &results) 210 211 // convert int slices into Punchcards 212 var cards []*PunchCard 213 for _, result := range results { 214 if len(result) != 3 { 215 continue 216 } 217 card := &PunchCard{ 218 Day: Int(result[0]), 219 Hour: Int(result[1]), 220 Commits: Int(result[2]), 221 } 222 cards = append(cards, card) 223 } 224 225 return cards, resp, err 226 } 227