Class: MergeRequestPresenter

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

Constant Summary collapse

APPROVALS_WIDGET_BASE_TYPE =
'base'

Instance Method Summary collapse

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, #fork_modal_options, #on_top_of_branch?, #patch_branch_name, #path_breadcrumbs, #relative_url_root, #selected_branch, #tree_edit_branch, #tree_icon, #tree_join, #vue_file_list_data, #web_ide_button_data

Methods included from WebIdeButtonHelper

#can_collaborate?, #can_create_mr_from_fork?, #edit_url, #fork?, #gitpod_url, #needs_to_fork?, #project_fork, #project_to_use, #readable_blob?, #show_edit_button?, #show_gitpod_button?, #show_pipeline_editor_button?, #show_web_ide_button?, #web_ide_url

Methods included from BlobHelper

#blob_editor_paths, #blob_icon, #blob_raw_path, #blob_raw_url, #blob_render_error_options, #blob_render_error_reason, #can_modify_blob?, #contribution_options, #copy_blob_source_button, #copy_file_path_button, #dockerfile_names, #download_blob_button, #edit_blob_button, #edit_blob_fork_params, #edit_blob_path, #edit_button_tag, #edit_disabled_button_tag, #edit_fork_button_tag, #edit_link_tag, #editing_preview_title, #encode_ide_path, #fork_and_edit_path, #fork_path_for_current_user, #gitignore_names, #gitlab_ci_ymls, #human_access, #ide_edit_path, #ide_fork_and_edit_path, #ide_merge_request_path, #leave_edit_message, #licenses_for_select, #open_raw_blob_button, #parent_dir_raw_path, #readable_blob, #ref_project, #sanitize_svg_data, #show_suggest_pipeline_creation_celebration?, #suggest_pipeline_commit_cookie_name, #vue_blob_app_data

Methods included from MarkupHelper

#cross_project_reference, #first_line_in_markdown, #link_to_html, #link_to_markdown, #link_to_markdown_field, #markdown, #markdown_field, #markup, #render_wiki_content

Methods included from Routing::PackagesHelper

#package_path

Methods included from Routing::PseudonymizationHelper

#masked_page_url

Methods included from Routing::GraphqlHelper

#graphql_etag_pipeline_path, #graphql_etag_pipeline_sha_path, #graphql_etag_project_on_demand_scan_counts_path

Methods included from Routing::WikiHelper

#wiki_page_path, #wiki_path

Methods included from Routing::SnippetsHelper

#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, #preview_markdown_path, #toggle_award_emoji_personal_snippet_path, #toggle_award_emoji_project_project_snippet_path, #toggle_award_emoji_project_project_snippet_url

Methods included from Routing::PipelineSchedulesHelper

#edit_pipeline_schedule_path, #pipeline_schedule_path, #pipeline_schedules_path, #play_pipeline_schedule_path, #take_ownership_pipeline_schedule_path

Methods included from Routing::ArtifactsHelper

#artifacts_action_path, #expose_fast_artifacts_path, #fast_browse_project_job_artifacts_path, #fast_download_project_job_artifacts_path, #fast_keep_project_job_artifacts_path

Methods included from Routing::MembersHelper

#source_members_url

Methods included from Routing::Groups::MembersHelper

#approve_access_request_group_member_path, #group_member_path, #group_members_url, #leave_group_members_path, #request_access_group_members_path, #resend_invite_group_member_path

Methods included from Routing::Projects::MembersHelper

#approve_access_request_project_member_path, #leave_project_members_path, #project_member_path, #project_members_url, #request_access_project_members_path, #resend_invite_project_member_path

Methods included from Routing::ProjectsHelper

#commit_url, #commits_url, #edit_milestone_path, #environment_delete_path, #environment_path, #issue_path, #issue_url, #merge_request_path, #merge_request_url, #pipeline_job_url, #pipeline_path, #pipeline_url, #project_commits_path, #project_ref_path, #project_tree_path, #release_url, #toggle_subscription_path, #work_item_url

Methods included from API::Helpers::RelatedResourcesHelpers

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

Methods included from ApplicationSettingsHelper

