Module: MergeRequestsHelper

Includes:
CompareHelper, Gitlab::Utils::StrongMemoize
Included in:
HomepageData, MergeRequestDiffEntity, Profile::EventEntity, Projects::MergeRequestsController, Sidebars::YourWork::Menus::MergeRequestsMenu, SidebarsHelper
Defined in:
app/helpers/merge_requests_helper.rb

Constant Summary collapse

DIFF_BATCH_ENDPOINT_PER_PAGE =
5

Instance Method Summary collapse

Methods included from CompareHelper

#create_mr_button?, #create_mr_path, #project_compare_selector_data

Instance Method Details

#allow_collaboration_unavailable_reason(merge_request) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'app/helpers/merge_requests_helper.rb', line 127

def allow_collaboration_unavailable_reason(merge_request)
  return if merge_request.can_allow_collaboration?(current_user)

  minimum_visibility = [merge_request.target_project.visibility_level,
    merge_request.source_project.visibility_level].min

  if minimum_visibility < Gitlab::VisibilityLevel::INTERNAL
    _('Not available for private projects')
  elsif ProtectedBranch.protected?(merge_request.source_project, merge_request.source_branch)
    _('Not available for protected branches')
  elsif !merge_request.author.can?(:push_code, merge_request.source_project)
    _('Merge request author cannot push to target project')
  end
end

#award_emoji_merge_request_api_path(merge_request) ⇒ Object



214
215
216
# File 'app/helpers/merge_requests_helper.rb', line 214

def award_emoji_merge_request_api_path(merge_request)
  api_v4_projects_merge_requests_award_emoji_path(id: merge_request.project.id, merge_request_iid: merge_request.iid)
end

#can_use_description_composer(_user, _merge_request) ⇒ Object



173
174
175
# File 'app/helpers/merge_requests_helper.rb', line 173

def can_use_description_composer(_user, _merge_request)
  false
end

#common_merge_request_list_data(current_user) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'app/helpers/merge_requests_helper.rb', line 247

def common_merge_request_list_data(current_user)
  {
    autocomplete_award_emojis_path: autocomplete_award_emojis_path,
    merge_request_target_branches_path: autocomplete_merge_request_target_branches_path,
    merge_request_source_branches_path: autocomplete_merge_request_source_branches_path,
    initial_sort: default_merge_request_sort || current_user&.user_preference&.merge_requests_sort,
    is_public_visibility_restricted:
      Gitlab::CurrentSettings.restricted_visibility_levels&.include?(Gitlab::VisibilityLevel::PUBLIC).to_s,
    is_signed_in: current_user.present?.to_s,
    show_export_button: "true",
    issuable_type: :merge_request,
    email: current_user.present? ? current_user.notification_email_or_default : nil,
    rss_url: url_for(safe_params.merge(rss_url_options)),
    emails_help_page_path: help_page_path('development/emails.md', anchor: 'email-namespace'),
    quick_actions_help_path: help_page_path('user/project/quick_actions.md'),
    markdown_help_path: help_page_path('user/markdown.md')
  }
end

#create_mr_button_from_event?(event) ⇒ Boolean



8
9
10
# File 'app/helpers/merge_requests_helper.rb', line 8

def create_mr_button_from_event?(event)
  create_mr_button?(from: event.branch_name, source_project: event.project)
end

#create_mr_path_from_push_event(event) ⇒ Object



12
13
14
# File 'app/helpers/merge_requests_helper.rb', line 12

def create_mr_path_from_push_event(event)
  create_mr_path(from: event.branch_name, source_project: event.project)
end

#default_merge_request_sortObject



239
240
241
242
243
244
245
# File 'app/helpers/merge_requests_helper.rb', line 239

def default_merge_request_sort
  return params[:sort] if params[:sort]

  case params[:state]
  when 'merged', 'closed' then sort_value_recently_updated
  end
end

#diffs_tab_pane_data(project, merge_request, params) ⇒ Object



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
# File 'app/helpers/merge_requests_helper.rb', line 180

