repositories.go

  1//
  2// Copyright 2017, Sander van Harmelen
  3//
  4// Licensed under the Apache License, Version 2.0 (the "License");
  5// you may not use this file except in compliance with the License.
  6// You may obtain a copy of the License at
  7//
  8//     http://www.apache.org/licenses/LICENSE-2.0
  9//
 10// Unless required by applicable law or agreed to in writing, software
 11// distributed under the License is distributed on an "AS IS" BASIS,
 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13// See the License for the specific language governing permissions and
 14// limitations under the License.
 15//
 16
 17package gitlab
 18
 19import (
 20	"bytes"
 21	"fmt"
 22	"io"
 23)
 24
 25// RepositoriesService handles communication with the repositories related
 26// methods of the GitLab API.
 27//
 28// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html
 29type RepositoriesService struct {
 30	client *Client
 31}
 32
 33// TreeNode represents a GitLab repository file or directory.
 34//
 35// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html
 36type TreeNode struct {
 37	ID   string `json:"id"`
 38	Name string `json:"name"`
 39	Type string `json:"type"`
 40	Path string `json:"path"`
 41	Mode string `json:"mode"`
 42}
 43
 44func (t TreeNode) String() string {
 45	return Stringify(t)
 46}
 47
 48// ListTreeOptions represents the available ListTree() options.
 49//
 50// GitLab API docs:
 51// https://docs.gitlab.com/ce/api/repositories.html#list-repository-tree
 52type ListTreeOptions struct {
 53	ListOptions
 54	Path      *string `url:"path,omitempty" json:"path,omitempty"`
 55	Ref       *string `url:"ref,omitempty" json:"ref,omitempty"`
 56	Recursive *bool   `url:"recursive,omitempty" json:"recursive,omitempty"`
 57}
 58
 59// ListTree gets a list of repository files and directories in a project.
 60//
 61// GitLab API docs:
 62// https://docs.gitlab.com/ce/api/repositories.html#list-repository-tree
 63func (s *RepositoriesService) ListTree(pid interface{}, opt *ListTreeOptions, options ...OptionFunc) ([]*TreeNode, *Response, error) {
 64	project, err := parseID(pid)
 65	if err != nil {
 66		return nil, nil, err
 67	}
 68	u := fmt.Sprintf("projects/%s/repository/tree", pathEscape(project))
 69
 70	req, err := s.client.NewRequest("GET", u, opt, options)
 71	if err != nil {
 72		return nil, nil, err
 73	}
 74
 75	var t []*TreeNode
 76	resp, err := s.client.Do(req, &t)
 77	if err != nil {
 78		return nil, resp, err
 79	}
 80
 81	return t, resp, err
 82}
 83
 84// Blob gets information about blob in repository like size and content. Note
 85// that blob content is Base64 encoded.
 86//
 87// GitLab API docs:
 88// https://docs.gitlab.com/ce/api/repositories.html#get-a-blob-from-repository
 89func (s *RepositoriesService) Blob(pid interface{}, sha string, options ...OptionFunc) ([]byte, *Response, error) {
 90	project, err := parseID(pid)
 91	if err != nil {
 92		return nil, nil, err
 93	}
 94	u := fmt.Sprintf("projects/%s/repository/blobs/%s", pathEscape(project), sha)
 95
 96	req, err := s.client.NewRequest("GET", u, nil, options)
 97	if err != nil {
 98		return nil, nil, err
 99	}
100
101	var b bytes.Buffer
102	resp, err := s.client.Do(req, &b)
103	if err != nil {
104		return nil, resp, err
105	}
106
107	return b.Bytes(), resp, err
108}
109
110// RawBlobContent gets the raw file contents for a blob by blob SHA.
111//
112// GitLab API docs:
113// https://docs.gitlab.com/ce/api/repositories.html#raw-blob-content
114func (s *RepositoriesService) RawBlobContent(pid interface{}, sha string, options ...OptionFunc) ([]byte, *Response, error) {
115	project, err := parseID(pid)
116	if err != nil {
117		return nil, nil, err
118	}
119	u := fmt.Sprintf("projects/%s/repository/blobs/%s/raw", pathEscape(project), sha)
120
121	req, err := s.client.NewRequest("GET", u, nil, options)
122	if err != nil {
123		return nil, nil, err
124	}
125
126	var b bytes.Buffer
127	resp, err := s.client.Do(req, &b)
128	if err != nil {
129		return nil, resp, err
130	}
131
132	return b.Bytes(), resp, err
133}
134
135// ArchiveOptions represents the available Archive() options.
136//
137// GitLab API docs:
138// https://docs.gitlab.com/ce/api/repositories.html#get-file-archive
139type ArchiveOptions struct {
140	Format *string `url:"-" json:"-"`
141	SHA    *string `url:"sha,omitempty" json:"sha,omitempty"`
142}
143
144// Archive gets an archive of the repository.
145//
146// GitLab API docs:
147// https://docs.gitlab.com/ce/api/repositories.html#get-file-archive
148func (s *RepositoriesService) Archive(pid interface{}, opt *ArchiveOptions, options ...OptionFunc) ([]byte, *Response, error) {
149	project, err := parseID(pid)
150	if err != nil {
151		return nil, nil, err
152	}
153	u := fmt.Sprintf("projects/%s/repository/archive", pathEscape(project))
154
155	// Set an optional format for the archive.
156	if opt != nil && opt.Format != nil {
157		u = fmt.Sprintf("%s.%s", u, *opt.Format)
158	}
159
160	req, err := s.client.NewRequest("GET", u, opt, options)
161	if err != nil {
162		return nil, nil, err
163	}
164
165	var b bytes.Buffer
166	resp, err := s.client.Do(req, &b)
167	if err != nil {
168		return nil, resp, err
169	}
170
171	return b.Bytes(), resp, err
172}
173
174// StreamArchive streams an archive of the repository to the provided
175// io.Writer.
176//
177// GitLab API docs:
178// https://docs.gitlab.com/ce/api/repositories.html#get-file-archive
179func (s *RepositoriesService) StreamArchive(pid interface{}, w io.Writer, opt *ArchiveOptions, options ...OptionFunc) (*Response, error) {
180	project, err := parseID(pid)
181	if err != nil {
182		return nil, err
183	}
184	u := fmt.Sprintf("projects/%s/repository/archive", pathEscape(project))
185
186	// Set an optional format for the archive.
187	if opt != nil && opt.Format != nil {
188		u = fmt.Sprintf("%s.%s", u, *opt.Format)
189	}
190
191	req, err := s.client.NewRequest("GET", u, opt, options)
192	if err != nil {
193		return nil, err
194	}
195
196	return s.client.Do(req, w)
197}
198
199// Compare represents the result of a comparison of branches, tags or commits.
200//
201// GitLab API docs:
202// https://docs.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits
203type Compare struct {
204	Commit         *Commit   `json:"commit"`
205	Commits        []*Commit `json:"commits"`
206	Diffs          []*Diff   `json:"diffs"`
207	CompareTimeout bool      `json:"compare_timeout"`
208	CompareSameRef bool      `json:"compare_same_ref"`
209}
210
211func (c Compare) String() string {
212	return Stringify(c)
213}
214
215// CompareOptions represents the available Compare() options.
216//
217// GitLab API docs:
218// https://docs.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits
219type CompareOptions struct {
220	From     *string `url:"from,omitempty" json:"from,omitempty"`
221	To       *string `url:"to,omitempty" json:"to,omitempty"`
222	Straight *bool   `url:"straight,omitempty" json:"straight,omitempty"`
223}
224
225// Compare compares branches, tags or commits.
226//
227// GitLab API docs:
228// https://docs.gitlab.com/ce/api/repositories.html#compare-branches-tags-or-commits
229func (s *RepositoriesService) Compare(pid interface{}, opt *CompareOptions, options ...OptionFunc) (*Compare, *Response, error) {
230	project, err := parseID(pid)
231	if err != nil {
232		return nil, nil, err
233	}
234	u := fmt.Sprintf("projects/%s/repository/compare", pathEscape(project))
235
236	req, err := s.client.NewRequest("GET", u, opt, options)
237	if err != nil {
238		return nil, nil, err
239	}
240
241	c := new(Compare)
242	resp, err := s.client.Do(req, c)
243	if err != nil {
244		return nil, resp, err
245	}
246
247	return c, resp, err
248}
249
250// Contributor represents a GitLap contributor.
251//
252// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html#contributors
253type Contributor struct {
254	Name      string `json:"name"`
255	Email     string `json:"email"`
256	Commits   int    `json:"commits"`
257	Additions int    `json:"additions"`
258	Deletions int    `json:"deletions"`
259}
260
261func (c Contributor) String() string {
262	return Stringify(c)
263}
264
265// ListContributorsOptions represents the available ListContributors() options.
266//
267// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html#contributors
268type ListContributorsOptions ListOptions
269
270// Contributors gets the repository contributors list.
271//
272// GitLab API docs: https://docs.gitlab.com/ce/api/repositories.html#contributors
273func (s *RepositoriesService) Contributors(pid interface{}, opt *ListContributorsOptions, options ...OptionFunc) ([]*Contributor, *Response, error) {
274	project, err := parseID(pid)
275	if err != nil {
276		return nil, nil, err
277	}
278	u := fmt.Sprintf("projects/%s/repository/contributors", pathEscape(project))
279
280	req, err := s.client.NewRequest("GET", u, opt, options)
281	if err != nil {
282		return nil, nil, err
283	}
284
285	var c []*Contributor
286	resp, err := s.client.Do(req, &c)
287	if err != nil {
288		return nil, resp, err
289	}
290
291	return c, resp, err
292}
293
294// MergeBaseOptions represents the available MergeBase() options.
295//
296// GitLab API docs:
297// https://docs.gitlab.com/ce/api/repositories.html#merge-base
298type MergeBaseOptions struct {
299	Ref []string `url:"refs[],omitempty" json:"refs,omitempty"`
300}
301
302// MergeBase gets the common ancestor for 2 refs (commit SHAs, branch
303// names or tags).
304//
305// GitLab API docs:
306// https://docs.gitlab.com/ce/api/repositories.html#merge-base
307func (s *RepositoriesService) MergeBase(pid interface{}, opt *MergeBaseOptions, options ...OptionFunc) (*Commit, *Response, error) {
308	project, err := parseID(pid)
309	if err != nil {
310		return nil, nil, err
311	}
312	u := fmt.Sprintf("projects/%s/repository/merge_base", pathEscape(project))
313
314	req, err := s.client.NewRequest("GET", u, opt, options)
315	if err != nil {
316		return nil, nil, err
317	}
318
319	c := new(Commit)
320	resp, err := s.client.Do(req, c)
321	if err != nil {
322		return nil, resp, err
323	}
324
325	return c, resp, err
326}