#all_protocols_enabled?, #allowed_protocols_present?, #anti_spam_service_enabled?, #deprecated_attributes, #enabled_protocol, #enabled_protocol_button, #expanded_by_default?, #external_authorization_allow_token_help_text, #external_authorization_client_certificate_help_text, #external_authorization_client_key_help_text, #external_authorization_client_pass_help_text, #external_authorization_client_url_help_text, #external_authorization_description, #external_authorization_service_attributes, #external_authorization_timeout_help_text, #external_authorization_url_help_text, #http_enabled?, #import_sources_checkboxes, #instance_clusters_enabled?, #integration_expanded?, #key_restriction_options_for_select, #kroki_available_formats, #oauth_providers_checkboxes, #omnibus_protected_paths_throttle?, #pending_user_count, #registration_features_can_be_prompted?, #repository_storages_options_json, #restricted_level_checkboxes, #runner_token_expiration_interval_attributes, #sidekiq_job_limiter_mode_help_text, #sidekiq_job_limiter_modes_for_select, #signup_enabled?, #signup_form_data, #ssh_enabled?, #storage_weights, #user_oauth_applications?, #valid_runner_registrars, #visible_attributes

Methods included from ProjectsHelper

#able_to_see_forks_count?, #able_to_see_issues?, #able_to_see_merge_requests?, #any_projects?, #author_content_tag, #autodeploy_flash_notice, #badge_count, #branch_rules_path, #can_admin_associated_clusters?, #can_admin_project_member?, #can_change_visibility_level?, #can_disable_emails?, #can_push_code?, #can_view_branch_rules?, #clusters_deprecation_alert_message, #delete_confirm_phrase, #directory?, #error_tracking_setting_project_json, #explore_projects_tab?, #external_classification_label_help_message, #fork_button_data_attributes, #grafana_integration_enabled?, #grafana_integration_masked_token, #grafana_integration_url, #http_clone_url_to_repo, #import_from_bitbucket_message, #import_from_gitlab_message, #inactive_project_deletion_date, #last_pipeline_from_status_cache, #last_push_event, #link_to_autodeploy_doc, #link_to_member, #link_to_member_avatar, #link_to_project, #load_pipeline_status, #localized_project_human_access, #membership_locked?, #no_password_message, #project_can_be_shared?, #project_classes, #project_coverage_chart_data_attributes, #project_incident_management_setting, #project_license_name, #project_list_cache_key, #project_permissions_panel_data, #project_title, #push_to_create_project_command, #remote_mirror_setting_enabled?, #remove_fork_project_confirm_json, #remove_fork_project_description_message, #remove_fork_project_warning_message, #remove_project_message, #show_auto_devops_implicitly_enabled_banner?, #show_clusters_alert?, #show_count?, #show_inactive_project_deletion_banner?, #show_mobile_devops_project_promo?, #show_no_password_message?, #show_no_ssh_key_message?, #show_projects?, #show_terraform_banner?, #show_xcode_link?, #ssh_clone_url_to_repo, #transfer_project_message, #visibility_level_content, #visible_fork_source, #vue_fork_divergence_data, #xcode_uri_to_repo

Methods included from Gitlab::Allowable

#can?

Methods included from CompareHelper

#create_mr_button?, #create_mr_path, #project_compare_selector_data, #target_projects

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

#initialize

Methods included from Gitlab::Utils::DelegatorOverride

#delegator_override, #delegator_override_with, #delegator_target, validator, validators, verify!

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

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

Methods included from Gitlab::Routing

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



214
215
216
# File 'app/presenters/merge_request_presenter.rb', line 214

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



218
219
220
# File 'app/presenters/merge_request_presenter.rb', line 218

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



222
223
224
# File 'app/presenters/merge_request_presenter.rb', line 222

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



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

def approvals_widget_type
  APPROVALS_WIDGET_BASE_TYPE
end

#assign_to_closing_issues_countObject



152
153
154
155
156
157
158
159
160
161
162
# File 'app/presenters/merge_request_presenter.rb', line 152

