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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
require 'gitlab/satellite/satellite'
class Projects::MergeRequestsController < Projects::ApplicationController
before_filter :module_enabled
before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status]
before_filter :closes_issues, only: [:edit, :update, :show, :diffs]
before_filter :validates_merge_request, only: [:show, :diffs]
before_filter :define_show_vars, only: [:show, :diffs]
# Allow read any merge_request
before_filter :authorize_read_merge_request!
# Allow write(create) merge_request
before_filter :authorize_write_merge_request!, only: [:new, :create]
# Allow modify merge_request
before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
def index
params[:sort] ||= 'newest'
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
params[:project_id] = @project.id
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = @merge_requests.page(params[:page]).per(20)
@sort = params[:sort].humanize
assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
@assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
end
def show
respond_to do |format|
format.html
format.diff { render text: @merge_request.to_diff(current_user) }
format.patch { render text: @merge_request.to_patch(current_user) }
end
end
def diffs
@commit = @merge_request.last_commit
@comments_allowed = @reply_allowed = true
@comments_target = {noteable_type: 'MergeRequest',
noteable_id: @merge_request.id}
@line_notes = @merge_request.notes.where("line_code is not null")
diff_line_count = Commit::diff_line_count(@merge_request.diffs)
@suppress_diff = Commit::diff_suppress?(@merge_request.diffs, diff_line_count) && !params[:force_show_diff]
@force_suppress_diff = Commit::diff_force_suppress?(@merge_request.diffs, diff_line_count)
respond_to do |format|
format.html
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
end
end
def new
@merge_request = MergeRequest.new(params[:merge_request])
@merge_request.source_project = @project unless @merge_request.source_project
@merge_request.target_project = @project unless @merge_request.target_project
@target_branches = @merge_request.target_project.nil? ? [] : @merge_request.target_project.repository.branch_names
@source_project = @merge_request.source_project
@merge_request
end
def edit
@source_project = @merge_request.source_project
@target_project = @merge_request.target_project
@target_branches = @merge_request.target_project.repository.branch_names
end
def create
@merge_request = MergeRequest.new(params[:merge_request])
@merge_request.author = current_user
@target_branches ||= []
if @merge_request.save
@merge_request.reload_code
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully created.'
else
@source_project = @merge_request.source_project
@target_project = @merge_request.target_project
render action: "new"
end
end
def update
# If we close MergeRequest we want to ignore validation
# so we can close broken one (Ex. fork project removed)
if params[:merge_request] == {"state_event"=>"close"}
@merge_request.allow_broken = true
if @merge_request.close
opts = { notice: 'Merge request was successfully closed.' }
else
opts = { alert: 'Failed to close merge request.' }
end
redirect_to [@merge_request.target_project, @merge_request], opts
return
end
# We dont allow change of source/target projects
# after merge request was created
params[:merge_request].delete(:source_project_id)
params[:merge_request].delete(:target_project_id)
if @merge_request.update_attributes(params[:merge_request].merge(author_id_of_changes: current_user.id))
@merge_request.reload_code
@merge_request.mark_as_unchecked
@merge_request.reset_events_cache
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully updated.'
else
render "edit"
end
end
def automerge_check
if @merge_request.unchecked?
@merge_request.check_if_can_be_merged
end
render json: {merge_status: @merge_request.merge_status_name}
rescue Gitlab::SatelliteNotExistError
render json: {merge_status: :no_satellite}
end
def automerge
return access_denied! unless allowed_to_merge?
if @merge_request.opened? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user, params[:merge_commit_message])
@status = true
else
@status = false
end
end
def branch_from
#This is always source
@source_project = @merge_request.nil? ? @project : @merge_request.source_project
@commit = @repository.commit(params[:ref]) if params[:ref].present?
end
def branch_to
@target_project = selected_target_project
@commit = @target_project.repository.commit(params[:ref]) if params[:ref].present?
end
def update_branches
@target_project = selected_target_project
@target_branches = @target_project.repository.branch_names
@target_branches
end
def ci_status
status = project.gitlab_ci_service.commit_status(merge_request.last_commit.sha)
response = {status: status}
render json: response
end
protected
def selected_target_project
((@project.id.to_s == params[:target_project_id]) || @project.forked_project_link.nil?) ? @project : @project.forked_project_link.forked_from_project
end
def merge_request
@merge_request ||= @project.merge_requests.find_by!(iid: params[:id])
end
def closes_issues
@closes_issues ||= @merge_request.closes_issues
end
def authorize_modify_merge_request!
return render_404 unless can?(current_user, :modify_merge_request, @merge_request)
end
def authorize_admin_merge_request!
return render_404 unless can?(current_user, :admin_merge_request, @merge_request)
end
def module_enabled
return render_404 unless @project.merge_requests_enabled
end
def validates_merge_request
# If source project was removed (Ex. mr from fork to origin)
return invalid_mr unless @merge_request.source_project
# Show git not found page
# if there is no saved commits between source & target branch
if @merge_request.commits.blank?
# and if target branch doesn't exist
return invalid_mr unless @merge_request.target_branch_exists?
# or if source branch doesn't exist
return invalid_mr unless @merge_request.source_branch_exists?
end
end
def define_show_vars
# Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request)
@notes = @merge_request.mr_and_commit_notes.inc_author.fresh
@discussions = Note.discussions_from_notes(@notes)
@noteable = @merge_request
# Get commits from repository
# or from cache if already merged
@commits = @merge_request.commits
@allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
end
def allowed_to_merge?
action = if project.protected_branch?(@merge_request.target_branch)
:push_code_to_protected_branches
else
:push_code
end
can?(current_user, action, @project)
end
def invalid_mr
# Render special view for MR with removed source or target branch
render 'invalid'
end
end
|