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
|
require 'gitlab/satellite/satellite'
class Projects::MergeRequestsController < Projects::ApplicationController
before_filter :module_enabled
before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status]
before_filter :closes_issues, only: [:edit, :update, :show, :commits, :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
@merge_requests = MergeRequestsLoadContext.new(project, current_user, params).execute
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.js
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")
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 @merge_request.update_attributes(params[:merge_request].merge(author_id_of_changes: current_user.id))
@merge_request.reload_code
@merge_request.mark_as_unchecked
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)
@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
# Show git not found page if target branch doesn't exist
return invalid_mr unless @merge_request.target_project.repository.branch_names.include?(@merge_request.target_branch)
# Show git not found page if source branch doesn't exist
# and there is no saved commits between source & target branch
return invalid_mr if !@merge_request.source_project.repository.branch_names.include?(@merge_request.source_branch) && @merge_request.commits.blank?
end
def define_show_vars
# Build a note object for comment form
@note = @project.notes.new(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
@target_type = :merge_request
@target_id = @merge_request.id
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
|