repos.go 39 KB

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