def diffs_tab_pane_data(project, merge_request, params)
  {
    "is-locked": merge_request.discussion_locked?,
    endpoint: diffs_project_merge_request_path(project, merge_request, 'json', params),
    endpoint_metadata: ,
    endpoint_batch: diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params),
    endpoint_coverage: @coverage_path,
    endpoint_diff_for_path: diff_for_path_namespace_project_merge_request_path(
      format: 'json',
      id: merge_request.iid,
      namespace_id: project.namespace.to_param,
      project_id: project.path
    ),
    help_page_path: help_page_path('user/project/merge_requests/reviews/suggestions.md'),
    current_user_data: @current_user_data,
    update_current_user_path: @update_current_user_path,
    project_path: project_path(merge_request.project),
    changes_empty_state_illustration: image_path('illustrations/empty-state/empty-commit-md.svg'),
    is_fluid_layout: fluid_layout.to_s,
    dismiss_endpoint: callouts_path,
    show_suggest_popover: show_suggest_popover?.to_s,
    show_whitespace_default: @show_whitespace_default.to_s,
    file_by_file_default: @file_by_file_default.to_s,
    default_suggestion_commit_message: default_suggestion_commit_message(project),
    source_project_default_url: merge_request.source_project && default_url_to_repo(merge_request.source_project),
    source_project_full_path: merge_request.source_project&.full_path,
    is_forked: project.forked?.to_s,
    new_comment_template_paths: new_comment_template_paths(project.group, project).to_json,
    iid: merge_request.iid,
    per_page: DIFF_BATCH_ENDPOINT_PER_PAGE,
    linked_file_url: @linked_file_url
  }
end

#format_mr_branch_names(merge_request) ⇒ Object



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

def format_mr_branch_names(merge_request)
  source_path = merge_request.source_project_path
  target_path = merge_request.target_project_path
  source_branch = merge_request.source_branch
  target_branch = merge_request.target_branch

  if source_path == target_path
    [source_branch, target_branch]
  else
    ["#{source_path}:#{source_branch}", "#{target_path}:#{target_branch}"]
  end
end

#group_merge_requests_list_data(group, current_user) ⇒ Object



283
284
285
286
287
288
289
290
291
292
293
294
# File 'app/helpers/merge_requests_helper.rb', line 283

def group_merge_requests_list_data(group, current_user)
  common_merge_request_list_data(current_user).merge({
    namespace_id: group.id,
    full_path: group.full_path,
    show_new_resource_dropdown: (current_user.presence && any_projects?(@projects)).to_s,
    has_any_merge_requests: group_merge_requests(group).exists?.to_s,
    releases_endpoint: group_releases_path(group, format: :json),
    can_bulk_update: (can?(current_user, :admin_merge_request, group) &&
      group.licensed_feature_available?(:group_bulk_edit)).to_s,
    environment_names_path: unfoldered_environment_names_group_path(group, :json)
  })
end

#how_merge_modal_data(merge_request) ⇒ Object



218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'app/helpers/merge_requests_helper.rb', line 218

def how_merge_modal_data(merge_request)
  {
    is_fork: merge_request.for_fork?.to_s,
    source_branch: merge_request.source_branch,
    source_project_path: merge_request.source_project&.path,
    source_project_full_path: merge_request.source_project&.full_path,
    source_project_default_url: merge_request.source_project && default_url_to_repo(merge_request.source_project),
    reviewing_docs_path: help_page_path(
      'user/project/merge_requests/merge_request_troubleshooting.md',
      anchor: "check-out-merge-requests-locally-through-the-head-ref"
    )
  }
end

#identity_verification_alert_data(_) ⇒ Object



296
297
298
# File 'app/helpers/merge_requests_helper.rb', line 296

def identity_verification_alert_data(_)
  { identity_verification_required: 'false' }
end

#merge_params(merge_request) ⇒ Object



92
93
94
95
96
97
98
99
# File 'app/helpers/merge_requests_helper.rb', line 92

def merge_params(merge_request)
  {
    auto_merge_strategy: merge_request.default_auto_merge_strategy,
    should_remove_source_branch: true,
    sha: merge_request.diff_head_sha,
    squash: merge_request.squash_on_merge?
  }
end

#merge_path_description(merge_request, with_arrow: false) ⇒ Object



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
# File 'app/helpers/merge_requests_helper.rb', line 23

