Class: MergeRequestPresenter

Inherits:
Gitlab::View::Presenter::Delegated show all
Includes:
ActionView::Helpers::UrlHelper, ChecksCollaboration, Gitlab::Utils::StrongMemoize, GitlabRoutingHelper, MarkupHelper, TreeHelper
Defined in:
app/presenters/merge_request_presenter.rb

Constant Summary collapse

APPROVALS_WIDGET_BASE_TYPE =
'base'

Constants included from TreeHelper

TreeHelper::FILE_LIMIT

Instance Attribute Summary

Attributes included from Gitlab::View::Presenter::Base

#subject

Instance Method Summary collapse

Methods included from Gitlab::Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Methods included from ChecksCollaboration

#can_collaborate_with_project?, #user_access

Methods included from TreeHelper

#breadcrumb_data_attributes, #can_edit_tree?, #commit_in_fork_help, #commit_in_single_accessible_branch, #directory_download_links, #edit_in_new_fork_notice, #edit_in_new_fork_notice_action, #edit_in_new_fork_notice_now, #fast_project_blob_path, #fast_project_tree_path, #flatten_tree, #on_top_of_branch?, #path_breadcrumbs, #relative_url_root, #render_tree, #selected_branch, #tree_content_data, #tree_edit_branch, #tree_edit_project, #tree_icon, #tree_join, #up_dir_path, #vue_file_list_data

Methods included from MarkupHelper

#asciidoc?, #cross_project_reference, #first_line_in_markdown, #gitlab_markdown?, #link_to_html, #link_to_markdown, #link_to_markdown_field, #markdown, #markdown_field, #markup, #markup?, #markup_unsafe, #plain?, #render_wiki_content

Methods included from GitlabRoutingHelper

#approve_access_request_group_member_path, #approve_access_request_project_member_path, #artifacts_action_path, #commit_url, #commits_url, #edit_milestone_path, #edit_pipeline_schedule_path, #environment_delete_path, #environment_metrics_path, #environment_path, #expose_fast_artifacts_path, #fast_browse_project_job_artifacts_path, #fast_download_project_job_artifacts_path, #fast_keep_project_job_artifacts_path, #gitlab_dashboard_snippets_path, #gitlab_raw_snippet_blob_path, #gitlab_raw_snippet_blob_url, #gitlab_raw_snippet_path, #gitlab_raw_snippet_url, #gitlab_snippet_note_path, #gitlab_snippet_note_url, #gitlab_snippet_notes_path, #gitlab_snippet_notes_url, #gitlab_snippet_path, #gitlab_snippet_url, #gitlab_toggle_award_emoji_snippet_note_path, #gitlab_toggle_award_emoji_snippet_note_url, #gitlab_toggle_award_emoji_snippet_path, #gitlab_toggle_award_emoji_snippet_url, #group_member_path, #group_members_url, #issue_path, #issue_url, #leave_group_members_path, #leave_project_members_path, #merge_request_path, #merge_request_url, #pipeline_job_url, #pipeline_path, #pipeline_schedule_path, #pipeline_schedules_path, #pipeline_url, #play_pipeline_schedule_path, #preview_markdown_path, #project_commits_path, #project_member_path, #project_members_url, #project_ref_path, #project_tree_path, #request_access_group_members_path, #request_access_project_members_path, #resend_invite_group_member_path, #resend_invite_project_member_path, #take_ownership_pipeline_schedule_path, #toggle_award_emoji_personal_snippet_path, #toggle_award_emoji_project_project_snippet_path, #toggle_award_emoji_project_project_snippet_url, #toggle_subscription_path, #wiki_page_path, #wiki_path

Methods included from API::Helpers::RelatedResourcesHelpers

#expose_path, #expose_url, #issues_available?, #mrs_available?

Methods inherited from Gitlab::View::Presenter::Delegated

#initialize

Methods included from Gitlab::View::Presenter::Base

#can?, #declarative_policy_delegate, #is_a?, #present, #url_builder, #web_path, #web_url

Methods included from Gitlab::Allowable

#can?

Methods included from Gitlab::Routing

add_helpers, includes_helpers, redirect_legacy_paths, url_helpers

Constructor Details

This class inherits a constructor from Gitlab::View::Presenter::Delegated

Instance Method Details

#api_approvals_pathObject


225
226
227
# File 'app/presenters/merge_request_presenter.rb', line 225

def api_approvals_path
  expose_path(api_v4_projects_merge_requests_approvals_path(id: project.id, merge_request_iid: merge_request.iid))
end

#api_approve_pathObject


229
230
231
# File 'app/presenters/merge_request_presenter.rb', line 229

def api_approve_path
  expose_path(api_v4_projects_merge_requests_approve_path(id: project.id, merge_request_iid: merge_request.iid))
end

#api_unapprove_pathObject


233
234
235
# File 'app/presenters/merge_request_presenter.rb', line 233

