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 "fmt"
21 "net/url"
22)
23
24// BranchesService handles communication with the branch related methods
25// of the GitLab API.
26//
27// GitLab API docs: https://docs.gitlab.com/ce/api/branches.html
28type BranchesService struct {
29 client *Client
30}
31
32// Branch represents a GitLab branch.
33//
34// GitLab API docs: https://docs.gitlab.com/ce/api/branches.html
35type Branch struct {
36 Commit *Commit `json:"commit"`
37 Name string `json:"name"`
38 Protected bool `json:"protected"`
39 Merged bool `json:"merged"`
40 Default bool `json:"default"`
41 DevelopersCanPush bool `json:"developers_can_push"`
42 DevelopersCanMerge bool `json:"developers_can_merge"`
43}
44
45func (b Branch) String() string {
46 return Stringify(b)
47}
48
49// ListBranchesOptions represents the available ListBranches() options.
50//
51// GitLab API docs:
52// https://docs.gitlab.com/ce/api/branches.html#list-repository-branches
53type ListBranchesOptions ListOptions
54
55// ListBranches gets a list of repository branches from a project, sorted by
56// name alphabetically.
57//
58// GitLab API docs:
59// https://docs.gitlab.com/ce/api/branches.html#list-repository-branches
60func (s *BranchesService) ListBranches(pid interface{}, opts *ListBranchesOptions, options ...OptionFunc) ([]*Branch, *Response, error) {
61 project, err := parseID(pid)
62 if err != nil {
63 return nil, nil, err
64 }
65 u := fmt.Sprintf("projects/%s/repository/branches", pathEscape(project))
66
67 req, err := s.client.NewRequest("GET", u, opts, options)
68 if err != nil {
69 return nil, nil, err
70 }
71
72 var b []*Branch
73 resp, err := s.client.Do(req, &b)
74 if err != nil {
75 return nil, resp, err
76 }
77
78 return b, resp, err
79}
80
81// GetBranch gets a single project repository branch.
82//
83// GitLab API docs:
84// https://docs.gitlab.com/ce/api/branches.html#get-single-repository-branch
85func (s *BranchesService) GetBranch(pid interface{}, branch string, options ...OptionFunc) (*Branch, *Response, error) {
86 project, err := parseID(pid)
87 if err != nil {
88 return nil, nil, err
89 }
90 u := fmt.Sprintf("projects/%s/repository/branches/%s", pathEscape(project), url.PathEscape(branch))
91
92 req, err := s.client.NewRequest("GET", u, nil, options)
93 if err != nil {
94 return nil, nil, err
95 }
96
97 b := new(Branch)
98 resp, err := s.client.Do(req, b)
99 if err != nil {
100 return nil, resp, err
101 }
102
103 return b, resp, err
104}
105
106// ProtectBranchOptions represents the available ProtectBranch() options.
107//
108// GitLab API docs:
109// https://docs.gitlab.com/ce/api/branches.html#protect-repository-branch
110type ProtectBranchOptions struct {
111 DevelopersCanPush *bool `url:"developers_can_push,omitempty" json:"developers_can_push,omitempty"`
112 DevelopersCanMerge *bool `url:"developers_can_merge,omitempty" json:"developers_can_merge,omitempty"`
113}
114
115// ProtectBranch protects a single project repository branch. This is an
116// idempotent function, protecting an already protected repository branch
117// still returns a 200 OK status code.
118//
119// GitLab API docs:
120// https://docs.gitlab.com/ce/api/branches.html#protect-repository-branch
121func (s *BranchesService) ProtectBranch(pid interface{}, branch string, opts *ProtectBranchOptions, options ...OptionFunc) (*Branch, *Response, error) {
122 project, err := parseID(pid)
123 if err != nil {
124 return nil, nil, err
125 }
126 u := fmt.Sprintf("projects/%s/repository/branches/%s/protect", pathEscape(project), url.PathEscape(branch))
127
128 req, err := s.client.NewRequest("PUT", u, opts, options)
129 if err != nil {
130 return nil, nil, err
131 }
132
133 b := new(Branch)
134 resp, err := s.client.Do(req, b)
135 if err != nil {
136 return nil, resp, err
137 }
138
139 return b, resp, err
140}
141
142// UnprotectBranch unprotects a single project repository branch. This is an
143// idempotent function, unprotecting an already unprotected repository branch
144// still returns a 200 OK status code.
145//
146// GitLab API docs:
147// https://docs.gitlab.com/ce/api/branches.html#unprotect-repository-branch
148func (s *BranchesService) UnprotectBranch(pid interface{}, branch string, options ...OptionFunc) (*Branch, *Response, error) {
149 project, err := parseID(pid)
150 if err != nil {
151 return nil, nil, err
152 }
153 u := fmt.Sprintf("projects/%s/repository/branches/%s/unprotect", pathEscape(project), url.PathEscape(branch))
154
155 req, err := s.client.NewRequest("PUT", u, nil, options)
156 if err != nil {
157 return nil, nil, err
158 }
159
160 b := new(Branch)
161 resp, err := s.client.Do(req, b)
162 if err != nil {
163 return nil, resp, err
164 }
165
166 return b, resp, err
167}
168
169// CreateBranchOptions represents the available CreateBranch() options.
170//
171// GitLab API docs:
172// https://docs.gitlab.com/ce/api/branches.html#create-repository-branch
173type CreateBranchOptions struct {
174 Branch *string `url:"branch,omitempty" json:"branch,omitempty"`
175 Ref *string `url:"ref,omitempty" json:"ref,omitempty"`
176}
177
178// CreateBranch creates branch from commit SHA or existing branch.
179//
180// GitLab API docs:
181// https://docs.gitlab.com/ce/api/branches.html#create-repository-branch
182func (s *BranchesService) CreateBranch(pid interface{}, opt *CreateBranchOptions, options ...OptionFunc) (*Branch, *Response, error) {
183 project, err := parseID(pid)
184 if err != nil {
185 return nil, nil, err
186 }
187 u := fmt.Sprintf("projects/%s/repository/branches", pathEscape(project))
188
189 req, err := s.client.NewRequest("POST", u, opt, options)
190 if err != nil {
191 return nil, nil, err
192 }
193
194 b := new(Branch)
195 resp, err := s.client.Do(req, b)
196 if err != nil {
197 return nil, resp, err
198 }
199
200 return b, resp, err
201}
202
203// DeleteBranch deletes an existing branch.
204//
205// GitLab API docs:
206// https://docs.gitlab.com/ce/api/branches.html#delete-repository-branch
207func (s *BranchesService) DeleteBranch(pid interface{}, branch string, options ...OptionFunc) (*Response, error) {
208 project, err := parseID(pid)
209 if err != nil {
210 return nil, err
211 }
212 u := fmt.Sprintf("projects/%s/repository/branches/%s", pathEscape(project), url.PathEscape(branch))
213
214 req, err := s.client.NewRequest("DELETE", u, nil, options)
215 if err != nil {
216 return nil, err
217 }
218
219 return s.client.Do(req, nil)
220}
221
222// DeleteMergedBranches deletes all branches that are merged into the project's default branch.
223//
224// GitLab API docs:
225// https://docs.gitlab.com/ce/api/branches.html#delete-merged-branches
226func (s *BranchesService) DeleteMergedBranches(pid interface{}, options ...OptionFunc) (*Response, error) {
227 project, err := parseID(pid)
228 if err != nil {
229 return nil, err
230 }
231 u := fmt.Sprintf("projects/%s/repository/merged_branches", pathEscape(project))
232
233 req, err := s.client.NewRequest("DELETE", u, nil, options)
234 if err != nil {
235 return nil, err
236 }
237
238 return s.client.Do(req, nil)
239}