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 6package github 7 8import ( 9 "context" 10 "fmt" 11 "strings" 12) 13 14// RepositoriesService handles communication with the repository related 15// methods of the GitHub API. 16// 17// GitHub API docs: https://developer.github.com/v3/repos/ 18type RepositoriesService service 19 20// Repository represents a GitHub repository. 21type Repository struct { 22 ID *int64 `json:"id,omitempty"` 23 NodeID *string `json:"node_id,omitempty"` 24 Owner *User `json:"owner,omitempty"` 25 Name *string `json:"name,omitempty"` 26 FullName *string `json:"full_name,omitempty"` 27 Description *string `json:"description,omitempty"` 28 Homepage *string `json:"homepage,omitempty"` 29 CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` 30 DefaultBranch *string `json:"default_branch,omitempty"` 31 MasterBranch *string `json:"master_branch,omitempty"` 32 CreatedAt *Timestamp `json:"created_at,omitempty"` 33 PushedAt *Timestamp `json:"pushed_at,omitempty"` 34 UpdatedAt *Timestamp `json:"updated_at,omitempty"` 35 HTMLURL *string `json:"html_url,omitempty"` 36 CloneURL *string `json:"clone_url,omitempty"` 37 GitURL *string `json:"git_url,omitempty"` 38 MirrorURL *string `json:"mirror_url,omitempty"` 39 SSHURL *string `json:"ssh_url,omitempty"` 40 SVNURL *string `json:"svn_url,omitempty"` 41 Language *string `json:"language,omitempty"` 42 Fork *bool `json:"fork,omitempty"` 43 ForksCount *int `json:"forks_count,omitempty"` 44 NetworkCount *int `json:"network_count,omitempty"` 45 OpenIssuesCount *int `json:"open_issues_count,omitempty"` 46 StargazersCount *int `json:"stargazers_count,omitempty"` 47 SubscribersCount *int `json:"subscribers_count,omitempty"` 48 WatchersCount *int `json:"watchers_count,omitempty"` 49 Size *int `json:"size,omitempty"` 50 AutoInit *bool `json:"auto_init,omitempty"` 51 Parent *Repository `json:"parent,omitempty"` 52 Source *Repository `json:"source,omitempty"` 53 Organization *Organization `json:"organization,omitempty"` 54 Permissions *map[string]bool `json:"permissions,omitempty"` 55 AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` 56 AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` 57 AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` 58 Topics []string `json:"topics,omitempty"` 59 60 // Only provided when using RepositoriesService.Get while in preview 61 License *License `json:"license,omitempty"` 62 63 // Additional mutable fields when creating and editing a repository 64 Private *bool `json:"private,omitempty"` 65 HasIssues *bool `json:"has_issues,omitempty"` 66 HasWiki *bool `json:"has_wiki,omitempty"` 67 HasPages *bool `json:"has_pages,omitempty"` 68 HasProjects *bool `json:"has_projects,omitempty"` 69 HasDownloads *bool `json:"has_downloads,omitempty"` 70 LicenseTemplate *string `json:"license_template,omitempty"` 71 GitignoreTemplate *string `json:"gitignore_template,omitempty"` 72 Archived *bool `json:"archived,omitempty"` 73 74 // Creating an organization repository. Required for non-owners. 75 TeamID *int64 `json:"team_id,omitempty"` 76 77 // API URLs 78 URL *string `json:"url,omitempty"` 79 ArchiveURL *string `json:"archive_url,omitempty"` 80 AssigneesURL *string `json:"assignees_url,omitempty"` 81 BlobsURL *string `json:"blobs_url,omitempty"` 82 BranchesURL *string `json:"branches_url,omitempty"` 83 CollaboratorsURL *string `json:"collaborators_url,omitempty"` 84 CommentsURL *string `json:"comments_url,omitempty"` 85 CommitsURL *string `json:"commits_url,omitempty"` 86 CompareURL *string `json:"compare_url,omitempty"` 87 ContentsURL *string `json:"contents_url,omitempty"` 88 ContributorsURL *string `json:"contributors_url,omitempty"` 89 DeploymentsURL *string `json:"deployments_url,omitempty"` 90 DownloadsURL *string `json:"downloads_url,omitempty"` 91 EventsURL *string `json:"events_url,omitempty"` 92 ForksURL *string `json:"forks_url,omitempty"` 93 GitCommitsURL *string `json:"git_commits_url,omitempty"` 94 GitRefsURL *string `json:"git_refs_url,omitempty"` 95 GitTagsURL *string `json:"git_tags_url,omitempty"` 96 HooksURL *string `json:"hooks_url,omitempty"` 97 IssueCommentURL *string `json:"issue_comment_url,omitempty"` 98 IssueEventsURL *string `json:"issue_events_url,omitempty"` 99 IssuesURL *string `json:"issues_url,omitempty"` 100 KeysURL *string `json:"keys_url,omitempty"` 101 LabelsURL *string `json:"labels_url,omitempty"` 102 LanguagesURL *string `json:"languages_url,omitempty"` 103 MergesURL *string `json:"merges_url,omitempty"` 104 MilestonesURL *string `json:"milestones_url,omitempty"` 105 NotificationsURL *string `json:"notifications_url,omitempty"` 106 PullsURL *string `json:"pulls_url,omitempty"` 107 ReleasesURL *string `json:"releases_url,omitempty"` 108 StargazersURL *string `json:"stargazers_url,omitempty"` 109 StatusesURL *string `json:"statuses_url,omitempty"` 110 SubscribersURL *string `json:"subscribers_url,omitempty"` 111 SubscriptionURL *string `json:"subscription_url,omitempty"` 112 TagsURL *string `json:"tags_url,omitempty"` 113 TreesURL *string `json:"trees_url,omitempty"` 114 TeamsURL *string `json:"teams_url,omitempty"` 115 116 // TextMatches is only populated from search results that request text matches 117 // See: search.go and https://developer.github.com/v3/search/#text-match-metadata 118 TextMatches []TextMatch `json:"text_matches,omitempty"` 119} 120 121func (r Repository) String() string { 122 return Stringify(r) 123} 124 125// RepositoryListOptions specifies the optional parameters to the 126// RepositoriesService.List method. 127type RepositoryListOptions struct { 128 // Visibility of repositories to list. Can be one of all, public, or private. 129 // Default: all 130 Visibility string `url:"visibility,omitempty"` 131 132 // List repos of given affiliation[s]. 133 // Comma-separated list of values. Can include: 134 // * owner: Repositories that are owned by the authenticated user. 135 // * collaborator: Repositories that the user has been added to as a 136 // collaborator. 137 // * organization_member: Repositories that the user has access to through 138 // being a member of an organization. This includes every repository on 139 // every team that the user is on. 140 // Default: owner,collaborator,organization_member 141 Affiliation string `url:"affiliation,omitempty"` 142 143 // Type of repositories to list. 144 // Can be one of all, owner, public, private, member. Default: all 145 // Will cause a 422 error if used in the same request as visibility or 146 // affiliation. 147 Type string `url:"type,omitempty"` 148 149 // How to sort the repository list. Can be one of created, updated, pushed, 150 // full_name. Default: full_name 151 Sort string `url:"sort,omitempty"` 152 153 // Direction in which to sort repositories. Can be one of asc or desc. 154 // Default: when using full_name: asc; otherwise desc 155 Direction string `url:"direction,omitempty"` 156 157 ListOptions 158} 159 160// List the repositories for a user. Passing the empty string will list 161// repositories for the authenticated user. 162// 163// GitHub API docs: https://developer.github.com/v3/repos/#list-user-repositories 164func (s *RepositoriesService) List(ctx context.Context, user string, opt *RepositoryListOptions) ([]*Repository, *Response, error) { 165 var u string 166 if user != "" { 167 u = fmt.Sprintf("users/%v/repos", user) 168 } else { 169 u = "user/repos" 170 } 171 u, err := addOptions(u, opt) 172 if err != nil { 173 return nil, nil, err 174 } 175 176 req, err := s.client.NewRequest("GET", u, nil) 177 if err != nil { 178 return nil, nil, err 179 } 180 181 // TODO: remove custom Accept headers when APIs fully launch. 182 acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} 183 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 184 185 var repos []*Repository 186 resp, err := s.client.Do(ctx, req, &repos) 187 if err != nil { 188 return nil, resp, err 189 } 190 191 return repos, resp, nil 192} 193 194// RepositoryListByOrgOptions specifies the optional parameters to the 195// RepositoriesService.ListByOrg method. 196type RepositoryListByOrgOptions struct { 197 // Type of repositories to list. Possible values are: all, public, private, 198 // forks, sources, member. Default is "all". 199 Type string `url:"type,omitempty"` 200 201 ListOptions 202} 203 204// ListByOrg lists the repositories for an organization. 205// 206// GitHub API docs: https://developer.github.com/v3/repos/#list-organization-repositories 207func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opt *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { 208 u := fmt.Sprintf("orgs/%v/repos", org) 209 u, err := addOptions(u, opt) 210 if err != nil { 211 return nil, nil, err 212 } 213 214 req, err := s.client.NewRequest("GET", u, nil) 215 if err != nil { 216 return nil, nil, err 217 } 218 219 // TODO: remove custom Accept headers when APIs fully launch. 220 acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} 221 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 222 223 var repos []*Repository 224 resp, err := s.client.Do(ctx, req, &repos) 225 if err != nil { 226 return nil, resp, err 227 } 228 229 return repos, resp, nil 230} 231 232// RepositoryListAllOptions specifies the optional parameters to the 233// RepositoriesService.ListAll method. 234type RepositoryListAllOptions struct { 235 // ID of the last repository seen 236 Since int64 `url:"since,omitempty"` 237} 238 239// ListAll lists all GitHub repositories in the order that they were created. 240// 241// GitHub API docs: https://developer.github.com/v3/repos/#list-all-public-repositories 242func (s *RepositoriesService) ListAll(ctx context.Context, opt *RepositoryListAllOptions) ([]*Repository, *Response, error) { 243 u, err := addOptions("repositories", opt) 244 if err != nil { 245 return nil, nil, err 246 } 247 248 req, err := s.client.NewRequest("GET", u, nil) 249 if err != nil { 250 return nil, nil, err 251 } 252 253 var repos []*Repository 254 resp, err := s.client.Do(ctx, req, &repos) 255 if err != nil { 256 return nil, resp, err 257 } 258 259 return repos, resp, nil 260} 261 262// Create a new repository. If an organization is specified, the new 263// repository will be created under that org. If the empty string is 264// specified, it will be created for the authenticated user. 265// 266// GitHub API docs: https://developer.github.com/v3/repos/#create 267func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { 268 var u string 269 if org != "" { 270 u = fmt.Sprintf("orgs/%v/repos", org) 271 } else { 272 u = "user/repos" 273 } 274 275 req, err := s.client.NewRequest("POST", u, repo) 276 if err != nil { 277 return nil, nil, err 278 } 279 280 r := new(Repository) 281 resp, err := s.client.Do(ctx, req, r) 282 if err != nil { 283 return nil, resp, err 284 } 285 286 return r, resp, nil 287} 288 289// Get fetches a repository. 290// 291// GitHub API docs: https://developer.github.com/v3/repos/#get 292func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { 293 u := fmt.Sprintf("repos/%v/%v", owner, repo) 294 req, err := s.client.NewRequest("GET", u, nil) 295 if err != nil { 296 return nil, nil, err 297 } 298 299 // TODO: remove custom Accept header when the license support fully launches 300 // https://developer.github.com/v3/licenses/#get-a-repositorys-license 301 acceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview} 302 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 303 304 repository := new(Repository) 305 resp, err := s.client.Do(ctx, req, repository) 306 if err != nil { 307 return nil, resp, err 308 } 309 310 return repository, resp, nil 311} 312 313// GetCodeOfConduct gets the contents of a repository's code of conduct. 314// 315// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#get-the-contents-of-a-repositorys-code-of-conduct 316func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { 317 u := fmt.Sprintf("repos/%v/%v/community/code_of_conduct", owner, repo) 318 req, err := s.client.NewRequest("GET", u, nil) 319 if err != nil { 320 return nil, nil, err 321 } 322 323 // TODO: remove custom Accept header when this API fully launches. 324 req.Header.Set("Accept", mediaTypeCodesOfConductPreview) 325 326 coc := new(CodeOfConduct) 327 resp, err := s.client.Do(ctx, req, coc) 328 if err != nil { 329 return nil, resp, err 330 } 331 332 return coc, resp, nil 333} 334 335// GetByID fetches a repository. 336// 337// Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id. 338func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { 339 u := fmt.Sprintf("repositories/%d", id) 340 req, err := s.client.NewRequest("GET", u, nil) 341 if err != nil { 342 return nil, nil, err 343 } 344 345 repository := new(Repository) 346 resp, err := s.client.Do(ctx, req, repository) 347 if err != nil { 348 return nil, resp, err 349 } 350 351 return repository, resp, nil 352} 353 354// Edit updates a repository. 355// 356// GitHub API docs: https://developer.github.com/v3/repos/#edit 357func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { 358 u := fmt.Sprintf("repos/%v/%v", owner, repo) 359 req, err := s.client.NewRequest("PATCH", u, repository) 360 if err != nil { 361 return nil, nil, err 362 } 363 364 r := new(Repository) 365 resp, err := s.client.Do(ctx, req, r) 366 if err != nil { 367 return nil, resp, err 368 } 369 370 return r, resp, nil 371} 372 373// Delete a repository. 374// 375// GitHub API docs: https://developer.github.com/v3/repos/#delete-a-repository 376func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { 377 u := fmt.Sprintf("repos/%v/%v", owner, repo) 378 req, err := s.client.NewRequest("DELETE", u, nil) 379 if err != nil { 380 return nil, err 381 } 382 383 return s.client.Do(ctx, req, nil) 384} 385 386// Contributor represents a repository contributor 387type Contributor struct { 388 Login *string `json:"login,omitempty"` 389 ID *int64 `json:"id,omitempty"` 390 AvatarURL *string `json:"avatar_url,omitempty"` 391 GravatarID *string `json:"gravatar_id,omitempty"` 392 URL *string `json:"url,omitempty"` 393 HTMLURL *string `json:"html_url,omitempty"` 394 FollowersURL *string `json:"followers_url,omitempty"` 395 FollowingURL *string `json:"following_url,omitempty"` 396 GistsURL *string `json:"gists_url,omitempty"` 397 StarredURL *string `json:"starred_url,omitempty"` 398 SubscriptionsURL *string `json:"subscriptions_url,omitempty"` 399 OrganizationsURL *string `json:"organizations_url,omitempty"` 400 ReposURL *string `json:"repos_url,omitempty"` 401 EventsURL *string `json:"events_url,omitempty"` 402 ReceivedEventsURL *string `json:"received_events_url,omitempty"` 403 Type *string `json:"type,omitempty"` 404 SiteAdmin *bool `json:"site_admin,omitempty"` 405 Contributions *int `json:"contributions,omitempty"` 406} 407 408// ListContributorsOptions specifies the optional parameters to the 409// RepositoriesService.ListContributors method. 410type ListContributorsOptions struct { 411 // Include anonymous contributors in results or not 412 Anon string `url:"anon,omitempty"` 413 414 ListOptions 415} 416 417// ListContributors lists contributors for a repository. 418// 419// GitHub API docs: https://developer.github.com/v3/repos/#list-contributors 420func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opt *ListContributorsOptions) ([]*Contributor, *Response, error) { 421 u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) 422 u, err := addOptions(u, opt) 423 if err != nil { 424 return nil, nil, err 425 } 426 427 req, err := s.client.NewRequest("GET", u, nil) 428 if err != nil { 429 return nil, nil, err 430 } 431 432 var contributor []*Contributor 433 resp, err := s.client.Do(ctx, req, &contributor) 434 if err != nil { 435 return nil, nil, err 436 } 437 438 return contributor, resp, nil 439} 440 441// ListLanguages lists languages for the specified repository. The returned map 442// specifies the languages and the number of bytes of code written in that 443// language. For example: 444// 445// { 446// "C": 78769, 447// "Python": 7769 448// } 449// 450// GitHub API docs: https://developer.github.com/v3/repos/#list-languages 451func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { 452 u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) 453 req, err := s.client.NewRequest("GET", u, nil) 454 if err != nil { 455 return nil, nil, err 456 } 457 458 languages := make(map[string]int) 459 resp, err := s.client.Do(ctx, req, &languages) 460 if err != nil { 461 return nil, resp, err 462 } 463 464 return languages, resp, nil 465} 466 467// ListTeams lists the teams for the specified repository. 468// 469// GitHub API docs: https://developer.github.com/v3/repos/#list-teams 470func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Team, *Response, error) { 471 u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) 472 u, err := addOptions(u, opt) 473 if err != nil { 474 return nil, nil, err 475 } 476 477 req, err := s.client.NewRequest("GET", u, nil) 478 if err != nil { 479 return nil, nil, err 480 } 481 482 req.Header.Set("Accept", mediaTypeNestedTeamsPreview) 483 484 var teams []*Team 485 resp, err := s.client.Do(ctx, req, &teams) 486 if err != nil { 487 return nil, resp, err 488 } 489 490 return teams, resp, nil 491} 492 493// RepositoryTag represents a repository tag. 494type RepositoryTag struct { 495 Name *string `json:"name,omitempty"` 496 Commit *Commit `json:"commit,omitempty"` 497 ZipballURL *string `json:"zipball_url,omitempty"` 498 TarballURL *string `json:"tarball_url,omitempty"` 499} 500 501// ListTags lists tags for the specified repository. 502// 503// GitHub API docs: https://developer.github.com/v3/repos/#list-tags 504func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*RepositoryTag, *Response, error) { 505 u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) 506 u, err := addOptions(u, opt) 507 if err != nil { 508 return nil, nil, err 509 } 510 511 req, err := s.client.NewRequest("GET", u, nil) 512 if err != nil { 513 return nil, nil, err 514 } 515 516 var tags []*RepositoryTag 517 resp, err := s.client.Do(ctx, req, &tags) 518 if err != nil { 519 return nil, resp, err 520 } 521 522 return tags, resp, nil 523} 524 525// Branch represents a repository branch 526type Branch struct { 527 Name *string `json:"name,omitempty"` 528 Commit *RepositoryCommit `json:"commit,omitempty"` 529 Protected *bool `json:"protected,omitempty"` 530} 531 532// Protection represents a repository branch's protection. 533type Protection struct { 534 RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` 535 RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` 536 EnforceAdmins *AdminEnforcement `json:"enforce_admins"` 537 Restrictions *BranchRestrictions `json:"restrictions"` 538} 539 540// ProtectionRequest represents a request to create/edit a branch's protection. 541type ProtectionRequest struct { 542 RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` 543 RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` 544 EnforceAdmins bool `json:"enforce_admins"` 545 Restrictions *BranchRestrictionsRequest `json:"restrictions"` 546} 547 548// RequiredStatusChecks represents the protection status of a individual branch. 549type RequiredStatusChecks struct { 550 // Require branches to be up to date before merging. (Required.) 551 Strict bool `json:"strict"` 552 // The list of status checks to require in order to merge into this 553 // branch. (Required; use []string{} instead of nil for empty list.) 554 Contexts []string `json:"contexts"` 555} 556 557// RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. 558type RequiredStatusChecksRequest struct { 559 Strict *bool `json:"strict,omitempty"` 560 Contexts []string `json:"contexts,omitempty"` 561} 562 563// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. 564type PullRequestReviewsEnforcement struct { 565 // Specifies which users and teams can dismiss pull request reviews. 566 DismissalRestrictions DismissalRestrictions `json:"dismissal_restrictions"` 567 // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. 568 DismissStaleReviews bool `json:"dismiss_stale_reviews"` 569 // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. 570 RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` 571 // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. 572 // Valid values are 1-6. 573 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 574} 575 576// PullRequestReviewsEnforcementRequest represents request to set the pull request review 577// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above 578// because the request structure is different from the response structure. 579type PullRequestReviewsEnforcementRequest struct { 580 // Specifies which users and teams should be allowed to dismiss pull request reviews. 581 // User and team dismissal restrictions are only available for 582 // organization-owned repositories. Must be nil for personal repositories. 583 DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` 584 // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) 585 DismissStaleReviews bool `json:"dismiss_stale_reviews"` 586 // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. 587 RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` 588 // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. 589 // Valid values are 1-6. 590 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 591} 592 593// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review 594// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above 595// because the patch request does not require all fields to be initialized. 596type PullRequestReviewsEnforcementUpdate struct { 597 // Specifies which users and teams can dismiss pull request reviews. Can be omitted. 598 DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` 599 // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. 600 DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` 601 // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. 602 RequireCodeOwnerReviews bool `json:"require_code_owner_reviews,omitempty"` 603 // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. 604 // Valid values are 1 - 6. 605 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 606} 607 608// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. 609type AdminEnforcement struct { 610 URL *string `json:"url,omitempty"` 611 Enabled bool `json:"enabled"` 612} 613 614// BranchRestrictions represents the restriction that only certain users or 615// teams may push to a branch. 616type BranchRestrictions struct { 617 // The list of user logins with push access. 618 Users []*User `json:"users"` 619 // The list of team slugs with push access. 620 Teams []*Team `json:"teams"` 621} 622 623// BranchRestrictionsRequest represents the request to create/edit the 624// restriction that only certain users or teams may push to a branch. It is 625// separate from BranchRestrictions above because the request structure is 626// different from the response structure. 627type BranchRestrictionsRequest struct { 628 // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) 629 Users []string `json:"users"` 630 // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) 631 Teams []string `json:"teams"` 632} 633 634// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. 635type DismissalRestrictions struct { 636 // The list of users who can dimiss pull request reviews. 637 Users []*User `json:"users"` 638 // The list of teams which can dismiss pull request reviews. 639 Teams []*Team `json:"teams"` 640} 641 642// DismissalRestrictionsRequest represents the request to create/edit the 643// restriction to allows only specific users or teams to dimiss pull request reviews. It is 644// separate from DismissalRestrictions above because the request structure is 645// different from the response structure. 646// Note: Both Users and Teams must be nil, or both must be non-nil. 647type DismissalRestrictionsRequest struct { 648 // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) 649 Users *[]string `json:"users,omitempty"` 650 // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) 651 Teams *[]string `json:"teams,omitempty"` 652} 653 654// ListBranches lists branches for the specified repository. 655// 656// GitHub API docs: https://developer.github.com/v3/repos/#list-branches 657func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opt *ListOptions) ([]*Branch, *Response, error) { 658 u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) 659 u, err := addOptions(u, opt) 660 if err != nil { 661 return nil, nil, err 662 } 663 664 req, err := s.client.NewRequest("GET", u, nil) 665 if err != nil { 666 return nil, nil, err 667 } 668 669 // TODO: remove custom Accept header when this API fully launches 670 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 671 672 var branches []*Branch 673 resp, err := s.client.Do(ctx, req, &branches) 674 if err != nil { 675 return nil, resp, err 676 } 677 678 return branches, resp, nil 679} 680 681// GetBranch gets the specified branch for a repository. 682// 683// GitHub API docs: https://developer.github.com/v3/repos/#get-branch 684func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string) (*Branch, *Response, error) { 685 u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) 686 req, err := s.client.NewRequest("GET", u, nil) 687 if err != nil { 688 return nil, nil, err 689 } 690 691 // TODO: remove custom Accept header when this API fully launches 692 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 693 694 b := new(Branch) 695 resp, err := s.client.Do(ctx, req, b) 696 if err != nil { 697 return nil, resp, err 698 } 699 700 return b, resp, nil 701} 702 703// GetBranchProtection gets the protection of a given branch. 704// 705// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-branch-protection 706func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { 707 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) 708 req, err := s.client.NewRequest("GET", u, nil) 709 if err != nil { 710 return nil, nil, err 711 } 712 713 // TODO: remove custom Accept header when this API fully launches 714 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 715 716 p := new(Protection) 717 resp, err := s.client.Do(ctx, req, p) 718 if err != nil { 719 return nil, resp, err 720 } 721 722 return p, resp, nil 723} 724 725// GetRequiredStatusChecks gets the required status checks for a given protected branch. 726// 727// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-required-status-checks-of-protected-branch 728func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { 729 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) 730 req, err := s.client.NewRequest("GET", u, nil) 731 if err != nil { 732 return nil, nil, err 733 } 734 735 // TODO: remove custom Accept header when this API fully launches 736 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 737 738 p := new(RequiredStatusChecks) 739 resp, err := s.client.Do(ctx, req, p) 740 if err != nil { 741 return nil, resp, err 742 } 743 744 return p, resp, nil 745} 746 747// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. 748// 749// GitHub API docs: https://developer.github.com/v3/repos/branches/#list-required-status-checks-contexts-of-protected-branch 750func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { 751 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) 752 req, err := s.client.NewRequest("GET", u, nil) 753 if err != nil { 754 return nil, nil, err 755 } 756 757 // TODO: remove custom Accept header when this API fully launches 758 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 759 760 resp, err = s.client.Do(ctx, req, &contexts) 761 if err != nil { 762 return nil, resp, err 763 } 764 765 return contexts, resp, nil 766} 767 768// UpdateBranchProtection updates the protection of a given branch. 769// 770// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-branch-protection 771func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { 772 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) 773 req, err := s.client.NewRequest("PUT", u, preq) 774 if err != nil { 775 return nil, nil, err 776 } 777 778 // TODO: remove custom Accept header when this API fully launches 779 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 780 781 p := new(Protection) 782 resp, err := s.client.Do(ctx, req, p) 783 if err != nil { 784 return nil, resp, err 785 } 786 787 return p, resp, nil 788} 789 790// RemoveBranchProtection removes the protection of a given branch. 791// 792// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-branch-protection 793func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { 794 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) 795 req, err := s.client.NewRequest("DELETE", u, nil) 796 if err != nil { 797 return nil, err 798 } 799 800 // TODO: remove custom Accept header when this API fully launches 801 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 802 803 return s.client.Do(ctx, req, nil) 804} 805 806// UpdateRequiredStatusChecks updates the required status checks for a given protected branch. 807// 808// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-required-status-checks-of-protected-branch 809func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { 810 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) 811 req, err := s.client.NewRequest("PATCH", u, sreq) 812 if err != nil { 813 return nil, nil, err 814 } 815 816 sc := new(RequiredStatusChecks) 817 resp, err := s.client.Do(ctx, req, sc) 818 if err != nil { 819 return nil, resp, err 820 } 821 822 return sc, resp, nil 823} 824 825// License gets the contents of a repository's license if one is detected. 826// 827// GitHub API docs: https://developer.github.com/v3/licenses/#get-the-contents-of-a-repositorys-license 828func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { 829 u := fmt.Sprintf("repos/%v/%v/license", owner, repo) 830 req, err := s.client.NewRequest("GET", u, nil) 831 if err != nil { 832 return nil, nil, err 833 } 834 835 r := &RepositoryLicense{} 836 resp, err := s.client.Do(ctx, req, r) 837 if err != nil { 838 return nil, resp, err 839 } 840 841 return r, resp, nil 842} 843 844// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. 845// 846// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-pull-request-review-enforcement-of-protected-branch 847func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { 848 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 849 req, err := s.client.NewRequest("GET", u, nil) 850 if err != nil { 851 return nil, nil, err 852 } 853 854 // TODO: remove custom Accept header when this API fully launches 855 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 856 857 r := new(PullRequestReviewsEnforcement) 858 resp, err := s.client.Do(ctx, req, r) 859 if err != nil { 860 return nil, resp, err 861 } 862 863 return r, resp, nil 864} 865 866// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. 867// It requires admin access and branch protection to be enabled. 868// 869// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch 870func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { 871 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 872 req, err := s.client.NewRequest("PATCH", u, patch) 873 if err != nil { 874 return nil, nil, err 875 } 876 877 // TODO: remove custom Accept header when this API fully launches 878 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 879 880 r := new(PullRequestReviewsEnforcement) 881 resp, err := s.client.Do(ctx, req, r) 882 if err != nil { 883 return nil, resp, err 884 } 885 886 return r, resp, err 887} 888 889// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. 890// It requires admin access and branch protection to be enabled. 891// 892// GitHub API docs: https://developer.github.com/v3/repos/branches/#update-pull-request-review-enforcement-of-protected-branch 893func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { 894 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 895 896 data := struct { 897 R []interface{} `json:"dismissal_restrictions"` 898 }{[]interface{}{}} 899 900 req, err := s.client.NewRequest("PATCH", u, data) 901 if err != nil { 902 return nil, nil, err 903 } 904 905 // TODO: remove custom Accept header when this API fully launches 906 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 907 908 r := new(PullRequestReviewsEnforcement) 909 resp, err := s.client.Do(ctx, req, r) 910 if err != nil { 911 return nil, resp, err 912 } 913 914 return r, resp, err 915} 916 917// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. 918// 919// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-pull-request-review-enforcement-of-protected-branch 920func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { 921 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) 922 req, err := s.client.NewRequest("DELETE", u, nil) 923 if err != nil { 924 return nil, err 925 } 926 927 // TODO: remove custom Accept header when this API fully launches 928 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 929 930 return s.client.Do(ctx, req, nil) 931} 932 933// GetAdminEnforcement gets admin enforcement information of a protected branch. 934// 935// GitHub API docs: https://developer.github.com/v3/repos/branches/#get-admin-enforcement-of-protected-branch 936func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { 937 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) 938 req, err := s.client.NewRequest("GET", u, nil) 939 if err != nil { 940 return nil, nil, err 941 } 942 943 // TODO: remove custom Accept header when this API fully launches 944 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 945 946 r := new(AdminEnforcement) 947 resp, err := s.client.Do(ctx, req, r) 948 if err != nil { 949 return nil, resp, err 950 } 951 952 return r, resp, nil 953} 954 955// AddAdminEnforcement adds admin enforcement to a protected branch. 956// It requires admin access and branch protection to be enabled. 957// 958// GitHub API docs: https://developer.github.com/v3/repos/branches/#add-admin-enforcement-of-protected-branch 959func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { 960 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) 961 req, err := s.client.NewRequest("POST", u, nil) 962 if err != nil { 963 return nil, nil, err 964 } 965 966 // TODO: remove custom Accept header when this API fully launches 967 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 968 969 r := new(AdminEnforcement) 970 resp, err := s.client.Do(ctx, req, r) 971 if err != nil { 972 return nil, resp, err 973 } 974 975 return r, resp, err 976} 977 978// RemoveAdminEnforcement removes admin enforcement from a protected branch. 979// 980// GitHub API docs: https://developer.github.com/v3/repos/branches/#remove-admin-enforcement-of-protected-branch 981func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { 982 u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) 983 req, err := s.client.NewRequest("DELETE", u, nil) 984 if err != nil { 985 return nil, err 986 } 987 988 // TODO: remove custom Accept header when this API fully launches 989 req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) 990 991 return s.client.Do(ctx, req, nil) 992} 993 994// repositoryTopics represents a collection of repository topics. 995type repositoryTopics struct { 996 Names []string `json:"names"` 997} 998 999// ListAllTopics lists topics for a repository. 1000// 1001// GitHub API docs: https://developer.github.com/v3/repos/#list-all-topics-for-a-repository 1002func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { 1003 u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) 1004 req, err := s.client.NewRequest("GET", u, nil) 1005 if err != nil { 1006 return nil, nil, err 1007 } 1008 1009 // TODO: remove custom Accept header when this API fully launches. 1010 req.Header.Set("Accept", mediaTypeTopicsPreview) 1011 1012 topics := new(repositoryTopics) 1013 resp, err := s.client.Do(ctx, req, topics) 1014 if err != nil { 1015 return nil, resp, err 1016 } 1017 1018 return topics.Names, resp, nil 1019} 1020 1021// ReplaceAllTopics replaces topics for a repository. 1022// 1023// GitHub API docs: https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository 1024func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { 1025 u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) 1026 t := &repositoryTopics{ 1027 Names: topics, 1028 } 1029 if t.Names == nil { 1030 t.Names = []string{} 1031 } 1032 req, err := s.client.NewRequest("PUT", u, t) 1033 if err != nil { 1034 return nil, nil, err 1035 } 1036 1037 // TODO: remove custom Accept header when this API fully launches. 1038 req.Header.Set("Accept", mediaTypeTopicsPreview) 1039 1040 t = new(repositoryTopics) 1041 resp, err := s.client.Do(ctx, req, t) 1042 if err != nil { 1043 return nil, resp, err 1044 } 1045 1046 return t.Names, resp, nil 1047} 1048 1049// TransferRequest represents a request to transfer a repository. 1050type TransferRequest struct { 1051 NewOwner string `json:"new_owner"` 1052 TeamID []int64 `json:"team_ids,omitempty"` 1053} 1054 1055// Transfer transfers a repository from one account or organization to another. 1056// 1057// This method might return an *AcceptedError and a status code of 1058// 202. This is because this is the status that GitHub returns to signify that 1059// it has now scheduled the transfer of the repository in a background task. 1060// A follow up request, after a delay of a second or so, should result 1061// in a successful request. 1062// 1063// GitHub API docs: https://developer.github.com/v3/repos/#transfer-a-repository 1064func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { 1065 u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) 1066 1067 req, err := s.client.NewRequest("POST", u, &transfer) 1068 if err != nil { 1069 return nil, nil, err 1070 } 1071 1072 // TODO: remove custom Accept header when this API fully launches. 1073 req.Header.Set("Accept", mediaTypeRepositoryTransferPreview) 1074 1075 r := new(Repository) 1076 resp, err := s.client.Do(ctx, req, r) 1077 if err != nil { 1078 return nil, resp, err 1079 } 1080 1081 return r, resp, nil 1082} 1083