github.com/google/go-github/v48@v48.2.0/github/repos.go (about)

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