def assign_to_closing_issues_count
  # rubocop: disable CodeReuse/ServiceClass
  issues = MergeRequests::AssignIssuesService.new(
    project: project,
    current_user: current_user,
    params: { merge_request: merge_request, closes_issues: closing_issues }
  ).assignable_issues

  issues.count
  # rubocop: enable CodeReuse/ServiceClass
end

#assign_to_closing_issues_pathObject



148
149
150
# File 'app/presenters/merge_request_presenter.rb', line 148

def assign_to_closing_issues_path
  assign_related_issues_project_merge_request_path(project, merge_request)
end

#can_cherry_pick_on_current_merge_request?Boolean

Returns:

  • (Boolean)


168
169
170
# File 'app/presenters/merge_request_presenter.rb', line 168

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)


172
173
174
175
176
177
178
# File 'app/presenters/merge_request_presenter.rb', line 172

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)


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

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

#can_remove_source_branch?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'app/presenters/merge_request_presenter.rb', line 181

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)


164
165
166
# File 'app/presenters/merge_request_presenter.rb', line 164

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

#cancel_auto_merge_pathObject



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

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



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

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



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

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

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

#closing_issuesObject



230
231
232
233
234
# File 'app/presenters/merge_request_presenter.rb', line 230

def closing_issues
  strong_memoize(:closing_issues) do
    visible_closing_issues_for(current_user)
  end
end


128
129
130
131
132
133
134
135
136
# File 'app/presenters/merge_request_presenter.rb', line 128

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

#conflict_resolution_pathObject



76
77
78
79
80
# File 'app/presenters/merge_request_presenter.rb', line 76

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



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

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

#mentioned_issuesObject



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

def mentioned_issues
  strong_memoize(:mentioned_issues) do
    issues_mentioned_but_not_closing(current_user)
  end
end


138
139
140
141
142
143
144
145
146
# File 'app/presenters/merge_request_presenter.rb', line 138

def mentioned_issues_links
  markdown(
    issues_sentence(project, mentioned_issues),
    pipeline: :gfm,
    author: author,
    project: project,
    issuable_reference_expansion_enabled: true
  )
end

#merge_pathObject



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

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

#mergeable_discussions_stateObject



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

def mergeable_discussions_state
  merge_request.mergeable_discussions_state?
end

#pipeline_coverage_deltaObject



243
244
245
246
247
# File 'app/presenters/merge_request_presenter.rb', line 243

def pipeline_coverage_delta
  return unless merge_request.pipeline_coverage_delta.present?

  '%.2f' % merge_request.pipeline_coverage_delta
end

#rebase_pathObject



82
83
84
85
86
# File 'app/presenters/merge_request_presenter.rb', line 82

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



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

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

#revert_in_fork_pathObject



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

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



106
107
108
109
110
# File 'app/presenters/merge_request_presenter.rb', line 106

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


198
199
200
201
202
203
204
# File 'app/presenters/merge_request_presenter.rb', line 198

def source_branch_link
  if source_branch_exists?
    link_to(source_branch, source_branch_commits_path, class: 'ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2')
  else
    (:span, source_branch, class: 'ref-name')
  end
end

#source_branch_pathObject



112
113
114
115
116
# File 'app/presenters/merge_request_presenter.rb', line 112

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


118
119
120
121
122
123
124
125
126
# File 'app/presenters/merge_request_presenter.rb', line 118

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)


194
195
196
# File 'app/presenters/merge_request_presenter.rb', line 194

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

#target_branch_commits_pathObject



94
95
96
97
98
# File 'app/presenters/merge_request_presenter.rb', line 94

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


206
207
208
209
210
211
212
# File 'app/presenters/merge_request_presenter.rb', line 206

def target_branch_link
  if target_branch_exists?
    link_to(target_branch, target_branch_commits_path, class: 'ref-name gl-link gl-bg-blue-50 gl-rounded-base gl-px-2')
  else
    (:span, target_branch, class: 'ref-name')
  end
end

#target_branch_pathObject



100
101
102
103
104
# File 'app/presenters/merge_request_presenter.rb', line 100

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

#target_branch_tree_pathObject



88
89
90
91
92
# File 'app/presenters/merge_request_presenter.rb', line 88

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