def merge_path_description(merge_request, with_arrow: false)
  if merge_request.for_fork?
    msg = if with_arrow
            _("Project:Branches: %{source_project_path}:%{source_branch} → %{target_project_path}:%{target_branch}")
          else
            _("Project:Branches: %{source_project_path}:%{source_branch} to %{target_project_path}:%{target_branch}")
          end

    msg % {
      source_project_path: merge_request.source_project_path,
      source_branch: merge_request.source_branch,
      target_project_path: merge_request.target_project.full_path,
      target_branch: merge_request.target_branch
    }
  else
    msg = if with_arrow
            _("Branches: %{source_branch} → %{target_branch}")
          else
            _("Branches: %{source_branch} to %{target_branch}")
          end

    msg % {
      source_branch: merge_request.source_branch,
      target_branch: merge_request.target_branch
    }
  end
end

#merge_request_button_hidden?(merge_request, closed) ⇒ Boolean



82
83
84
85
86
# File 'app/helpers/merge_requests_helper.rb', line 82

def merge_request_button_hidden?(merge_request, closed)
  merge_request.closed? == closed ||
    (merge_request.merged? == closed && !merge_request.closed?) ||
    merge_request.closed_or_merged_without_fork?
end

#merge_request_dashboard_show_drafts?Boolean



349
350
351
# File 'app/helpers/merge_requests_helper.rb', line 349

def merge_request_dashboard_show_drafts?
  current_user.merge_request_dashboard_show_drafts
end

#merge_request_source_project_for_project(project = @project) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
# File 'app/helpers/merge_requests_helper.rb', line 142

def merge_request_source_project_for_project(project = @project)
  unless can?(current_user, :create_merge_request_in, project)
    return
  end

  if can?(current_user, :create_merge_request_from, project)
    project
  else
    current_user.fork_of(project)
  end
end

#merge_request_squash_option?(merge_request) ⇒ Boolean



345
346
347
# File 'app/helpers/merge_requests_helper.rb', line 345

def merge_request_squash_option?(merge_request)
  merge_request.persisted? ? merge_request.squash : merge_request.squash_enabled_by_default?
end

#merge_request_version_path(project, merge_request, merge_request_diff, start_sha = nil) ⇒ Object



88
89
90
# File 'app/helpers/merge_requests_helper.rb', line 88

def merge_request_version_path(project, merge_request, merge_request_diff, start_sha = nil)
  diffs_project_merge_request_path(project, merge_request, diff_id: merge_request_diff.id, start_sha: start_sha)
end

#mr_change_branches_path(merge_request) ⇒ Object



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

def mr_change_branches_path(merge_request)
  project_new_merge_request_path(
    @project,
    merge_request: {
      source_project_id: merge_request.source_project_id,
      target_project_id: merge_request.target_project_id,
      source_branch: merge_request.source_branch,
      target_branch: merge_request.target_branch
    },
    change_branches: true
  )
end

#mr_compare_form_data(_, merge_request) ⇒ Object



232
233
234
235
236
237
# File 'app/helpers/merge_requests_helper.rb', line 232

def mr_compare_form_data(_, merge_request)
  {
    source_branch_url: project_new_merge_request_branch_from_path(merge_request.source_project),
    target_branch_url: project_new_merge_request_branch_to_path(merge_request.source_project)
  }
end

#mr_css_classes(mr) ⇒ Object



16
17
18
19
20
21
# File 'app/helpers/merge_requests_helper.rb', line 16

def mr_css_classes(mr)
  classes = ["merge-request"]
  classes << "closed" if mr.closed?
  classes << "merged" if mr.merged?
  classes.join(' ')
end

#notifications_todos_buttons_enabled?Boolean



169
170
171
# File 'app/helpers/merge_requests_helper.rb', line 169

def notifications_todos_buttons_enabled?
  Feature.enabled?(:notifications_todos_buttons, current_user)
end

#project_merge_requests_list_data(project, current_user) ⇒ Object



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'app/helpers/merge_requests_helper.rb', line 266

