1// Copyright 2014 The Gogs Authors. All rights reserved. 2// Copyright 2019 The Gitea Authors. All rights reserved. 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file. 5 6package gitea 7 8import ( 9 "bytes" 10 "encoding/json" 11 "fmt" 12) 13 14// FileOptions options for all file APIs 15type FileOptions struct { 16 // message (optional) for the commit of this file. if not supplied, a default message will be used 17 Message string `json:"message"` 18 // branch (optional) to base this file from. if not given, the default branch is used 19 BranchName string `json:"branch"` 20 // new_branch (optional) will make a new branch from `branch` before creating the file 21 NewBranchName string `json:"new_branch"` 22 // `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used) 23 Author Identity `json:"author"` 24 Committer Identity `json:"committer"` 25 Dates CommitDateOptions `json:"dates"` 26} 27 28// CreateFileOptions options for creating files 29// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used) 30type CreateFileOptions struct { 31 FileOptions 32 // content must be base64 encoded 33 // required: true 34 Content string `json:"content"` 35} 36 37// DeleteFileOptions options for deleting files (used for other File structs below) 38// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used) 39type DeleteFileOptions struct { 40 FileOptions 41 // sha is the SHA for the file that already exists 42 // required: true 43 SHA string `json:"sha"` 44} 45 46// UpdateFileOptions options for updating files 47// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used) 48type UpdateFileOptions struct { 49 FileOptions 50 // sha is the SHA for the file that already exists 51 // required: true 52 SHA string `json:"sha"` 53 // content must be base64 encoded 54 // required: true 55 Content string `json:"content"` 56 // from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL 57 FromPath string `json:"from_path"` 58} 59 60// FileLinksResponse contains the links for a repo's file 61type FileLinksResponse struct { 62 Self *string `json:"self"` 63 GitURL *string `json:"git"` 64 HTMLURL *string `json:"html"` 65} 66 67// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content 68type ContentsResponse struct { 69 Name string `json:"name"` 70 Path string `json:"path"` 71 SHA string `json:"sha"` 72 // `type` will be `file`, `dir`, `symlink`, or `submodule` 73 Type string `json:"type"` 74 Size int64 `json:"size"` 75 // `encoding` is populated when `type` is `file`, otherwise null 76 Encoding *string `json:"encoding"` 77 // `content` is populated when `type` is `file`, otherwise null 78 Content *string `json:"content"` 79 // `target` is populated when `type` is `symlink`, otherwise null 80 Target *string `json:"target"` 81 URL *string `json:"url"` 82 HTMLURL *string `json:"html_url"` 83 GitURL *string `json:"git_url"` 84 DownloadURL *string `json:"download_url"` 85 // `submodule_git_url` is populated when `type` is `submodule`, otherwise null 86 SubmoduleGitURL *string `json:"submodule_git_url"` 87 Links *FileLinksResponse `json:"_links"` 88} 89 90// FileCommitResponse contains information generated from a Git commit for a repo's file. 91type FileCommitResponse struct { 92 CommitMeta 93 HTMLURL string `json:"html_url"` 94 Author *CommitUser `json:"author"` 95 Committer *CommitUser `json:"committer"` 96 Parents []*CommitMeta `json:"parents"` 97 Message string `json:"message"` 98 Tree *CommitMeta `json:"tree"` 99} 100 101// FileResponse contains information about a repo's file 102type FileResponse struct { 103 Content *ContentsResponse `json:"content"` 104 Commit *FileCommitResponse `json:"commit"` 105 Verification *PayloadCommitVerification `json:"verification"` 106} 107 108// FileDeleteResponse contains information about a repo's file that was deleted 109type FileDeleteResponse struct { 110 Content interface{} `json:"content"` // to be set to nil 111 Commit *FileCommitResponse `json:"commit"` 112 Verification *PayloadCommitVerification `json:"verification"` 113} 114 115// GetFile downloads a file of repository, ref can be branch/tag/commit. 116// e.g.: ref -> master, tree -> macaron.go(no leading slash) 117func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, error) { 118 return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), nil, nil) 119} 120 121// GetContents get the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir 122// ref is optional 123func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, error) { 124 cr := new(ContentsResponse) 125 return cr, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, ref), jsonHeader, nil, cr) 126 127} 128 129// CreateFile create a file in a repository 130func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, error) { 131 body, err := json.Marshal(&opt) 132 if err != nil { 133 return nil, err 134 } 135 fr := new(FileResponse) 136 return fr, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr) 137} 138 139// UpdateFile update a file in a repository 140func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, error) { 141 body, err := json.Marshal(&opt) 142 if err != nil { 143 return nil, err 144 } 145 fr := new(FileResponse) 146 return fr, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr) 147} 148 149// DeleteFile delete a file from repository 150func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) error { 151 body, err := json.Marshal(&opt) 152 if err != nil { 153 return err 154 } 155 status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body)) 156 if err != nil { 157 return err 158 } 159 if status != 200 && status != 204 { 160 return fmt.Errorf("unexpected Status: %d", status) 161 } 162 return nil 163} 164