def api_unapprove_path
  expose_path(api_v4_projects_merge_requests_unapprove_path(id: project.id, merge_request_iid: merge_request.iid))
end

#approvals_widget_typeObject


237
238
239
# File 'app/presenters/merge_request_presenter.rb', line 237

def approvals_widget_type
  APPROVALS_WIDGET_BASE_TYPE
end

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'app/presenters/merge_request_presenter.rb', line 152

def assign_to_closing_issues_link
  # rubocop: disable CodeReuse/ServiceClass
  issues = MergeRequests::AssignIssuesService.new(project,
                                                  current_user,
                                                  merge_request: merge_request,
                                                  closes_issues: closing_issues
                                                 ).assignable_issues
  path = assign_related_issues_project_merge_request_path(project, merge_request)
  if issues.present?
    if issues.count > 1
      link_to _('Assign yourself to these issues'), path, method: :post
    else
      link_to _('Assign yourself to this issue'), path, method: :post
    end
  end
  # rubocop: enable CodeReuse/ServiceClass
end

#can_cherry_pick_on_current_merge_request?Boolean

Returns:

  • (Boolean)

174
175
176
# File 'app/presenters/merge_request_presenter.rb', line 174

def can_cherry_pick_on_current_merge_request?
  can_collaborate_with_project?(project) && can_be_cherry_picked?
end

#can_push_to_source_branch?Boolean

Returns:

  • (Boolean)

178
179
180
181
182
183
184
# File 'app/presenters/merge_request_presenter.rb', line 178

def can_push_to_source_branch?
  return false unless source_branch_exists?

  !!::Gitlab::UserAccess
    .new(current_user, container: source_project)
    .can_push_to_branch?(source_branch)
end

#can_read_pipeline?Boolean

Returns:

  • (Boolean)

190
191
192
# File 'app/presenters/merge_request_presenter.rb', line 190

def can_read_pipeline?
  pipeline && can?(current_user, :read_pipeline, pipeline)
end

#can_remove_source_branch?Boolean

Returns:

  • (Boolean)

186
187
188
# File 'app/presenters/merge_request_presenter.rb', line 186

def can_remove_source_branch?
  source_branch_exists? && merge_request.can_remove_source_branch?(current_user)
end

#can_revert_on_current_merge_request?Boolean

Returns:

  • (Boolean)

170
171
172
# File 'app/presenters/merge_request_presenter.rb', line 170

def can_revert_on_current_merge_request?
  can_collaborate_with_project?(project) && cached_can_be_reverted?
end

#cancel_auto_merge_pathObject


27
28
29
30
31
# File 'app/presenters/merge_request_presenter.rb', line 27

def cancel_auto_merge_path
  if can_cancel_auto_merge?(current_user)
    cancel_auto_merge_project_merge_request_path(project, merge_request)
  end
end

#cherry_pick_in_fork_pathObject


65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'app/presenters/merge_request_presenter.rb', line 65

def cherry_pick_in_fork_path
  if user_can_fork_project? && can_be_cherry_picked?
    continue_params = {
      to: merge_request_path(merge_request),
      notice: _('%{edit_in_new_fork_notice} Try to revert this commit again.') % { edit_in_new_fork_notice: edit_in_new_fork_notice },
      notice_now: edit_in_new_fork_notice_now
    }

    project_forks_path(project,
                                 namespace_key: current_user.namespace.id,
                                 continue: continue_params)
  end
end

#ci_statusObject


15
16
17
18
19
20
21
22
23
24
25
# File 'app/presenters/merge_request_presenter.rb', line 15

def ci_status
  if pipeline
    status = pipeline.status
    status = "success-with-warnings" if pipeline.success? && pipeline.has_warnings?

    status || "preparing"
  else
    ci_service = source_project.try(:ci_service)
    ci_service&.commit_status(diff_head_sha, source_branch)
  end
end

131
132
133
134
135
136
137
138
139
# File 'app/presenters/merge_request_presenter.rb', line 131

def closing_issues_links
  markdown(
    issues_sentence(project, closing_issues),
    pipeline: :gfm,
    author: author,
    project: project,
    issuable_state_filter_enabled: true
  )
end

#conflict_resolution_pathObject


79
80
81
82
83
# File 'app/presenters/merge_request_presenter.rb', line 79

def conflict_resolution_path
  if conflicts.can_be_resolved_in_ui? && conflicts.can_be_resolved_by?(current_user)
    conflicts_project_merge_request_path(project, merge_request)
  end
end

#create_issue_to_resolve_discussions_pathObject


33
34
35
36
37
# File 'app/presenters/merge_request_presenter.rb', line 33

def create_issue_to_resolve_discussions_path
  if can?(current_user, :create_issue, project) && project.issues_enabled?
    new_project_issue_path(project, merge_request_to_resolve_discussions_of: iid)
  end