def project_merge_requests_list_data(project, current_user)
  merge_project = merge_request_source_project_for_project(project)

  common_merge_request_list_data(current_user).merge({
    namespace_id: project.id,
    full_path: project.full_path,
    has_any_merge_requests: project_merge_requests(project).exists?.to_s,
    new_merge_request_path: merge_project && project_new_merge_request_path(merge_project),
    export_csv_path: export_csv_project_merge_requests_path(project),
    releases_endpoint: project_releases_path(project, format: :json),
    can_bulk_update: can?(current_user, :admin_merge_request, project).to_s,
    environment_names_path: unfoldered_environment_names_project_path(project, :json),
    initial_email: can?(current_user, :create_merge_request_in, project) &&
      project.new_issuable_address(current_user, 'merge_request')
  })
end

#reviewers_label(merge_request, include_value: true) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'app/helpers/merge_requests_helper.rb', line 154

def reviewers_label(merge_request, include_value: true)
  reviewers = merge_request.reviewers

  if include_value
    sanitized_list = sanitize_name(reviewers.map(&:name).to_sentence)
    ns_(
      'NotificationEmail|Reviewer: %{users}',
      'NotificationEmail|Reviewers: %{users}',
      reviewers.count
    ) % { users: sanitized_list }
  else
    ns_('NotificationEmail|Reviewer', 'NotificationEmail|Reviewers', reviewers.count)
  end
end

#show_mr_dashboard_banner?Boolean



339
340
341
342
343
# File 'app/helpers/merge_requests_helper.rb', line 339

def show_mr_dashboard_banner?
  request.query_string.present? &&
    current_page?(merge_requests_search_dashboard_path) &&
    show_new_mr_dashboard_banner?
end

#sticky_header_data(project, merge_request) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'app/helpers/merge_requests_helper.rb', line 300

def sticky_header_data(project, merge_request)
  data = {
    iid: merge_request.iid,
    canResolveDiscussion: merge_request.resolvable_discussions.first&.can_resolve?(current_user).to_s,
    defaultBranchName: project.default_branch,
    projectPath: project.full_path,
    sourceProjectPath: merge_request.source_project_path,
    title: markdown_field(merge_request, :title),
    isFluidLayout: fluid_layout.to_s,
    blocksMerge: project.only_allow_merge_if_all_discussions_are_resolved?.to_s,
    imported: merge_request.imported?.to_s,
    isDraft: merge_request.draft.to_s,
    tabs: [
      [
        'show',
        _('Overview'),
        project_merge_request_path(project, merge_request),
        merge_request.related_notes.user.count
      ],
      ['commits', _('Commits'), commits_project_merge_request_path(project, merge_request), @commits_count],
      ['diffs', _('Changes'), diffs_project_merge_request_path(project, merge_request), @diffs_count]
    ]
  }

  if project.builds_enabled?
    data[:tabs].insert(
      2,
      [
        'pipelines',
        _('Pipelines'),
        pipelines_project_merge_request_path(project, merge_request),
        @number_of_pipelines
      ]
    )
  end

  data
end

#summarize_new_merge_request_disabled_reason(_merge_request) ⇒ Object

Overriden in EE



178
# File 'app/helpers/merge_requests_helper.rb', line 178

def summarize_new_merge_request_disabled_reason(_merge_request); end


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
# File 'app/helpers/merge_requests_helper.rb', line 101

def tab_link_for(merge_request, tab, options = {}, &block)
  data_attrs = {
    action: tab.to_s,
    target: "##{tab}",
    toggle: options.fetch(:force_link, false) ? '' : 'tabvue'
  }

  url = case tab
        when :show
          data_attrs[:target] = '#notes'
          method(:project_merge_request_path)
        when :commits
          method(:commits_project_merge_request_path)
        when :pipelines
          method(:pipelines_project_merge_request_path)
        when :diffs
          method(:diffs_project_merge_request_path)
        when :reports
          method(:reports_project_merge_request_path)
        else
          raise "Cannot create tab #{tab}."
        end

  link_to(url[merge_request.project, merge_request], data: data_attrs, &block)
end

#target_projects(project) ⇒ Object



77
78
79
80
# File 'app/helpers/merge_requests_helper.rb', line 77

def target_projects(project)
  MergeRequestTargetProjectFinder.new(current_user: current_user, source_project: project)
    .execute(include_routes: true)
end