1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
require 'mime/types'
module API
class Branches < Grape::API
include PaginationParams
BRANCH_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(branch: API::NO_SLASH_URL_PART_REGEX)
before { authorize! :download_code, user_project }
params do
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
desc 'Get a project repository branches' do
success Entities::RepoBranch
end
params do
use :pagination
end
get ':id/repository/branches' do
branches = ::Kaminari.paginate_array(user_project.repository.branches.sort_by(&:name))
# n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/37442
Gitlab::GitalyClient.allow_n_plus_1_calls do
present paginate(branches), with: Entities::RepoBranch, project: user_project
end
end
resource ':id/repository/branches/:branch', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
desc 'Get a single branch' do
success Entities::RepoBranch
end
params do
requires :branch, type: String, desc: 'The name of the branch'
end
head do
user_project.repository.branch_exists?(params[:branch]) ? status(204) : status(404)
end
get do
branch = user_project.repository.find_branch(params[:branch])
not_found!('Branch') unless branch
present branch, with: Entities::RepoBranch, project: user_project
end
end
# Note: This API will be deprecated in favor of the protected branches API.
# Note: The internal data model moved from `developers_can_{merge,push}` to `allowed_to_{merge,push}`
# in `gitlab-org/gitlab-ce!5081`. The API interface has not been changed (to maintain compatibility),
# but it works with the changed data model to infer `developers_can_merge` and `developers_can_push`.
desc 'Protect a single branch' do
success Entities::RepoBranch
end
params do
requires :branch, type: String, desc: 'The name of the branch'
optional :developers_can_push, type: Boolean, desc: 'Flag if developers can push to that branch'
optional :developers_can_merge, type: Boolean, desc: 'Flag if developers can merge to that branch'
end
put ':id/repository/branches/:branch/protect', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
authorize_admin_project
branch = user_project.repository.find_branch(params[:branch])
not_found!('Branch') unless branch
protected_branch = user_project.protected_branches.find_by(name: branch.name)
protected_branch_params = {
name: branch.name,
developers_can_push: params[:developers_can_push],
developers_can_merge: params[:developers_can_merge]
}
service_args = [user_project, current_user, protected_branch_params]
protected_branch = if protected_branch
::ProtectedBranches::ApiUpdateService.new(*service_args).execute(protected_branch)
else
::ProtectedBranches::ApiCreateService.new(*service_args).execute
end
if protected_branch.valid?
present branch, with: Entities::RepoBranch, project: user_project
else
render_api_error!(protected_branch.errors.full_messages, 422)
end
end
# Note: This API will be deprecated in favor of the protected branches API.
desc 'Unprotect a single branch' do
success Entities::RepoBranch
end
params do
requires :branch, type: String, desc: 'The name of the branch'
end
put ':id/repository/branches/:branch/unprotect', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
authorize_admin_project
branch = user_project.repository.find_branch(params[:branch])
not_found!("Branch") unless branch
protected_branch = user_project.protected_branches.find_by(name: branch.name)
protected_branch&.destroy
present branch, with: Entities::RepoBranch, project: user_project
end
desc 'Create branch' do
success Entities::RepoBranch
end
params do
requires :branch, type: String, desc: 'The name of the branch'
requires :ref, type: String, desc: 'Create branch from commit sha or existing branch'
end
post ':id/repository/branches' do
authorize_push_project
result = CreateBranchService.new(user_project, current_user)
.execute(params[:branch], params[:ref])
if result[:status] == :success
present result[:branch],
with: Entities::RepoBranch,
project: user_project
else
render_api_error!(result[:message], 400)
end
end
desc 'Delete a branch'
params do
requires :branch, type: String, desc: 'The name of the branch'
end
delete ':id/repository/branches/:branch', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
authorize_push_project
branch = user_project.repository.find_branch(params[:branch])
not_found!('Branch') unless branch
commit = user_project.repository.commit(branch.dereferenced_target)
destroy_conditionally!(commit, last_updated: commit.authored_date) do
result = DeleteBranchService.new(user_project, current_user)
.execute(params[:branch])
if result[:status] != :success
render_api_error!(result[:message], result[:return_code])
end
end
end
desc 'Delete all merged branches'
delete ':id/repository/merged_branches' do
DeleteMergedBranchesService.new(user_project, current_user).async_execute
accepted!
end
end
end
end
|