end

141
142
143
144
145
146
147
148
149
150
# File 'app/presenters/merge_request_presenter.rb', line 141

def mentioned_issues_links
  mentioned_issues = issues_mentioned_but_not_closing(current_user)
  markdown(
    issues_sentence(project, mentioned_issues),
    pipeline: :gfm,
    author: author,
    project: project,
    issuable_state_filter_enabled: true
  )
end

#merge_pathObject


45
46
47
48
49
# File 'app/presenters/merge_request_presenter.rb', line 45

def merge_path
  if can_be_merged_by?(current_user)
    merge_project_merge_request_path(project, merge_request)
  end
end

#mergeable_discussions_stateObject


194
195
196
197
198
199
200
201
202
203
# File 'app/presenters/merge_request_presenter.rb', line 194

def mergeable_discussions_state
  # This avoids calling MergeRequest#mergeable_discussions_state without
  # considering the state of the MR first. If a MR isn't mergeable, we can
  # safely short-circuit it.
  if merge_request.mergeable_state?(skip_ci_check: true, skip_discussions_check: true)
    merge_request.mergeable_discussions_state?
  else
    false
  end
end

#rebase_pathObject


85
86
87
88
89
# File 'app/presenters/merge_request_presenter.rb', line 85

def rebase_path
  if !rebase_in_progress? && should_be_rebased? && can_push_to_source_branch?
    rebase_project_merge_request_path(project, merge_request)
  end
end

#remove_wip_pathObject


39
40
41
42
43
# File 'app/presenters/merge_request_presenter.rb', line 39

def remove_wip_path
  if work_in_progress? && can?(current_user, :update_merge_request, merge_request.project)
    remove_wip_project_merge_request_path(project, merge_request)
  end
end

#revert_in_fork_pathObject


51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/presenters/merge_request_presenter.rb', line 51

def revert_in_fork_path
  if user_can_fork_project? && cached_can_be_reverted?
    continue_params = {
      to: merge_request_path(merge_request),
      notice: _('%{edit_in_new_fork_notice} Try to cherry-pick this commit again.') % { edit_in_new_fork_notice: edit_in_new_fork_notice },
      notice_now: edit_in_new_fork_notice_now
    }

    project_forks_path(merge_request.project,
                                 namespace_key: current_user.namespace.id,
                                 continue: continue_params)
  end
end

#source_branch_commits_pathObject


109
110
111
112
113
# File 'app/presenters/merge_request_presenter.rb', line 109

def source_branch_commits_path
  if source_branch_exists?
    project_commits_path(source_project, source_branch)
  end
end

209
210
211
212
213
214
215
# File 'app/presenters/merge_request_presenter.rb', line 209

def source_branch_link
  if source_branch_exists?
    link_to(source_branch, source_branch_commits_path, class: 'ref-name')
  else
    (:span, source_branch, class: 'ref-name')
  end
end

#source_branch_pathObject


115
116
117
118
119
# File 'app/presenters/merge_request_presenter.rb', line 115

def source_branch_path
  if source_branch_exists?
    project_branch_path(source_project, source_branch)
  end
end

121
122
123
124
125
126
127
128
129
# File 'app/presenters/merge_request_presenter.rb', line 121

def source_branch_with_namespace_link
  namespace = source_project_namespace
  branch = source_branch

  namespace_link = source_branch_exists? ? link_to(namespace, project_path(source_project)) : ERB::Util.html_escape(namespace)
  branch_link = source_branch_exists? ? link_to(branch, project_tree_path(source_project, source_branch)) : ERB::Util.html_escape(branch)

  for_fork? ? "#{namespace_link}:#{branch_link}" : branch_link
end

#subscribed?Boolean

Returns:

  • (Boolean)

205
206
207
# File 'app/presenters/merge_request_presenter.rb', line 205

def subscribed?
  merge_request.subscribed?(current_user, merge_request.target_project)
end

#target_branch_commits_pathObject


97
98
99
100
101
# File 'app/presenters/merge_request_presenter.rb', line 97

def target_branch_commits_path
  if target_branch_exists?
    project_commits_path(project, target_branch)
  end
end

217
218
219
220
221
222
223
# File 'app/presenters/merge_request_presenter.rb', line 217

def target_branch_link
  if target_branch_exists?
    link_to(target_branch, target_branch_commits_path, class: 'ref-name')
  else
    (:span, target_branch, class: 'ref-name')
  end
end

#target_branch_pathObject


103
104
105
106
107
# File 'app/presenters/merge_request_presenter.rb', line 103

def target_branch_path
  if target_branch_exists?
    project_branch_path(project, target_branch)
  end
end

#target_branch_tree_pathObject


91
92
93
94
95
# File 'app/presenters/merge_request_presenter.rb', line 91

def target_branch_tree_path
  if target_branch_exists?
    project_tree_path(project, target_branch)
  end
end