...

Source file src/github.com/google/go-github/v47/github/repos.go

Documentation: github.com/google/go-github/v47/github

     1  // Copyright 2013 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"errors"
    12  	"fmt"
    13  	"net/http"
    14  	"strings"
    15  )
    16  
    17  const githubBranchNotProtected string = "Branch not protected"
    18  
    19  var ErrBranchNotProtected = errors.New("branch is not protected")
    20  
    21  // RepositoriesService handles communication with the repository related
    22  // methods of the GitHub API.
    23  //
    24  // GitHub API docs: https://docs.github.com/en/rest/repos/
    25  type RepositoriesService service
    26  
    27  // Repository represents a GitHub repository.
    28  type Repository struct {
    29  	ID                        *int64          `json:"id,omitempty"`
    30  	NodeID                    *string         `json:"node_id,omitempty"`
    31  	Owner                     *User           `json:"owner,omitempty"`
    32  	Name                      *string         `json:"name,omitempty"`
    33  	FullName                  *string         `json:"full_name,omitempty"`
    34  	Description               *string         `json:"description,omitempty"`
    35  	Homepage                  *string         `json:"homepage,omitempty"`
    36  	CodeOfConduct             *CodeOfConduct  `json:"code_of_conduct,omitempty"`
    37  	DefaultBranch             *string         `json:"default_branch,omitempty"`
    38  	MasterBranch              *string         `json:"master_branch,omitempty"`
    39  	CreatedAt                 *Timestamp      `json:"created_at,omitempty"`
    40  	PushedAt                  *Timestamp      `json:"pushed_at,omitempty"`
    41  	UpdatedAt                 *Timestamp      `json:"updated_at,omitempty"`
    42  	HTMLURL                   *string         `json:"html_url,omitempty"`
    43  	CloneURL                  *string         `json:"clone_url,omitempty"`
    44  	GitURL                    *string         `json:"git_url,omitempty"`
    45  	MirrorURL                 *string         `json:"mirror_url,omitempty"`
    46  	SSHURL                    *string         `json:"ssh_url,omitempty"`
    47  	SVNURL                    *string         `json:"svn_url,omitempty"`
    48  	Language                  *string         `json:"language,omitempty"`
    49  	Fork                      *bool           `json:"fork,omitempty"`
    50  	ForksCount                *int            `json:"forks_count,omitempty"`
    51  	NetworkCount              *int            `json:"network_count,omitempty"`
    52  	OpenIssuesCount           *int            `json:"open_issues_count,omitempty"`
    53  	OpenIssues                *int            `json:"open_issues,omitempty"` // Deprecated: Replaced by OpenIssuesCount. For backward compatibility OpenIssues is still populated.
    54  	StargazersCount           *int            `json:"stargazers_count,omitempty"`
    55  	SubscribersCount          *int            `json:"subscribers_count,omitempty"`
    56  	WatchersCount             *int            `json:"watchers_count,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility WatchersCount is still populated.
    57  	Watchers                  *int            `json:"watchers,omitempty"`       // Deprecated: Replaced by StargazersCount. For backward compatibility Watchers is still populated.
    58  	Size                      *int            `json:"size,omitempty"`
    59  	AutoInit                  *bool           `json:"auto_init,omitempty"`
    60  	Parent                    *Repository     `json:"parent,omitempty"`
    61  	Source                    *Repository     `json:"source,omitempty"`
    62  	TemplateRepository        *Repository     `json:"template_repository,omitempty"`
    63  	Organization              *Organization   `json:"organization,omitempty"`
    64  	Permissions               map[string]bool `json:"permissions,omitempty"`
    65  	AllowRebaseMerge          *bool           `json:"allow_rebase_merge,omitempty"`
    66  	AllowUpdateBranch         *bool           `json:"allow_update_branch,omitempty"`
    67  	AllowSquashMerge          *bool           `json:"allow_squash_merge,omitempty"`
    68  	AllowMergeCommit          *bool           `json:"allow_merge_commit,omitempty"`
    69  	AllowAutoMerge            *bool           `json:"allow_auto_merge,omitempty"`
    70  	AllowForking              *bool           `json:"allow_forking,omitempty"`
    71  	DeleteBranchOnMerge       *bool           `json:"delete_branch_on_merge,omitempty"`
    72  	UseSquashPRTitleAsDefault *bool           `json:"use_squash_pr_title_as_default,omitempty"`
    73  	SquashMergeCommitTitle    *string         `json:"squash_merge_commit_title,omitempty"`   // Can be one of: "PR_TITLE", "COMMIT_OR_PR_TITLE"
    74  	SquashMergeCommitMessage  *string         `json:"squash_merge_commit_message,omitempty"` // Can be one of: "PR_BODY", "COMMIT_MESSAGES", "BLANK"
    75  	MergeCommitTitle          *string         `json:"merge_commit_title,omitempty"`          // Can be one of: "PR_TITLE", "MERGE_MESSAGE"
    76  	MergeCommitMessage        *string         `json:"merge_commit_message,omitempty"`        // Can be one of: "PR_BODY", "PR_TITLE", "BLANK"
    77  	Topics                    []string        `json:"topics,omitempty"`
    78  	Archived                  *bool           `json:"archived,omitempty"`
    79  	Disabled                  *bool           `json:"disabled,omitempty"`
    80  
    81  	// Only provided when using RepositoriesService.Get while in preview
    82  	License *License `json:"license,omitempty"`
    83  
    84  	// Additional mutable fields when creating and editing a repository
    85  	Private           *bool   `json:"private,omitempty"`
    86  	HasIssues         *bool   `json:"has_issues,omitempty"`
    87  	HasWiki           *bool   `json:"has_wiki,omitempty"`
    88  	HasPages          *bool   `json:"has_pages,omitempty"`
    89  	HasProjects       *bool   `json:"has_projects,omitempty"`
    90  	HasDownloads      *bool   `json:"has_downloads,omitempty"`
    91  	IsTemplate        *bool   `json:"is_template,omitempty"`
    92  	LicenseTemplate   *string `json:"license_template,omitempty"`
    93  	GitignoreTemplate *string `json:"gitignore_template,omitempty"`
    94  
    95  	// Options for configuring Advanced Security and Secret Scanning
    96  	SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"`
    97  
    98  	// Creating an organization repository. Required for non-owners.
    99  	TeamID *int64 `json:"team_id,omitempty"`
   100  
   101  	// API URLs
   102  	URL              *string `json:"url,omitempty"`
   103  	ArchiveURL       *string `json:"archive_url,omitempty"`
   104  	AssigneesURL     *string `json:"assignees_url,omitempty"`
   105  	BlobsURL         *string `json:"blobs_url,omitempty"`
   106  	BranchesURL      *string `json:"branches_url,omitempty"`
   107  	CollaboratorsURL *string `json:"collaborators_url,omitempty"`
   108  	CommentsURL      *string `json:"comments_url,omitempty"`
   109  	CommitsURL       *string `json:"commits_url,omitempty"`
   110  	CompareURL       *string `json:"compare_url,omitempty"`
   111  	ContentsURL      *string `json:"contents_url,omitempty"`
   112  	ContributorsURL  *string `json:"contributors_url,omitempty"`
   113  	DeploymentsURL   *string `json:"deployments_url,omitempty"`
   114  	DownloadsURL     *string `json:"downloads_url,omitempty"`
   115  	EventsURL        *string `json:"events_url,omitempty"`
   116  	ForksURL         *string `json:"forks_url,omitempty"`
   117  	GitCommitsURL    *string `json:"git_commits_url,omitempty"`
   118  	GitRefsURL       *string `json:"git_refs_url,omitempty"`
   119  	GitTagsURL       *string `json:"git_tags_url,omitempty"`
   120  	HooksURL         *string `json:"hooks_url,omitempty"`
   121  	IssueCommentURL  *string `json:"issue_comment_url,omitempty"`
   122  	IssueEventsURL   *string `json:"issue_events_url,omitempty"`
   123  	IssuesURL        *string `json:"issues_url,omitempty"`
   124  	KeysURL          *string `json:"keys_url,omitempty"`
   125  	LabelsURL        *string `json:"labels_url,omitempty"`
   126  	LanguagesURL     *string `json:"languages_url,omitempty"`
   127  	MergesURL        *string `json:"merges_url,omitempty"`
   128  	MilestonesURL    *string `json:"milestones_url,omitempty"`
   129  	NotificationsURL *string `json:"notifications_url,omitempty"`
   130  	PullsURL         *string `json:"pulls_url,omitempty"`
   131  	ReleasesURL      *string `json:"releases_url,omitempty"`
   132  	StargazersURL    *string `json:"stargazers_url,omitempty"`
   133  	StatusesURL      *string `json:"statuses_url,omitempty"`
   134  	SubscribersURL   *string `json:"subscribers_url,omitempty"`
   135  	SubscriptionURL  *string `json:"subscription_url,omitempty"`
   136  	TagsURL          *string `json:"tags_url,omitempty"`
   137  	TreesURL         *string `json:"trees_url,omitempty"`
   138  	TeamsURL         *string `json:"teams_url,omitempty"`
   139  
   140  	// TextMatches is only populated from search results that request text matches
   141  	// See: search.go and https://docs.github.com/en/rest/search/#text-match-metadata
   142  	TextMatches []*TextMatch `json:"text_matches,omitempty"`
   143  
   144  	// Visibility is only used for Create and Edit endpoints. The visibility field
   145  	// overrides the field parameter when both are used.
   146  	// Can be one of public, private or internal.
   147  	Visibility *string `json:"visibility,omitempty"`
   148  
   149  	// RoleName is only returned by the API 'check team permissions for a repository'.
   150  	// See: teams.go (IsTeamRepoByID) https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository
   151  	RoleName *string `json:"role_name,omitempty"`
   152  }
   153  
   154  func (r Repository) String() string {
   155  	return Stringify(r)
   156  }
   157  
   158  // BranchListOptions specifies the optional parameters to the
   159  // RepositoriesService.ListBranches method.
   160  type BranchListOptions struct {
   161  	// Setting to true returns only protected branches.
   162  	// When set to false, only unprotected branches are returned.
   163  	// Omitting this parameter returns all branches.
   164  	// Default: nil
   165  	Protected *bool `url:"protected,omitempty"`
   166  
   167  	ListOptions
   168  }
   169  
   170  // RepositoryListOptions specifies the optional parameters to the
   171  // RepositoriesService.List method.
   172  type RepositoryListOptions struct {
   173  	// Visibility of repositories to list. Can be one of all, public, or private.
   174  	// Default: all
   175  	Visibility string `url:"visibility,omitempty"`
   176  
   177  	// List repos of given affiliation[s].
   178  	// Comma-separated list of values. Can include:
   179  	// * owner: Repositories that are owned by the authenticated user.
   180  	// * collaborator: Repositories that the user has been added to as a
   181  	//   collaborator.
   182  	// * organization_member: Repositories that the user has access to through
   183  	//   being a member of an organization. This includes every repository on
   184  	//   every team that the user is on.
   185  	// Default: owner,collaborator,organization_member
   186  	Affiliation string `url:"affiliation,omitempty"`
   187  
   188  	// Type of repositories to list.
   189  	// Can be one of all, owner, public, private, member. Default: all
   190  	// Will cause a 422 error if used in the same request as visibility or
   191  	// affiliation.
   192  	Type string `url:"type,omitempty"`
   193  
   194  	// How to sort the repository list. Can be one of created, updated, pushed,
   195  	// full_name. Default: full_name
   196  	Sort string `url:"sort,omitempty"`
   197  
   198  	// Direction in which to sort repositories. Can be one of asc or desc.
   199  	// Default: when using full_name: asc; otherwise desc
   200  	Direction string `url:"direction,omitempty"`
   201  
   202  	ListOptions
   203  }
   204  
   205  // SecurityAndAnalysis specifies the optional advanced security features
   206  // that are enabled on a given repository.
   207  type SecurityAndAnalysis struct {
   208  	AdvancedSecurity *AdvancedSecurity `json:"advanced_security,omitempty"`
   209  	SecretScanning   *SecretScanning   `json:"secret_scanning,omitempty"`
   210  }
   211  
   212  func (s SecurityAndAnalysis) String() string {
   213  	return Stringify(s)
   214  }
   215  
   216  // AdvancedSecurity specifies the state of advanced security on a repository.
   217  //
   218  // GitHub API docs: https://docs.github.com/en/github/getting-started-with-github/learning-about-github/about-github-advanced-security
   219  type AdvancedSecurity struct {
   220  	Status *string `json:"status,omitempty"`
   221  }
   222  
   223  func (a AdvancedSecurity) String() string {
   224  	return Stringify(a)
   225  }
   226  
   227  // SecretScanning specifies the state of secret scanning on a repository.
   228  //
   229  // GitHub API docs: https://docs.github.com/en/code-security/secret-security/about-secret-scanning
   230  type SecretScanning struct {
   231  	Status *string `json:"status,omitempty"`
   232  }
   233  
   234  func (s SecretScanning) String() string {
   235  	return Stringify(s)
   236  }
   237  
   238  // List the repositories for a user. Passing the empty string will list
   239  // repositories for the authenticated user.
   240  //
   241  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repositories-for-the-authenticated-user
   242  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repositories-for-a-user
   243  func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) {
   244  	var u string
   245  	if user != "" {
   246  		u = fmt.Sprintf("users/%v/repos", user)
   247  	} else {
   248  		u = "user/repos"
   249  	}
   250  	u, err := addOptions(u, opts)
   251  	if err != nil {
   252  		return nil, nil, err
   253  	}
   254  
   255  	req, err := s.client.NewRequest("GET", u, nil)
   256  	if err != nil {
   257  		return nil, nil, err
   258  	}
   259  
   260  	// TODO: remove custom Accept headers when APIs fully launch.
   261  	acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview}
   262  	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
   263  
   264  	var repos []*Repository
   265  	resp, err := s.client.Do(ctx, req, &repos)
   266  	if err != nil {
   267  		return nil, resp, err
   268  	}
   269  
   270  	return repos, resp, nil
   271  }
   272  
   273  // RepositoryListByOrgOptions specifies the optional parameters to the
   274  // RepositoriesService.ListByOrg method.
   275  type RepositoryListByOrgOptions struct {
   276  	// Type of repositories to list. Possible values are: all, public, private,
   277  	// forks, sources, member. Default is "all".
   278  	Type string `url:"type,omitempty"`
   279  
   280  	// How to sort the repository list. Can be one of created, updated, pushed,
   281  	// full_name. Default is "created".
   282  	Sort string `url:"sort,omitempty"`
   283  
   284  	// Direction in which to sort repositories. Can be one of asc or desc.
   285  	// Default when using full_name: asc; otherwise desc.
   286  	Direction string `url:"direction,omitempty"`
   287  
   288  	ListOptions
   289  }
   290  
   291  // ListByOrg lists the repositories for an organization.
   292  //
   293  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-organization-repositories
   294  func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opts *RepositoryListByOrgOptions) ([]*Repository, *Response, error) {
   295  	u := fmt.Sprintf("orgs/%v/repos", org)
   296  	u, err := addOptions(u, opts)
   297  	if err != nil {
   298  		return nil, nil, err
   299  	}
   300  
   301  	req, err := s.client.NewRequest("GET", u, nil)
   302  	if err != nil {
   303  		return nil, nil, err
   304  	}
   305  
   306  	// TODO: remove custom Accept headers when APIs fully launch.
   307  	acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview}
   308  	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
   309  
   310  	var repos []*Repository
   311  	resp, err := s.client.Do(ctx, req, &repos)
   312  	if err != nil {
   313  		return nil, resp, err
   314  	}
   315  
   316  	return repos, resp, nil
   317  }
   318  
   319  // RepositoryListAllOptions specifies the optional parameters to the
   320  // RepositoriesService.ListAll method.
   321  type RepositoryListAllOptions struct {
   322  	// ID of the last repository seen
   323  	Since int64 `url:"since,omitempty"`
   324  }
   325  
   326  // ListAll lists all GitHub repositories in the order that they were created.
   327  //
   328  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-public-repositories
   329  func (s *RepositoriesService) ListAll(ctx context.Context, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) {
   330  	u, err := addOptions("repositories", opts)
   331  	if err != nil {
   332  		return nil, nil, err
   333  	}
   334  
   335  	req, err := s.client.NewRequest("GET", u, nil)
   336  	if err != nil {
   337  		return nil, nil, err
   338  	}
   339  
   340  	var repos []*Repository
   341  	resp, err := s.client.Do(ctx, req, &repos)
   342  	if err != nil {
   343  		return nil, resp, err
   344  	}
   345  
   346  	return repos, resp, nil
   347  }
   348  
   349  // createRepoRequest is a subset of Repository and is used internally
   350  // by Create to pass only the known fields for the endpoint.
   351  //
   352  // See https://github.com/google/go-github/issues/1014 for more
   353  // information.
   354  type createRepoRequest struct {
   355  	// Name is required when creating a repo.
   356  	Name        *string `json:"name,omitempty"`
   357  	Description *string `json:"description,omitempty"`
   358  	Homepage    *string `json:"homepage,omitempty"`
   359  
   360  	Private     *bool   `json:"private,omitempty"`
   361  	Visibility  *string `json:"visibility,omitempty"`
   362  	HasIssues   *bool   `json:"has_issues,omitempty"`
   363  	HasProjects *bool   `json:"has_projects,omitempty"`
   364  	HasWiki     *bool   `json:"has_wiki,omitempty"`
   365  	IsTemplate  *bool   `json:"is_template,omitempty"`
   366  
   367  	// Creating an organization repository. Required for non-owners.
   368  	TeamID *int64 `json:"team_id,omitempty"`
   369  
   370  	AutoInit                  *bool   `json:"auto_init,omitempty"`
   371  	GitignoreTemplate         *string `json:"gitignore_template,omitempty"`
   372  	LicenseTemplate           *string `json:"license_template,omitempty"`
   373  	AllowSquashMerge          *bool   `json:"allow_squash_merge,omitempty"`
   374  	AllowMergeCommit          *bool   `json:"allow_merge_commit,omitempty"`
   375  	AllowRebaseMerge          *bool   `json:"allow_rebase_merge,omitempty"`
   376  	AllowUpdateBranch         *bool   `json:"allow_update_branch,omitempty"`
   377  	AllowAutoMerge            *bool   `json:"allow_auto_merge,omitempty"`
   378  	AllowForking              *bool   `json:"allow_forking,omitempty"`
   379  	DeleteBranchOnMerge       *bool   `json:"delete_branch_on_merge,omitempty"`
   380  	UseSquashPRTitleAsDefault *bool   `json:"use_squash_pr_title_as_default,omitempty"`
   381  	SquashMergeCommitTitle    *string `json:"squash_merge_commit_title,omitempty"`
   382  	SquashMergeCommitMessage  *string `json:"squash_merge_commit_message,omitempty"`
   383  	MergeCommitTitle          *string `json:"merge_commit_title,omitempty"`
   384  	MergeCommitMessage        *string `json:"merge_commit_message,omitempty"`
   385  }
   386  
   387  // Create a new repository. If an organization is specified, the new
   388  // repository will be created under that org. If the empty string is
   389  // specified, it will be created for the authenticated user.
   390  //
   391  // Note that only a subset of the repo fields are used and repo must
   392  // not be nil.
   393  //
   394  // Also note that this method will return the response without actually
   395  // waiting for GitHub to finish creating the repository and letting the
   396  // changes propagate throughout its servers. You may set up a loop with
   397  // exponential back-off to verify repository's creation.
   398  //
   399  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-for-the-authenticated-user
   400  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-an-organization-repository
   401  func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) {
   402  	var u string
   403  	if org != "" {
   404  		u = fmt.Sprintf("orgs/%v/repos", org)
   405  	} else {
   406  		u = "user/repos"
   407  	}
   408  
   409  	repoReq := &createRepoRequest{
   410  		Name:                      repo.Name,
   411  		Description:               repo.Description,
   412  		Homepage:                  repo.Homepage,
   413  		Private:                   repo.Private,
   414  		Visibility:                repo.Visibility,
   415  		HasIssues:                 repo.HasIssues,
   416  		HasProjects:               repo.HasProjects,
   417  		HasWiki:                   repo.HasWiki,
   418  		IsTemplate:                repo.IsTemplate,
   419  		TeamID:                    repo.TeamID,
   420  		AutoInit:                  repo.AutoInit,
   421  		GitignoreTemplate:         repo.GitignoreTemplate,
   422  		LicenseTemplate:           repo.LicenseTemplate,
   423  		AllowSquashMerge:          repo.AllowSquashMerge,
   424  		AllowMergeCommit:          repo.AllowMergeCommit,
   425  		AllowRebaseMerge:          repo.AllowRebaseMerge,
   426  		AllowUpdateBranch:         repo.AllowUpdateBranch,
   427  		AllowAutoMerge:            repo.AllowAutoMerge,
   428  		AllowForking:              repo.AllowForking,
   429  		DeleteBranchOnMerge:       repo.DeleteBranchOnMerge,
   430  		UseSquashPRTitleAsDefault: repo.UseSquashPRTitleAsDefault,
   431  		SquashMergeCommitTitle:    repo.SquashMergeCommitTitle,
   432  		SquashMergeCommitMessage:  repo.SquashMergeCommitMessage,
   433  		MergeCommitTitle:          repo.MergeCommitTitle,
   434  		MergeCommitMessage:        repo.MergeCommitMessage,
   435  	}
   436  
   437  	req, err := s.client.NewRequest("POST", u, repoReq)
   438  	if err != nil {
   439  		return nil, nil, err
   440  	}
   441  
   442  	acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   443  	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
   444  	r := new(Repository)
   445  	resp, err := s.client.Do(ctx, req, r)
   446  	if err != nil {
   447  		return nil, resp, err
   448  	}
   449  
   450  	return r, resp, nil
   451  }
   452  
   453  // TemplateRepoRequest represents a request to create a repository from a template.
   454  type TemplateRepoRequest struct {
   455  	// Name is required when creating a repo.
   456  	Name        *string `json:"name,omitempty"`
   457  	Owner       *string `json:"owner,omitempty"`
   458  	Description *string `json:"description,omitempty"`
   459  
   460  	IncludeAllBranches *bool `json:"include_all_branches,omitempty"`
   461  	Private            *bool `json:"private,omitempty"`
   462  }
   463  
   464  // CreateFromTemplate generates a repository from a template.
   465  //
   466  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-using-a-template
   467  func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) {
   468  	u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo)
   469  
   470  	req, err := s.client.NewRequest("POST", u, templateRepoReq)
   471  	if err != nil {
   472  		return nil, nil, err
   473  	}
   474  
   475  	req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview)
   476  	r := new(Repository)
   477  	resp, err := s.client.Do(ctx, req, r)
   478  	if err != nil {
   479  		return nil, resp, err
   480  	}
   481  
   482  	return r, resp, nil
   483  }
   484  
   485  // Get fetches a repository.
   486  //
   487  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository
   488  func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) {
   489  	u := fmt.Sprintf("repos/%v/%v", owner, repo)
   490  	req, err := s.client.NewRequest("GET", u, nil)
   491  	if err != nil {
   492  		return nil, nil, err
   493  	}
   494  
   495  	// TODO: remove custom Accept header when the license support fully launches
   496  	// https://docs.github.com/en/rest/licenses/#get-a-repositorys-license
   497  	acceptHeaders := []string{
   498  		mediaTypeCodesOfConductPreview,
   499  		mediaTypeTopicsPreview,
   500  		mediaTypeRepositoryTemplatePreview,
   501  		mediaTypeRepositoryVisibilityPreview,
   502  	}
   503  	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
   504  
   505  	repository := new(Repository)
   506  	resp, err := s.client.Do(ctx, req, repository)
   507  	if err != nil {
   508  		return nil, resp, err
   509  	}
   510  
   511  	return repository, resp, nil
   512  }
   513  
   514  // GetCodeOfConduct gets the contents of a repository's code of conduct.
   515  // Note that https://docs.github.com/en/rest/codes-of-conduct#about-the-codes-of-conduct-api
   516  // says to use the GET /repos/{owner}/{repo} endpoint.
   517  //
   518  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository
   519  func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) {
   520  	u := fmt.Sprintf("repos/%v/%v", owner, repo)
   521  	req, err := s.client.NewRequest("GET", u, nil)
   522  	if err != nil {
   523  		return nil, nil, err
   524  	}
   525  
   526  	// TODO: remove custom Accept header when this API fully launches.
   527  	req.Header.Set("Accept", mediaTypeCodesOfConductPreview)
   528  
   529  	r := new(Repository)
   530  	resp, err := s.client.Do(ctx, req, r)
   531  	if err != nil {
   532  		return nil, resp, err
   533  	}
   534  
   535  	return r.GetCodeOfConduct(), resp, nil
   536  }
   537  
   538  // GetByID fetches a repository.
   539  //
   540  // Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id.
   541  func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) {
   542  	u := fmt.Sprintf("repositories/%d", id)
   543  	req, err := s.client.NewRequest("GET", u, nil)
   544  	if err != nil {
   545  		return nil, nil, err
   546  	}
   547  
   548  	repository := new(Repository)
   549  	resp, err := s.client.Do(ctx, req, repository)
   550  	if err != nil {
   551  		return nil, resp, err
   552  	}
   553  
   554  	return repository, resp, nil
   555  }
   556  
   557  // Edit updates a repository.
   558  //
   559  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository
   560  func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) {
   561  	u := fmt.Sprintf("repos/%v/%v", owner, repo)
   562  	req, err := s.client.NewRequest("PATCH", u, repository)
   563  	if err != nil {
   564  		return nil, nil, err
   565  	}
   566  
   567  	acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   568  	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
   569  	r := new(Repository)
   570  	resp, err := s.client.Do(ctx, req, r)
   571  	if err != nil {
   572  		return nil, resp, err
   573  	}
   574  
   575  	return r, resp, nil
   576  }
   577  
   578  // Delete a repository.
   579  //
   580  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#delete-a-repository
   581  func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) {
   582  	u := fmt.Sprintf("repos/%v/%v", owner, repo)
   583  	req, err := s.client.NewRequest("DELETE", u, nil)
   584  	if err != nil {
   585  		return nil, err
   586  	}
   587  
   588  	return s.client.Do(ctx, req, nil)
   589  }
   590  
   591  // Contributor represents a repository contributor
   592  type Contributor struct {
   593  	Login             *string `json:"login,omitempty"`
   594  	ID                *int64  `json:"id,omitempty"`
   595  	NodeID            *string `json:"node_id,omitempty"`
   596  	AvatarURL         *string `json:"avatar_url,omitempty"`
   597  	GravatarID        *string `json:"gravatar_id,omitempty"`
   598  	URL               *string `json:"url,omitempty"`
   599  	HTMLURL           *string `json:"html_url,omitempty"`
   600  	FollowersURL      *string `json:"followers_url,omitempty"`
   601  	FollowingURL      *string `json:"following_url,omitempty"`
   602  	GistsURL          *string `json:"gists_url,omitempty"`
   603  	StarredURL        *string `json:"starred_url,omitempty"`
   604  	SubscriptionsURL  *string `json:"subscriptions_url,omitempty"`
   605  	OrganizationsURL  *string `json:"organizations_url,omitempty"`
   606  	ReposURL          *string `json:"repos_url,omitempty"`
   607  	EventsURL         *string `json:"events_url,omitempty"`
   608  	ReceivedEventsURL *string `json:"received_events_url,omitempty"`
   609  	Type              *string `json:"type,omitempty"`
   610  	SiteAdmin         *bool   `json:"site_admin,omitempty"`
   611  	Contributions     *int    `json:"contributions,omitempty"`
   612  	Name              *string `json:"name,omitempty"`
   613  	Email             *string `json:"email,omitempty"`
   614  }
   615  
   616  // ListContributorsOptions specifies the optional parameters to the
   617  // RepositoriesService.ListContributors method.
   618  type ListContributorsOptions struct {
   619  	// Include anonymous contributors in results or not
   620  	Anon string `url:"anon,omitempty"`
   621  
   622  	ListOptions
   623  }
   624  
   625  // GetVulnerabilityAlerts checks if vulnerability alerts are enabled for a repository.
   626  //
   627  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#check-if-vulnerability-alerts-are-enabled-for-a-repository
   628  func (s *RepositoriesService) GetVulnerabilityAlerts(ctx context.Context, owner, repository string) (bool, *Response, error) {
   629  	u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository)
   630  
   631  	req, err := s.client.NewRequest("GET", u, nil)
   632  	if err != nil {
   633  		return false, nil, err
   634  	}
   635  
   636  	// TODO: remove custom Accept header when this API fully launches
   637  	req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   638  
   639  	resp, err := s.client.Do(ctx, req, nil)
   640  	vulnerabilityAlertsEnabled, err := parseBoolResponse(err)
   641  	return vulnerabilityAlertsEnabled, resp, err
   642  }
   643  
   644  // EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository.
   645  //
   646  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#enable-vulnerability-alerts
   647  func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) {
   648  	u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository)
   649  
   650  	req, err := s.client.NewRequest("PUT", u, nil)
   651  	if err != nil {
   652  		return nil, err
   653  	}
   654  
   655  	// TODO: remove custom Accept header when this API fully launches
   656  	req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   657  
   658  	return s.client.Do(ctx, req, nil)
   659  }
   660  
   661  // DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository.
   662  //
   663  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#disable-vulnerability-alerts
   664  func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) {
   665  	u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository)
   666  
   667  	req, err := s.client.NewRequest("DELETE", u, nil)
   668  	if err != nil {
   669  		return nil, err
   670  	}
   671  
   672  	// TODO: remove custom Accept header when this API fully launches
   673  	req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   674  
   675  	return s.client.Do(ctx, req, nil)
   676  }
   677  
   678  // EnableAutomatedSecurityFixes enables the automated security fixes for a repository.
   679  //
   680  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#enable-automated-security-fixes
   681  func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) {
   682  	u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository)
   683  
   684  	req, err := s.client.NewRequest("PUT", u, nil)
   685  	if err != nil {
   686  		return nil, err
   687  	}
   688  
   689  	// TODO: remove custom Accept header when this API fully launches
   690  	req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
   691  
   692  	return s.client.Do(ctx, req, nil)
   693  }
   694  
   695  // DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository.
   696  //
   697  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#disable-automated-security-fixes
   698  func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) {
   699  	u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository)
   700  
   701  	req, err := s.client.NewRequest("DELETE", u, nil)
   702  	if err != nil {
   703  		return nil, err
   704  	}
   705  
   706  	// TODO: remove custom Accept header when this API fully launches
   707  	req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
   708  
   709  	return s.client.Do(ctx, req, nil)
   710  }
   711  
   712  // ListContributors lists contributors for a repository.
   713  //
   714  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-contributors
   715  func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opts *ListContributorsOptions) ([]*Contributor, *Response, error) {
   716  	u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository)
   717  	u, err := addOptions(u, opts)
   718  	if err != nil {
   719  		return nil, nil, err
   720  	}
   721  
   722  	req, err := s.client.NewRequest("GET", u, nil)
   723  	if err != nil {
   724  		return nil, nil, err
   725  	}
   726  
   727  	var contributor []*Contributor
   728  	resp, err := s.client.Do(ctx, req, &contributor)
   729  	if err != nil {
   730  		return nil, resp, err
   731  	}
   732  
   733  	return contributor, resp, nil
   734  }
   735  
   736  // ListLanguages lists languages for the specified repository. The returned map
   737  // specifies the languages and the number of bytes of code written in that
   738  // language. For example:
   739  //
   740  //	{
   741  //	  "C": 78769,
   742  //	  "Python": 7769
   743  //	}
   744  //
   745  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-languages
   746  func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) {
   747  	u := fmt.Sprintf("repos/%v/%v/languages", owner, repo)
   748  	req, err := s.client.NewRequest("GET", u, nil)
   749  	if err != nil {
   750  		return nil, nil, err
   751  	}
   752  
   753  	languages := make(map[string]int)
   754  	resp, err := s.client.Do(ctx, req, &languages)
   755  	if err != nil {
   756  		return nil, resp, err
   757  	}
   758  
   759  	return languages, resp, nil
   760  }
   761  
   762  // ListTeams lists the teams for the specified repository.
   763  //
   764  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-teams
   765  func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Team, *Response, error) {
   766  	u := fmt.Sprintf("repos/%v/%v/teams", owner, repo)
   767  	u, err := addOptions(u, opts)
   768  	if err != nil {
   769  		return nil, nil, err
   770  	}
   771  
   772  	req, err := s.client.NewRequest("GET", u, nil)
   773  	if err != nil {
   774  		return nil, nil, err
   775  	}
   776  
   777  	var teams []*Team
   778  	resp, err := s.client.Do(ctx, req, &teams)
   779  	if err != nil {
   780  		return nil, resp, err
   781  	}
   782  
   783  	return teams, resp, nil
   784  }
   785  
   786  // RepositoryTag represents a repository tag.
   787  type RepositoryTag struct {
   788  	Name       *string `json:"name,omitempty"`
   789  	Commit     *Commit `json:"commit,omitempty"`
   790  	ZipballURL *string `json:"zipball_url,omitempty"`
   791  	TarballURL *string `json:"tarball_url,omitempty"`
   792  }
   793  
   794  // ListTags lists tags for the specified repository.
   795  //
   796  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-tags
   797  func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*RepositoryTag, *Response, error) {
   798  	u := fmt.Sprintf("repos/%v/%v/tags", owner, repo)
   799  	u, err := addOptions(u, opts)
   800  	if err != nil {
   801  		return nil, nil, err
   802  	}
   803  
   804  	req, err := s.client.NewRequest("GET", u, nil)
   805  	if err != nil {
   806  		return nil, nil, err
   807  	}
   808  
   809  	var tags []*RepositoryTag
   810  	resp, err := s.client.Do(ctx, req, &tags)
   811  	if err != nil {
   812  		return nil, resp, err
   813  	}
   814  
   815  	return tags, resp, nil
   816  }
   817  
   818  // Branch represents a repository branch
   819  type Branch struct {
   820  	Name      *string           `json:"name,omitempty"`
   821  	Commit    *RepositoryCommit `json:"commit,omitempty"`
   822  	Protected *bool             `json:"protected,omitempty"`
   823  }
   824  
   825  // Protection represents a repository branch's protection.
   826  type Protection struct {
   827  	RequiredStatusChecks           *RequiredStatusChecks           `json:"required_status_checks"`
   828  	RequiredPullRequestReviews     *PullRequestReviewsEnforcement  `json:"required_pull_request_reviews"`
   829  	EnforceAdmins                  *AdminEnforcement               `json:"enforce_admins"`
   830  	Restrictions                   *BranchRestrictions             `json:"restrictions"`
   831  	RequireLinearHistory           *RequireLinearHistory           `json:"required_linear_history"`
   832  	AllowForcePushes               *AllowForcePushes               `json:"allow_force_pushes"`
   833  	AllowDeletions                 *AllowDeletions                 `json:"allow_deletions"`
   834  	RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"`
   835  }
   836  
   837  // BranchProtectionRule represents the rule applied to a repositories branch.
   838  type BranchProtectionRule struct {
   839  	ID                                       *int64     `json:"id,omitempty"`
   840  	RepositoryID                             *int64     `json:"repository_id,omitempty"`
   841  	Name                                     *string    `json:"name,omitempty"`
   842  	CreatedAt                                *Timestamp `json:"created_at,omitempty"`
   843  	UpdatedAt                                *Timestamp `json:"updated_at,omitempty"`
   844  	PullRequestReviewsEnforcementLevel       *string    `json:"pull_request_reviews_enforcement_level,omitempty"`
   845  	RequiredApprovingReviewCount             *int       `json:"required_approving_review_count,omitempty"`
   846  	DismissStaleReviewsOnPush                *bool      `json:"dismiss_stale_reviews_on_push,omitempty"`
   847  	AuthorizedDismissalActorsOnly            *bool      `json:"authorized_dismissal_actors_only,omitempty"`
   848  	IgnoreApprovalsFromContributors          *bool      `json:"ignore_approvals_from_contributors,omitempty"`
   849  	RequireCodeOwnerReview                   *bool      `json:"require_code_owner_review,omitempty"`
   850  	RequiredStatusChecks                     []string   `json:"required_status_checks,omitempty"`
   851  	RequiredStatusChecksEnforcementLevel     *string    `json:"required_status_checks_enforcement_level,omitempty"`
   852  	StrictRequiredStatusChecksPolicy         *bool      `json:"strict_required_status_checks_policy,omitempty"`
   853  	SignatureRequirementEnforcementLevel     *string    `json:"signature_requirement_enforcement_level,omitempty"`
   854  	LinearHistoryRequirementEnforcementLevel *string    `json:"linear_history_requirement_enforcement_level,omitempty"`
   855  	AdminEnforced                            *bool      `json:"admin_enforced,omitempty"`
   856  	AllowForcePushesEnforcementLevel         *string    `json:"allow_force_pushes_enforcement_level,omitempty"`
   857  	AllowDeletionsEnforcementLevel           *string    `json:"allow_deletions_enforcement_level,omitempty"`
   858  	MergeQueueEnforcementLevel               *string    `json:"merge_queue_enforcement_level,omitempty"`
   859  	RequiredDeploymentsEnforcementLevel      *string    `json:"required_deployments_enforcement_level,omitempty"`
   860  	RequiredConversationResolutionLevel      *string    `json:"required_conversation_resolution_level,omitempty"`
   861  	AuthorizedActorsOnly                     *bool      `json:"authorized_actors_only,omitempty"`
   862  	AuthorizedActorNames                     []string   `json:"authorized_actor_names,omitempty"`
   863  }
   864  
   865  // ProtectionChanges represents the changes to the rule if the BranchProtection was edited.
   866  type ProtectionChanges struct {
   867  	AuthorizedActorsOnly *AuthorizedActorsOnly `json:"authorized_actors_only,omitempty"`
   868  	AuthorizedActorNames *AuthorizedActorNames `json:"authorized_actor_names,omitempty"`
   869  }
   870  
   871  // AuthorizedActorNames represents who are authorized to edit the branch protection rules.
   872  type AuthorizedActorNames struct {
   873  	From []string `json:"from,omitempty"`
   874  }
   875  
   876  // AuthorizedActorsOnly represents if the branche rule can be edited by authorized actors only.
   877  type AuthorizedActorsOnly struct {
   878  	From *bool `json:"from,omitempty"`
   879  }
   880  
   881  // ProtectionRequest represents a request to create/edit a branch's protection.
   882  type ProtectionRequest struct {
   883  	RequiredStatusChecks       *RequiredStatusChecks                 `json:"required_status_checks"`
   884  	RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"`
   885  	EnforceAdmins              bool                                  `json:"enforce_admins"`
   886  	Restrictions               *BranchRestrictionsRequest            `json:"restrictions"`
   887  	// Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch.
   888  	RequireLinearHistory *bool `json:"required_linear_history,omitempty"`
   889  	// Permits force pushes to the protected branch by anyone with write access to the repository.
   890  	AllowForcePushes *bool `json:"allow_force_pushes,omitempty"`
   891  	// Allows deletion of the protected branch by anyone with write access to the repository.
   892  	AllowDeletions *bool `json:"allow_deletions,omitempty"`
   893  	// RequiredConversationResolution, if set to true, requires all comments
   894  	// on the pull request to be resolved before it can be merged to a protected branch.
   895  	RequiredConversationResolution *bool `json:"required_conversation_resolution,omitempty"`
   896  }
   897  
   898  // RequiredStatusChecks represents the protection status of a individual branch.
   899  type RequiredStatusChecks struct {
   900  	// Require branches to be up to date before merging. (Required.)
   901  	Strict bool `json:"strict"`
   902  	// The list of status checks to require in order to merge into this
   903  	// branch. (Deprecated. Note: only one of Contexts/Checks can be populated,
   904  	// but at least one must be populated).
   905  	Contexts []string `json:"contexts,omitempty"`
   906  	// The list of status checks to require in order to merge into this
   907  	// branch.
   908  	Checks []*RequiredStatusCheck `json:"checks"`
   909  }
   910  
   911  // RequiredStatusChecksRequest represents a request to edit a protected branch's status checks.
   912  type RequiredStatusChecksRequest struct {
   913  	Strict *bool `json:"strict,omitempty"`
   914  	// Note: if both Contexts and Checks are populated,
   915  	// the GitHub API will only use Checks.
   916  	Contexts []string               `json:"contexts,omitempty"`
   917  	Checks   []*RequiredStatusCheck `json:"checks,omitempty"`
   918  }
   919  
   920  // RequiredStatusCheck represents a status check of a protected branch.
   921  type RequiredStatusCheck struct {
   922  	// The name of the required check.
   923  	Context string `json:"context"`
   924  	// The ID of the GitHub App that must provide this check.
   925  	// Omit this field to automatically select the GitHub App
   926  	// that has recently provided this check,
   927  	// or any app if it was not set by a GitHub App.
   928  	// Pass -1 to explicitly allow any app to set the status.
   929  	AppID *int64 `json:"app_id,omitempty"`
   930  }
   931  
   932  // PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch.
   933  type PullRequestReviewsEnforcement struct {
   934  	// Allow specific users, teams, or apps to bypass pull request requirements.
   935  	BypassPullRequestAllowances *BypassPullRequestAllowances `json:"bypass_pull_request_allowances,omitempty"`
   936  	// Specifies which users and teams can dismiss pull request reviews.
   937  	DismissalRestrictions *DismissalRestrictions `json:"dismissal_restrictions,omitempty"`
   938  	// Specifies if approved reviews are dismissed automatically, when a new commit is pushed.
   939  	DismissStaleReviews bool `json:"dismiss_stale_reviews"`
   940  	// RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner.
   941  	RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"`
   942  	// RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged.
   943  	// Valid values are 1-6.
   944  	RequiredApprovingReviewCount int `json:"required_approving_review_count"`
   945  }
   946  
   947  // PullRequestReviewsEnforcementRequest represents request to set the pull request review
   948  // enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above
   949  // because the request structure is different from the response structure.
   950  type PullRequestReviewsEnforcementRequest struct {
   951  	// Allow specific users, teams, or apps to bypass pull request requirements.
   952  	BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"`
   953  	// Specifies which users and teams should be allowed to dismiss pull request reviews.
   954  	// User and team dismissal restrictions are only available for
   955  	// organization-owned repositories. Must be nil for personal repositories.
   956  	DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"`
   957  	// Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required)
   958  	DismissStaleReviews bool `json:"dismiss_stale_reviews"`
   959  	// RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner.
   960  	RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"`
   961  	// RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged.
   962  	// Valid values are 1-6.
   963  	RequiredApprovingReviewCount int `json:"required_approving_review_count"`
   964  }
   965  
   966  // PullRequestReviewsEnforcementUpdate represents request to patch the pull request review
   967  // enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above
   968  // because the patch request does not require all fields to be initialized.
   969  type PullRequestReviewsEnforcementUpdate struct {
   970  	// Allow specific users, teams, or apps to bypass pull request requirements.
   971  	BypassPullRequestAllowancesRequest *BypassPullRequestAllowancesRequest `json:"bypass_pull_request_allowances,omitempty"`
   972  	// Specifies which users and teams can dismiss pull request reviews. Can be omitted.
   973  	DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"`
   974  	// Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted.
   975  	DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"`
   976  	// RequireCodeOwnerReviews specifies if merging pull requests is blocked until code owners have reviewed.
   977  	RequireCodeOwnerReviews *bool `json:"require_code_owner_reviews,omitempty"`
   978  	// RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged.
   979  	// Valid values are 1 - 6 or 0 to not require reviewers.
   980  	RequiredApprovingReviewCount int `json:"required_approving_review_count"`
   981  }
   982  
   983  // RequireLinearHistory represents the configuration to enforce branches with no merge commit.
   984  type RequireLinearHistory struct {
   985  	Enabled bool `json:"enabled"`
   986  }
   987  
   988  // AllowDeletions represents the configuration to accept deletion of protected branches.
   989  type AllowDeletions struct {
   990  	Enabled bool `json:"enabled"`
   991  }
   992  
   993  // AllowForcePushes represents the configuration to accept forced pushes on protected branches.
   994  type AllowForcePushes struct {
   995  	Enabled bool `json:"enabled"`
   996  }
   997  
   998  // RequiredConversationResolution, if enabled, requires all comments on the pull request to be resolved before it can be merged to a protected branch.
   999  type RequiredConversationResolution struct {
  1000  	Enabled bool `json:"enabled"`
  1001  }
  1002  
  1003  // AdminEnforcement represents the configuration to enforce required status checks for repository administrators.
  1004  type AdminEnforcement struct {
  1005  	URL     *string `json:"url,omitempty"`
  1006  	Enabled bool    `json:"enabled"`
  1007  }
  1008  
  1009  // BranchRestrictions represents the restriction that only certain users or
  1010  // teams may push to a branch.
  1011  type BranchRestrictions struct {
  1012  	// The list of user logins with push access.
  1013  	Users []*User `json:"users"`
  1014  	// The list of team slugs with push access.
  1015  	Teams []*Team `json:"teams"`
  1016  	// The list of app slugs with push access.
  1017  	Apps []*App `json:"apps"`
  1018  }
  1019  
  1020  // BranchRestrictionsRequest represents the request to create/edit the
  1021  // restriction that only certain users or teams may push to a branch. It is
  1022  // separate from BranchRestrictions above because the request structure is
  1023  // different from the response structure.
  1024  type BranchRestrictionsRequest struct {
  1025  	// The list of user logins with push access. (Required; use []string{} instead of nil for empty list.)
  1026  	Users []string `json:"users"`
  1027  	// The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.)
  1028  	Teams []string `json:"teams"`
  1029  	// The list of app slugs with push access.
  1030  	Apps []string `json:"apps,omitempty"`
  1031  }
  1032  
  1033  // BypassPullRequestAllowances represents the people, teams, or apps who are allowed to bypass required pull requests.
  1034  type BypassPullRequestAllowances struct {
  1035  	// The list of users allowed to bypass pull request requirements.
  1036  	Users []*User `json:"users"`
  1037  	// The list of teams allowed to bypass pull request requirements.
  1038  	Teams []*Team `json:"teams"`
  1039  	// The list of apps allowed to bypass pull request requirements.
  1040  	Apps []*App `json:"apps"`
  1041  }
  1042  
  1043  // BypassPullRequestAllowancesRequest represents the people, teams, or apps who are
  1044  // allowed to bypass required pull requests.
  1045  // It is separate from BypassPullRequestAllowances above because the request structure is
  1046  // different from the response structure.
  1047  type BypassPullRequestAllowancesRequest struct {
  1048  	// The list of user logins allowed to bypass pull request requirements.
  1049  	Users []string `json:"users"`
  1050  	// The list of team slugs allowed to bypass pull request requirements.
  1051  	Teams []string `json:"teams"`
  1052  	// The list of app slugs allowed to bypass pull request requirements.
  1053  	Apps []string `json:"apps"`
  1054  }
  1055  
  1056  // DismissalRestrictions specifies which users and teams can dismiss pull request reviews.
  1057  type DismissalRestrictions struct {
  1058  	// The list of users who can dimiss pull request reviews.
  1059  	Users []*User `json:"users"`
  1060  	// The list of teams which can dismiss pull request reviews.
  1061  	Teams []*Team `json:"teams"`
  1062  }
  1063  
  1064  // DismissalRestrictionsRequest represents the request to create/edit the
  1065  // restriction to allows only specific users or teams to dimiss pull request reviews. It is
  1066  // separate from DismissalRestrictions above because the request structure is
  1067  // different from the response structure.
  1068  // Note: Both Users and Teams must be nil, or both must be non-nil.
  1069  type DismissalRestrictionsRequest struct {
  1070  	// The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.)
  1071  	Users *[]string `json:"users,omitempty"`
  1072  	// The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.)
  1073  	Teams *[]string `json:"teams,omitempty"`
  1074  }
  1075  
  1076  // SignaturesProtectedBranch represents the protection status of an individual branch.
  1077  type SignaturesProtectedBranch struct {
  1078  	URL *string `json:"url,omitempty"`
  1079  	// Commits pushed to matching branches must have verified signatures.
  1080  	Enabled *bool `json:"enabled,omitempty"`
  1081  }
  1082  
  1083  // ListBranches lists branches for the specified repository.
  1084  //
  1085  // GitHub API docs: https://docs.github.com/en/rest/branches/branches#list-branches
  1086  func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opts *BranchListOptions) ([]*Branch, *Response, error) {
  1087  	u := fmt.Sprintf("repos/%v/%v/branches", owner, repo)
  1088  	u, err := addOptions(u, opts)
  1089  	if err != nil {
  1090  		return nil, nil, err
  1091  	}
  1092  
  1093  	req, err := s.client.NewRequest("GET", u, nil)
  1094  	if err != nil {
  1095  		return nil, nil, err
  1096  	}
  1097  
  1098  	var branches []*Branch
  1099  	resp, err := s.client.Do(ctx, req, &branches)
  1100  	if err != nil {
  1101  		return nil, resp, err
  1102  	}
  1103  
  1104  	return branches, resp, nil
  1105  }
  1106  
  1107  // GetBranch gets the specified branch for a repository.
  1108  //
  1109  // GitHub API docs: https://docs.github.com/en/rest/branches/branches#get-a-branch
  1110  func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, followRedirects bool) (*Branch, *Response, error) {
  1111  	u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch)
  1112  
  1113  	resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects)
  1114  	if err != nil {
  1115  		return nil, nil, err
  1116  	}
  1117  	defer resp.Body.Close()
  1118  
  1119  	if resp.StatusCode != http.StatusOK {
  1120  		return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
  1121  	}
  1122  
  1123  	b := new(Branch)
  1124  	err = json.NewDecoder(resp.Body).Decode(b)
  1125  	return b, newResponse(resp), err
  1126  }
  1127  
  1128  // renameBranchRequest represents a request to rename a branch.
  1129  type renameBranchRequest struct {
  1130  	NewName string `json:"new_name"`
  1131  }
  1132  
  1133  // RenameBranch renames a branch in a repository.
  1134  //
  1135  // To rename a non-default branch: Users must have push access. GitHub Apps must have the `contents:write` repository permission.
  1136  // To rename the default branch: Users must have admin or owner permissions. GitHub Apps must have the `administration:write` repository permission.
  1137  //
  1138  // GitHub API docs: https://docs.github.com/en/rest/branches/branches#rename-a-branch
  1139  func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, branch, newName string) (*Branch, *Response, error) {
  1140  	u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, branch)
  1141  	r := &renameBranchRequest{NewName: newName}
  1142  	req, err := s.client.NewRequest("POST", u, r)
  1143  	if err != nil {
  1144  		return nil, nil, err
  1145  	}
  1146  
  1147  	b := new(Branch)
  1148  	resp, err := s.client.Do(ctx, req, b)
  1149  	if err != nil {
  1150  		return nil, resp, err
  1151  	}
  1152  
  1153  	return b, resp, nil
  1154  }
  1155  
  1156  // GetBranchProtection gets the protection of a given branch.
  1157  //
  1158  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-branch-protection
  1159  func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) {
  1160  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
  1161  	req, err := s.client.NewRequest("GET", u, nil)
  1162  	if err != nil {
  1163  		return nil, nil, err
  1164  	}
  1165  
  1166  	// TODO: remove custom Accept header when this API fully launches
  1167  	req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
  1168  
  1169  	p := new(Protection)
  1170  	resp, err := s.client.Do(ctx, req, p)
  1171  	if err != nil {
  1172  		if isBranchNotProtected(err) {
  1173  			err = ErrBranchNotProtected
  1174  		}
  1175  		return nil, resp, err
  1176  	}
  1177  
  1178  	return p, resp, nil
  1179  }
  1180  
  1181  // GetRequiredStatusChecks gets the required status checks for a given protected branch.
  1182  //
  1183  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-status-checks-protection
  1184  func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) {
  1185  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
  1186  	req, err := s.client.NewRequest("GET", u, nil)
  1187  	if err != nil {
  1188  		return nil, nil, err
  1189  	}
  1190  
  1191  	p := new(RequiredStatusChecks)
  1192  	resp, err := s.client.Do(ctx, req, p)
  1193  	if err != nil {
  1194  		if isBranchNotProtected(err) {
  1195  			err = ErrBranchNotProtected
  1196  		}
  1197  		return nil, resp, err
  1198  	}
  1199  
  1200  	return p, resp, nil
  1201  }
  1202  
  1203  // ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch.
  1204  //
  1205  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-all-status-check-contexts
  1206  func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) {
  1207  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch)
  1208  	req, err := s.client.NewRequest("GET", u, nil)
  1209  	if err != nil {
  1210  		return nil, nil, err
  1211  	}
  1212  
  1213  	resp, err = s.client.Do(ctx, req, &contexts)
  1214  	if err != nil {
  1215  		if isBranchNotProtected(err) {
  1216  			err = ErrBranchNotProtected
  1217  		}
  1218  		return nil, resp, err
  1219  	}
  1220  
  1221  	return contexts, resp, nil
  1222  }
  1223  
  1224  // UpdateBranchProtection updates the protection of a given branch.
  1225  //
  1226  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-branch-protection
  1227  func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) {
  1228  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
  1229  	req, err := s.client.NewRequest("PUT", u, preq)
  1230  	if err != nil {
  1231  		return nil, nil, err
  1232  	}
  1233  
  1234  	// TODO: remove custom Accept header when this API fully launches
  1235  	req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
  1236  
  1237  	p := new(Protection)
  1238  	resp, err := s.client.Do(ctx, req, p)
  1239  	if err != nil {
  1240  		return nil, resp, err
  1241  	}
  1242  
  1243  	return p, resp, nil
  1244  }
  1245  
  1246  // RemoveBranchProtection removes the protection of a given branch.
  1247  //
  1248  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-branch-protection
  1249  func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) {
  1250  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch)
  1251  	req, err := s.client.NewRequest("DELETE", u, nil)
  1252  	if err != nil {
  1253  		return nil, err
  1254  	}
  1255  
  1256  	return s.client.Do(ctx, req, nil)
  1257  }
  1258  
  1259  // GetSignaturesProtectedBranch gets required signatures of protected branch.
  1260  //
  1261  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-commit-signature-protection
  1262  func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
  1263  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
  1264  	req, err := s.client.NewRequest("GET", u, nil)
  1265  	if err != nil {
  1266  		return nil, nil, err
  1267  	}
  1268  
  1269  	// TODO: remove custom Accept header when this API fully launches
  1270  	req.Header.Set("Accept", mediaTypeSignaturePreview)
  1271  
  1272  	p := new(SignaturesProtectedBranch)
  1273  	resp, err := s.client.Do(ctx, req, p)
  1274  	if err != nil {
  1275  		return nil, resp, err
  1276  	}
  1277  
  1278  	return p, resp, nil
  1279  }
  1280  
  1281  // RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch.
  1282  // It requires admin access and branch protection to be enabled.
  1283  //
  1284  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#create-commit-signature-protection
  1285  func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) {
  1286  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
  1287  	req, err := s.client.NewRequest("POST", u, nil)
  1288  	if err != nil {
  1289  		return nil, nil, err
  1290  	}
  1291  
  1292  	// TODO: remove custom Accept header when this API fully launches
  1293  	req.Header.Set("Accept", mediaTypeSignaturePreview)
  1294  
  1295  	r := new(SignaturesProtectedBranch)
  1296  	resp, err := s.client.Do(ctx, req, r)
  1297  	if err != nil {
  1298  		return nil, resp, err
  1299  	}
  1300  
  1301  	return r, resp, nil
  1302  }
  1303  
  1304  // OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch.
  1305  //
  1306  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-commit-signature-protection
  1307  func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) {
  1308  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch)
  1309  	req, err := s.client.NewRequest("DELETE", u, nil)
  1310  	if err != nil {
  1311  		return nil, err
  1312  	}
  1313  
  1314  	// TODO: remove custom Accept header when this API fully launches
  1315  	req.Header.Set("Accept", mediaTypeSignaturePreview)
  1316  
  1317  	return s.client.Do(ctx, req, nil)
  1318  }
  1319  
  1320  // UpdateRequiredStatusChecks updates the required status checks for a given protected branch.
  1321  //
  1322  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-status-check-protection
  1323  func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) {
  1324  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
  1325  	req, err := s.client.NewRequest("PATCH", u, sreq)
  1326  	if err != nil {
  1327  		return nil, nil, err
  1328  	}
  1329  
  1330  	sc := new(RequiredStatusChecks)
  1331  	resp, err := s.client.Do(ctx, req, sc)
  1332  	if err != nil {
  1333  		return nil, resp, err
  1334  	}
  1335  
  1336  	return sc, resp, nil
  1337  }
  1338  
  1339  // RemoveRequiredStatusChecks removes the required status checks for a given protected branch.
  1340  //
  1341  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-status-check-protection
  1342  func (s *RepositoriesService) RemoveRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*Response, error) {
  1343  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch)
  1344  	req, err := s.client.NewRequest("DELETE", u, nil)
  1345  	if err != nil {
  1346  		return nil, err
  1347  	}
  1348  
  1349  	return s.client.Do(ctx, req, nil)
  1350  }
  1351  
  1352  // License gets the contents of a repository's license if one is detected.
  1353  //
  1354  // GitHub API docs: https://docs.github.com/en/rest/licenses#get-the-license-for-a-repository
  1355  func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) {
  1356  	u := fmt.Sprintf("repos/%v/%v/license", owner, repo)
  1357  	req, err := s.client.NewRequest("GET", u, nil)
  1358  	if err != nil {
  1359  		return nil, nil, err
  1360  	}
  1361  
  1362  	r := &RepositoryLicense{}
  1363  	resp, err := s.client.Do(ctx, req, r)
  1364  	if err != nil {
  1365  		return nil, resp, err
  1366  	}
  1367  
  1368  	return r, resp, nil
  1369  }
  1370  
  1371  // GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch.
  1372  //
  1373  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-pull-request-review-protection
  1374  func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
  1375  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
  1376  	req, err := s.client.NewRequest("GET", u, nil)
  1377  	if err != nil {
  1378  		return nil, nil, err
  1379  	}
  1380  
  1381  	// TODO: remove custom Accept header when this API fully launches
  1382  	req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
  1383  
  1384  	r := new(PullRequestReviewsEnforcement)
  1385  	resp, err := s.client.Do(ctx, req, r)
  1386  	if err != nil {
  1387  		return nil, resp, err
  1388  	}
  1389  
  1390  	return r, resp, nil
  1391  }
  1392  
  1393  // UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch.
  1394  // It requires admin access and branch protection to be enabled.
  1395  //
  1396  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection
  1397  func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) {
  1398  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
  1399  	req, err := s.client.NewRequest("PATCH", u, patch)
  1400  	if err != nil {
  1401  		return nil, nil, err
  1402  	}
  1403  
  1404  	// TODO: remove custom Accept header when this API fully launches
  1405  	req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
  1406  
  1407  	r := new(PullRequestReviewsEnforcement)
  1408  	resp, err := s.client.Do(ctx, req, r)
  1409  	if err != nil {
  1410  		return nil, resp, err
  1411  	}
  1412  
  1413  	return r, resp, nil
  1414  }
  1415  
  1416  // DisableDismissalRestrictions disables dismissal restrictions of a protected branch.
  1417  // It requires admin access and branch protection to be enabled.
  1418  //
  1419  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection
  1420  func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) {
  1421  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
  1422  
  1423  	data := new(struct {
  1424  		DismissalRestrictionsRequest `json:"dismissal_restrictions"`
  1425  	})
  1426  
  1427  	req, err := s.client.NewRequest("PATCH", u, data)
  1428  	if err != nil {
  1429  		return nil, nil, err
  1430  	}
  1431  
  1432  	// TODO: remove custom Accept header when this API fully launches
  1433  	req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview)
  1434  
  1435  	r := new(PullRequestReviewsEnforcement)
  1436  	resp, err := s.client.Do(ctx, req, r)
  1437  	if err != nil {
  1438  		return nil, resp, err
  1439  	}
  1440  
  1441  	return r, resp, nil
  1442  }
  1443  
  1444  // RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch.
  1445  //
  1446  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-pull-request-review-protection
  1447  func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
  1448  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch)
  1449  	req, err := s.client.NewRequest("DELETE", u, nil)
  1450  	if err != nil {
  1451  		return nil, err
  1452  	}
  1453  
  1454  	return s.client.Do(ctx, req, nil)
  1455  }
  1456  
  1457  // GetAdminEnforcement gets admin enforcement information of a protected branch.
  1458  //
  1459  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-admin-branch-protection
  1460  func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
  1461  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
  1462  	req, err := s.client.NewRequest("GET", u, nil)
  1463  	if err != nil {
  1464  		return nil, nil, err
  1465  	}
  1466  
  1467  	r := new(AdminEnforcement)
  1468  	resp, err := s.client.Do(ctx, req, r)
  1469  	if err != nil {
  1470  		return nil, resp, err
  1471  	}
  1472  
  1473  	return r, resp, nil
  1474  }
  1475  
  1476  // AddAdminEnforcement adds admin enforcement to a protected branch.
  1477  // It requires admin access and branch protection to be enabled.
  1478  //
  1479  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-admin-branch-protection
  1480  func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) {
  1481  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
  1482  	req, err := s.client.NewRequest("POST", u, nil)
  1483  	if err != nil {
  1484  		return nil, nil, err
  1485  	}
  1486  
  1487  	r := new(AdminEnforcement)
  1488  	resp, err := s.client.Do(ctx, req, r)
  1489  	if err != nil {
  1490  		return nil, resp, err
  1491  	}
  1492  
  1493  	return r, resp, nil
  1494  }
  1495  
  1496  // RemoveAdminEnforcement removes admin enforcement from a protected branch.
  1497  //
  1498  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-admin-branch-protection
  1499  func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) {
  1500  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch)
  1501  	req, err := s.client.NewRequest("DELETE", u, nil)
  1502  	if err != nil {
  1503  		return nil, err
  1504  	}
  1505  
  1506  	return s.client.Do(ctx, req, nil)
  1507  }
  1508  
  1509  // repositoryTopics represents a collection of repository topics.
  1510  type repositoryTopics struct {
  1511  	Names []string `json:"names"`
  1512  }
  1513  
  1514  // ListAllTopics lists topics for a repository.
  1515  //
  1516  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#get-all-repository-topics
  1517  func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) {
  1518  	u := fmt.Sprintf("repos/%v/%v/topics", owner, repo)
  1519  	req, err := s.client.NewRequest("GET", u, nil)
  1520  	if err != nil {
  1521  		return nil, nil, err
  1522  	}
  1523  
  1524  	// TODO: remove custom Accept header when this API fully launches.
  1525  	req.Header.Set("Accept", mediaTypeTopicsPreview)
  1526  
  1527  	topics := new(repositoryTopics)
  1528  	resp, err := s.client.Do(ctx, req, topics)
  1529  	if err != nil {
  1530  		return nil, resp, err
  1531  	}
  1532  
  1533  	return topics.Names, resp, nil
  1534  }
  1535  
  1536  // ReplaceAllTopics replaces all repository topics.
  1537  //
  1538  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#replace-all-repository-topics
  1539  func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) {
  1540  	u := fmt.Sprintf("repos/%v/%v/topics", owner, repo)
  1541  	t := &repositoryTopics{
  1542  		Names: topics,
  1543  	}
  1544  	if t.Names == nil {
  1545  		t.Names = []string{}
  1546  	}
  1547  	req, err := s.client.NewRequest("PUT", u, t)
  1548  	if err != nil {
  1549  		return nil, nil, err
  1550  	}
  1551  
  1552  	// TODO: remove custom Accept header when this API fully launches.
  1553  	req.Header.Set("Accept", mediaTypeTopicsPreview)
  1554  
  1555  	t = new(repositoryTopics)
  1556  	resp, err := s.client.Do(ctx, req, t)
  1557  	if err != nil {
  1558  		return nil, resp, err
  1559  	}
  1560  
  1561  	return t.Names, resp, nil
  1562  }
  1563  
  1564  // ListApps lists the GitHub apps that have push access to a given protected branch.
  1565  // It requires the GitHub apps to have `write` access to the `content` permission.
  1566  //
  1567  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch
  1568  func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) {
  1569  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
  1570  	req, err := s.client.NewRequest("GET", u, nil)
  1571  	if err != nil {
  1572  		return nil, nil, err
  1573  	}
  1574  
  1575  	var apps []*App
  1576  	resp, err := s.client.Do(ctx, req, &apps)
  1577  	if err != nil {
  1578  		return nil, resp, err
  1579  	}
  1580  
  1581  	return apps, resp, nil
  1582  }
  1583  
  1584  // ReplaceAppRestrictions replaces the apps that have push access to a given protected branch.
  1585  // It removes all apps that previously had push access and grants push access to the new list of apps.
  1586  // It requires the GitHub apps to have `write` access to the `content` permission.
  1587  //
  1588  // Note: The list of users, apps, and teams in total is limited to 100 items.
  1589  //
  1590  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-app-access-restrictions
  1591  func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) {
  1592  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
  1593  	req, err := s.client.NewRequest("PUT", u, slug)
  1594  	if err != nil {
  1595  		return nil, nil, err
  1596  	}
  1597  
  1598  	var apps []*App
  1599  	resp, err := s.client.Do(ctx, req, &apps)
  1600  	if err != nil {
  1601  		return nil, resp, err
  1602  	}
  1603  
  1604  	return apps, resp, nil
  1605  }
  1606  
  1607  // AddAppRestrictions grants the specified apps push access to a given protected branch.
  1608  // It requires the GitHub apps to have `write` access to the `content` permission.
  1609  //
  1610  // Note: The list of users, apps, and teams in total is limited to 100 items.
  1611  //
  1612  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#add-app-access-restrictions
  1613  func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) {
  1614  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
  1615  	req, err := s.client.NewRequest("POST", u, slug)
  1616  	if err != nil {
  1617  		return nil, nil, err
  1618  	}
  1619  
  1620  	var apps []*App
  1621  	resp, err := s.client.Do(ctx, req, &apps)
  1622  	if err != nil {
  1623  		return nil, resp, err
  1624  	}
  1625  
  1626  	return apps, resp, nil
  1627  }
  1628  
  1629  // RemoveAppRestrictions removes the ability of an app to push to this branch.
  1630  // It requires the GitHub apps to have `write` access to the `content` permission.
  1631  //
  1632  // Note: The list of users, apps, and teams in total is limited to 100 items.
  1633  //
  1634  // GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-app-access-restrictions
  1635  func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) {
  1636  	u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch)
  1637  	req, err := s.client.NewRequest("DELETE", u, slug)
  1638  	if err != nil {
  1639  		return nil, nil, err
  1640  	}
  1641  
  1642  	var apps []*App
  1643  	resp, err := s.client.Do(ctx, req, &apps)
  1644  	if err != nil {
  1645  		return nil, resp, err
  1646  	}
  1647  
  1648  	return apps, resp, nil
  1649  }
  1650  
  1651  // TransferRequest represents a request to transfer a repository.
  1652  type TransferRequest struct {
  1653  	NewOwner string  `json:"new_owner"`
  1654  	TeamID   []int64 `json:"team_ids,omitempty"`
  1655  }
  1656  
  1657  // Transfer transfers a repository from one account or organization to another.
  1658  //
  1659  // This method might return an *AcceptedError and a status code of
  1660  // 202. This is because this is the status that GitHub returns to signify that
  1661  // it has now scheduled the transfer of the repository in a background task.
  1662  // A follow up request, after a delay of a second or so, should result
  1663  // in a successful request.
  1664  //
  1665  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#transfer-a-repository
  1666  func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) {
  1667  	u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo)
  1668  
  1669  	req, err := s.client.NewRequest("POST", u, &transfer)
  1670  	if err != nil {
  1671  		return nil, nil, err
  1672  	}
  1673  
  1674  	r := new(Repository)
  1675  	resp, err := s.client.Do(ctx, req, r)
  1676  	if err != nil {
  1677  		return nil, resp, err
  1678  	}
  1679  
  1680  	return r, resp, nil
  1681  }
  1682  
  1683  // DispatchRequestOptions represents a request to trigger a repository_dispatch event.
  1684  type DispatchRequestOptions struct {
  1685  	// EventType is a custom webhook event name. (Required.)
  1686  	EventType string `json:"event_type"`
  1687  	// ClientPayload is a custom JSON payload with extra information about the webhook event.
  1688  	// Defaults to an empty JSON object.
  1689  	ClientPayload *json.RawMessage `json:"client_payload,omitempty"`
  1690  }
  1691  
  1692  // Dispatch triggers a repository_dispatch event in a GitHub Actions workflow.
  1693  //
  1694  // GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-dispatch-event
  1695  func (s *RepositoriesService) Dispatch(ctx context.Context, owner, repo string, opts DispatchRequestOptions) (*Repository, *Response, error) {
  1696  	u := fmt.Sprintf("repos/%v/%v/dispatches", owner, repo)
  1697  
  1698  	req, err := s.client.NewRequest("POST", u, &opts)
  1699  	if err != nil {
  1700  		return nil, nil, err
  1701  	}
  1702  
  1703  	r := new(Repository)
  1704  	resp, err := s.client.Do(ctx, req, r)
  1705  	if err != nil {
  1706  		return nil, resp, err
  1707  	}
  1708  
  1709  	return r, resp, nil
  1710  }
  1711  
  1712  // isBranchNotProtected determines whether a branch is not protected
  1713  // based on the error message returned by GitHub API.
  1714  func isBranchNotProtected(err error) bool {
  1715  	errorResponse, ok := err.(*ErrorResponse)
  1716  	return ok && errorResponse.Message == githubBranchNotProtected
  1717  }
  1718  

View as plain text