// Copyright 2013 The go-github AUTHORS. All rights reserved.//// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// Repository contents API methods.// GitHub API docs: https://docs.github.com/rest/repos/contents/package githubimport ()varErrPathForbidden = errors.New("path must not contain '..' due to auth vulnerability issue")// RepositoryContent represents a file or directory in a github repository.typeRepositoryContentstruct { Type *string`json:"type,omitempty"`// Target is only set if the type is "symlink" and the target is not a normal file. // If Target is set, Path will be the symlink path. Target *string`json:"target,omitempty"` Encoding *string`json:"encoding,omitempty"` Size *int`json:"size,omitempty"` Name *string`json:"name,omitempty"` Path *string`json:"path,omitempty"`// Content contains the actual file content, which may be encoded. // Callers should call GetContent which will decode the content if // necessary. Content *string`json:"content,omitempty"` SHA *string`json:"sha,omitempty"` URL *string`json:"url,omitempty"` GitURL *string`json:"git_url,omitempty"` HTMLURL *string`json:"html_url,omitempty"` DownloadURL *string`json:"download_url,omitempty"` SubmoduleGitURL *string`json:"submodule_git_url,omitempty"`}// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile.typeRepositoryContentResponsestruct { Content *RepositoryContent`json:"content,omitempty"`Commit`json:"commit,omitempty"`}// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile.typeRepositoryContentFileOptionsstruct { Message *string`json:"message,omitempty"` Content []byte`json:"content"`// unencoded SHA *string`json:"sha,omitempty"` Branch *string`json:"branch,omitempty"` Author *CommitAuthor`json:"author,omitempty"` Committer *CommitAuthor`json:"committer,omitempty"`}// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA,// branch, or tagtypeRepositoryContentGetOptionsstruct { Ref string`url:"ref,omitempty"`}// String converts RepositoryContent to a string. It's primarily for testing.func ( RepositoryContent) () string {returnStringify()}// GetContent returns the content of r, decoding it if necessary.func ( *RepositoryContent) () (string, error) {varstringif .Encoding != nil { = *.Encoding }switch {case"base64":if .Content == nil {return"", errors.New("malformed response: base64 encoding of null content") } , := base64.StdEncoding.DecodeString(*.Content)returnstring(), case"":if .Content == nil {return"", nil }return *.Content, nilcase"none":return"", errors.New("unsupported content encoding: none, this may occur when file size > 1 MB, if that is the case consider using DownloadContents")default:return"", fmt.Errorf("unsupported content encoding: %v", ) }}// GetReadme gets the Readme file for the repository.//// GitHub API docs: https://docs.github.com/rest/repos/contents#get-a-repository-readme////meta:operation GET /repos/{owner}/{repo}/readmefunc ( *RepositoriesService) ( context.Context, , string, *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { := fmt.Sprintf("repos/%v/%v/readme", , ) , := addOptions(, )if != nil {returnnil, nil, } , := .client.NewRequest("GET", , nil)if != nil {returnnil, nil, } := new(RepositoryContent) , := .client.Do(, , )if != nil {returnnil, , }return , , nil}// DownloadContents returns an io.ReadCloser that reads the contents of the// specified file. This function will work with files of any size, as opposed// to GetContents which is limited to 1 Mb files. It is the caller's// responsibility to close the ReadCloser.//// It is possible for the download to result in a failed response when the// returned error is nil. Callers should check the returned Response status// code to verify the content is from a successful response.//// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content////meta:operation GET /repos/{owner}/{repo}/contents/{path}func ( *RepositoriesService) ( context.Context, , , string, *RepositoryContentGetOptions) (io.ReadCloser, *Response, error) { := path.Dir() := path.Base() , , , := .GetContents(, , , , )if != nil {returnnil, , }for , := range {if *.Name == {if .DownloadURL == nil || *.DownloadURL == "" {returnnil, , fmt.Errorf("no download link found for %s", ) } , := http.NewRequestWithContext(, http.MethodGet, *.DownloadURL, nil)if != nil {returnnil, , } , := .client.client.Do()if != nil {returnnil, &Response{Response: }, }return .Body, &Response{Response: }, nil } }returnnil, , fmt.Errorf("no file named %s found in %s", , )}// DownloadContentsWithMeta is identical to DownloadContents but additionally// returns the RepositoryContent of the requested file. This additional data// is useful for future operations involving the requested file. For merely// reading the content of a file, DownloadContents is perfectly adequate.//// It is possible for the download to result in a failed response when the// returned error is nil. Callers should check the returned Response status// code to verify the content is from a successful response.//// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content////meta:operation GET /repos/{owner}/{repo}/contents/{path}func ( *RepositoriesService) ( context.Context, , , string, *RepositoryContentGetOptions) (io.ReadCloser, *RepositoryContent, *Response, error) { := path.Dir() := path.Base() , , , := .GetContents(, , , , )if != nil {returnnil, nil, , }for , := range {if *.Name == {if .DownloadURL == nil || *.DownloadURL == "" {returnnil, , , fmt.Errorf("no download link found for %s", ) } , := http.NewRequestWithContext(, http.MethodGet, *.DownloadURL, nil)if != nil {returnnil, , , } , := .client.client.Do()if != nil {returnnil, , &Response{Response: }, }return .Body, , &Response{Response: }, nil } }returnnil, nil, , fmt.Errorf("no file named %s found in %s", , )}// GetContents can return either the metadata and content of a single file// (when path references a file) or the metadata of all the files and/or// subdirectories of a directory (when path references a directory). To make it// easy to distinguish between both result types and to mimic the API as much// as possible, both result types will be returned but only one will contain a// value and the other will be nil.//// Due to an auth vulnerability issue in the GitHub v3 API, ".." is not allowed// to appear anywhere in the "path" or this method will return an error.//// GitHub API docs: https://docs.github.com/rest/repos/contents#get-repository-content////meta:operation GET /repos/{owner}/{repo}/contents/{path}func ( *RepositoriesService) ( context.Context, , , string, *RepositoryContentGetOptions) ( *RepositoryContent, []*RepositoryContent, *Response, error) {ifstrings.Contains(, "..") {returnnil, nil, nil, ErrPathForbidden } := (&url.URL{Path: strings.TrimSuffix(, "/")}).String() := fmt.Sprintf("repos/%s/%s/contents/%s", , , ) , = addOptions(, )if != nil {returnnil, nil, nil, } , := .client.NewRequest("GET", , nil)if != nil {returnnil, nil, nil, }varjson.RawMessage , = .client.Do(, , &)if != nil {returnnil, nil, , } := json.Unmarshal(, &)if == nil {return , nil, , nil } := json.Unmarshal(, &)if == nil {returnnil, , , nil }returnnil, nil, , fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", , )}// CreateFile creates a new file in a repository at the given path and returns// the commit and file metadata.//// GitHub API docs: https://docs.github.com/rest/repos/contents#create-or-update-file-contents////meta:operation PUT /repos/{owner}/{repo}/contents/{path}func ( *RepositoriesService) ( context.Context, , , string, *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { := fmt.Sprintf("repos/%s/%s/contents/%s", , , ) , := .client.NewRequest("PUT", , )if != nil {returnnil, nil, } := new(RepositoryContentResponse) , := .client.Do(, , )if != nil {returnnil, , }return , , nil}// UpdateFile updates a file in a repository at the given path and returns the// commit and file metadata. Requires the blob SHA of the file being updated.//// GitHub API docs: https://docs.github.com/rest/repos/contents#create-or-update-file-contents////meta:operation PUT /repos/{owner}/{repo}/contents/{path}func ( *RepositoriesService) ( context.Context, , , string, *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { := fmt.Sprintf("repos/%s/%s/contents/%s", , , ) , := .client.NewRequest("PUT", , )if != nil {returnnil, nil, } := new(RepositoryContentResponse) , := .client.Do(, , )if != nil {returnnil, , }return , , nil}// DeleteFile deletes a file from a repository and returns the commit.// Requires the blob SHA of the file to be deleted.//// GitHub API docs: https://docs.github.com/rest/repos/contents#delete-a-file////meta:operation DELETE /repos/{owner}/{repo}/contents/{path}func ( *RepositoriesService) ( context.Context, , , string, *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { := fmt.Sprintf("repos/%s/%s/contents/%s", , , ) , := .client.NewRequest("DELETE", , )if != nil {returnnil, nil, } := new(RepositoryContentResponse) , := .client.Do(, , )if != nil {returnnil, , }return , , nil}// ArchiveFormat is used to define the archive type when calling GetArchiveLink.typeArchiveFormatstringconst (// Tarball specifies an archive in gzipped tar format.TarballArchiveFormat = "tarball"// Zipball specifies an archive in zip format.ZipballArchiveFormat = "zipball")// GetArchiveLink returns an URL to download a tarball or zipball archive for a// repository. The archiveFormat can be specified by either the github.Tarball// or github.Zipball constant.//// GitHub API docs: https://docs.github.com/rest/repos/contents#download-a-repository-archive-tar// GitHub API docs: https://docs.github.com/rest/repos/contents#download-a-repository-archive-zip////meta:operation GET /repos/{owner}/{repo}/tarball/{ref}//meta:operation GET /repos/{owner}/{repo}/zipball/{ref}func ( *RepositoriesService) ( context.Context, , string, ArchiveFormat, *RepositoryContentGetOptions, int) (*url.URL, *Response, error) { := fmt.Sprintf("repos/%s/%s/%s", , , )if != nil && .Ref != "" { += fmt.Sprintf("/%s", .Ref) } , := .client.roundTripWithOptionalFollowRedirect(, , )if != nil {returnnil, nil, }defer .Body.Close()if .StatusCode != http.StatusOK && .StatusCode != http.StatusFound {returnnil, newResponse(), fmt.Errorf("unexpected status code: %s", .Status) } , := url.Parse(.Header.Get("Location"))if != nil {returnnil, newResponse(), }return , newResponse(), nil}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.